Design variables in Jetstream can take on many forms, e.g. AoA, section shape, planform variables, etc., which can often have drastically different magnitudes. Ideally, all variables and gradients would be of similar magnitudes to aid optimizer convergence. To facilitate this scaling, we can scale the variables (and by extension the gradients) before they are given to SNOPT.
This scaling is done as
X = X' / V
where X are the scaled variables seem by SNOPT, X' are the unscaled variables (such as the axial control point perturbations seen by Jetstream), and V is a vector of scaling variables. This also implies a scaling of the gradients computed by Jetstream, as
dJ/dX = dJ/dX' * dX'/dX
= dJ/dX' * V
where dJ/dX' is the gradient of the function, J, computed by Jetstream and dJ/dX is the scaled version seen by SNOPT. The effect of this is to effectively increase the sensitivity of the problem to variable i when V_i > 1, and decrease it when V_i < 1.
Jetstream has a few built-in scaling methods. The method is chosen with the input parameter jtstrm%scldv_type = <int>. For jtstrm%scldv_type = 0, no scaling is used. Other built-in types include:
1: Scale by the initial value, with a safegaurd of V_i = 1 if X_i = 0.
2: Scale by the square root of the initial value, with the same safegaurd as type 1.
3: Scale the AoA variable only to make it the same order as the geometric variables.
4: Scale each different type of variable by a different value based on input. Predefined scaling types include jtstrm%geo_scale, %aoa_scale, %mach_scale, %cg_scale, %flap_scale, %struct_scale.
5: Scale by the initial value of the gradient. This requires an additional flow and adjoint solve. This method may not work anymore. Recommend using method 6 instead.
6: Scale based on an V vector contained in a VarScling.txt file. See the source code for the format of this file.
7: Scale the geometric variables by the square root of their initial value.
8: Scale by the square root of the variable range.
9: Scale by the norm of X.
All of these scalings are calculated in optimizer/Optimizer_Mod.f90 in the subroutine calcScaling(). If you want to add your own scaling method, just add to this subroutine. So long as Xscl(:) is set here, its application for scaling will be handled throughout automatically throughout the code.
Over the years, multiple internal studies (see the BASc thesis here) have looked at the impact of scaling to try and determine an optimal scaling for common problems. However, the studies have always been inconclusive, with no one scaling being appropriate for all problems. For problems with a large number and type of design variables (e.g. wing design) scaling hasn't generally proved beneficial. For problems with a smaller number or type of design variables (e.g. just sweep and AoA), scaling tends to have a larger impact, or at least its impact is easier to understand, thus making an appropriate selection of a scaling possible. Such a selection is generally made after it is overserved that the optimizer is only changing one type of design variable, e.g. sweep, and leaving the other, e.g. AoA, unchanged.