Setup Guide: Shape Optimization with the Discrete Adjoint

Draft. These settings are drawn from SU2 source, tutorials and regression cases. Recommendations marked (to be reviewed) still need an experienced user’s review.

Use this guide to choose settings and understand their consequences. Follow the linked Tutorials for worked examples and consult V&V for numerical and physical comparisons. Example settings are starting points, not evidence that a case is converged or validated.

The documentation guide explains the source tags used below: (code), (test case), (tutorial), (docs), (advice) and (to be reviewed).



When to use this guide

Use this guide to change the shape of a body or a duct so that an output of the flow improves: for example less drag at a fixed lift, or a lower pressure drop.

SU2 computes the gradient of the output with respect to the shape parameters with the adjoint method: one adjoint solve gives the sensitivity of one scalar output to all shape parameters. Its cost does not grow by one flow solve per parameter, but runtime and memory depend on the solver, convergence and recording strategy.

SU2 has two adjoint solvers:

  • The discrete adjoint differentiates the SU2 code itself with algorithmic differentiation (AD). Its gradient matches the discretized flow equations, including turbulence models and most boundary conditions. This guide focuses on it.
  • The continuous adjoint solves separate adjoint equations derived by hand. It runs with the normal build, but supports fewer cases.

In this guide, the (code) tag also covers the Python scripts of SU2.

Start from

The block below comes from the test case multiple_ffd/naca0012. It is an inviscid NACA 0012 airfoil with two FFD boxes, one on each side. The regression tests run it with discrete_adjoint.py.

  • We removed the comments, the continuous adjoint options, the options that have no effect in this setup, and most file names.
  • We added GEO_MARKER and GEO_DESCRIPTION from optimization_euler/steady_naca0012, because the thickness constraint needs SU2_GEO.
  • The mesh mesh_NACA0012_multiFFD.su2 already contains the FFD boxes. It is in the TestCases repository.
SOLVER= EULER
MATH_PROBLEM= DIRECT
RESTART_SOL= NO
READ_BINARY_RESTART= NO
%
MACH_NUMBER= 0.8
AOA= 1.25
FREESTREAM_PRESSURE= 101325.0
FREESTREAM_TEMPERATURE= 288.15
REF_ORIGIN_MOMENT_X= 0.25
REF_ORIGIN_MOMENT_Y= 0.00
REF_ORIGIN_MOMENT_Z= 0.00
REF_LENGTH= 1.0
REF_AREA= 1.0
REF_DIMENSIONALIZATION= FREESTREAM_PRESS_EQ_ONE
%
MARKER_EULER= ( airfoil_upper, airfoil_lower )
MARKER_FAR= ( farfield )
MARKER_PLOTTING= ( airfoil_upper, airfoil_lower )
MARKER_MONITORING= ( airfoil_upper, airfoil_lower )
%
NUM_METHOD_GRAD= GREEN_GAUSS
CFL_NUMBER= 5.0
LINEAR_SOLVER= FGMRES
LINEAR_SOLVER_PREC= ILU
LINEAR_SOLVER_ERROR= 1E-1
LINEAR_SOLVER_ITER= 3
MGLEVEL= 3
MGCYCLE= V_CYCLE
MG_PRE_SMOOTH= ( 2, 2, 2, 2 )
MG_POST_SMOOTH= ( 2, 2, 2, 2 )
MG_CORRECTION_SMOOTH= ( 1, 1, 1, 1 )
MG_DAMP_RESTRICTION= 0.5
MG_DAMP_PROLONGATION= 0.5
CONV_NUM_METHOD_FLOW= JST
JST_SENSOR_COEFF= ( 0.5, 0.02 )
TIME_DISCRE_FLOW= EULER_IMPLICIT
%
OBJECTIVE_FUNCTION= DRAG
%
% The test stops after 10 iterations. A useful gradient needs a converged
% flow and adjoint solution: raise ITER.
ITER= 10
CONV_RESIDUAL_MINVAL= -9
CONV_STARTITER= 10
%
DV_KIND= FFD_SETTING
DV_MARKER= ( airfoil_upper, airfoil_lower )
DV_PARAM= ( UPPER, 1, 0, 0, 0.0, 1.0, 0.0 )
DV_VALUE= 0.001
DEFORM_LINEAR_SOLVER_ITER= 500
DEFORM_NONLINEAR_ITER= 1
DEFORM_CONSOLE_OUTPUT= YES
DEFORM_LINEAR_SOLVER_ERROR= 1E-14
DEFORM_STIFFNESS_TYPE= INVERSE_VOLUME
%
FFD_TOLERANCE= 1E-10
FFD_ITERATIONS= 500
FFD_DEFINITION= ( LOWER, 0.075, -0.075, 0.0, 0.625, -0.075, 0.0, 0.625, -0.02, 0.0, 0.075, -0.02, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ); ( UPPER, 0.075, 0.02, 0.0, 0.625, 0.02, 0.0, 0.625, 0.075, 0.0, 0.075, 0.075, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 )
FFD_DEGREE= ( 4, 1, 0 ); ( 4, 1, 0 )
FFD_CONTINUITY= USER_INPUT
FFD_FIX_I= (0,4)
FFD_FIX_J= (15)
FFD_FIX_K= (15)
%
GEO_MARKER= ( airfoil_upper, airfoil_lower )
GEO_DESCRIPTION= AIRFOIL
%
MESH_FILENAME= mesh_NACA0012_multiFFD.su2
MESH_FORMAT= SU2
HISTORY_OUTPUT= (ITER, RMS_RES, AERO_COEFF)
OUTPUT_FILES= (RESTART_ASCII)
%
OPT_OBJECTIVE= DRAG * 0.001
OPT_CONSTRAINT= ( LIFT > 0.327 ) * 0.001; ( MOMENT_Z > 0.0 ) * 0.001; ( AIRFOIL_THICKNESS > 0.12 ) * 0.001
OPT_ITERATIONS= 1
OPT_ACCURACY= 1E-6
OPT_BOUND_UPPER= 0.1
OPT_BOUND_LOWER= -0.1
% This test uses the 3D kind 11 (FFD_CONTROL_POINT) on a 2D mesh.
% The 2D tutorials use kind 19 (FFD_CONTROL_POINT_2D).
DEFINITION_DV= ( 11, 1.0 | airfoil_upper | UPPER, 1, 0, 0, 0.0, 1.0, 0.0 ); ( 11, 1.0 | airfoil_lower | LOWER, 1, 0, 0, 0.0, 1.0, 0.0 )

Run the gradient only:

discrete_adjoint.py -f inv_NACA0012_ffd.cfg

Run an optimization (raise OPT_ITERATIONS first):

shape_optimization.py -g DISCRETE_ADJOINT -f inv_NACA0012_ffd.cfg

For a RANS case, start from the RAE 2822 tutorial or the test case optimization_rans/steady_rae2822. For a 3D wing, start from the ONERA M6 tutorial.

Settings that matter

Build SU2 with AD

  • Configure with ./meson.py setup build -Denable-autodiff=true (code). See Build SU2 on Linux/MacOS.
  • This build gives the AD programs SU2_CFD_AD and SU2_DOT_AD, next to the normal SU2_CFD, SU2_DEF, SU2_DOT and SU2_GEO (tutorial). The optimization loop needs all of them.
  • SU2_CFD stops with “MATH_PROBLEM= DISCRETE_ADJOINT requires AD support” if you give it a discrete adjoint config (code). Use SU2_CFD_AD for the adjoint run.
  • The Python scripts need NumPy and SciPy (tutorial).
  • The CoolProp fluid models cannot be used with the AD build (code).
  • To check gradients with forward-mode AD, also build with -Denable-directdiff=true (code).

Discrete or continuous adjoint

  • MATH_PROBLEM takes DIRECT, CONTINUOUS_ADJOINT or DISCRETE_ADJOINT (code).
  • With the Python scripts, keep MATH_PROBLEM= DIRECT in your file. The scripts set the adjoint value themselves, from the gradient method you choose on the command line (code).
  • To run by hand: run SU2_CFD for the flow, and copy the restart file to the name in SOLUTION_FILENAME. Then run SU2_CFD_AD with MATH_PROBLEM= DISCRETE_ADJOINT. Then run SU2_DOT_AD, which turns the surface sensitivities into the gradient for the design variables (tutorial, to be reviewed: check the file names against the scripts).
  • The discrete adjoint uses the numerical settings of the flow solver. It ignores the continuous adjoint options, such as CONV_NUM_METHOD_ADJFLOW, ADJ_JST_SENSOR_COEFF, CFL_REDUCTION_ADJFLOW and LIMIT_ADJFLOW (tutorial). INCONSISTENT_DISC= YES (default NO) makes the discrete adjoint use the adjoint scheme options CONV_NUM_METHOD_ADJFLOW and ADJ_JST_SENSOR_COEFF instead (code). The tutorial text calls this switch INCONSISTENT_AD.
  • FROZEN_VISC_DISC (default NO) freezes the turbulence model in the adjoint. FROZEN_LIMITER_DISC (default NO) freezes the slope limiter (code). These differentiate a frozen model or limiter rather than the fully coupled, recomputed residual. For a gradient comparison, make the derivative definition and frozen settings agree on both sides; otherwise disagreement is expected (advice).
  • QUASI_NEWTON_NUM_SAMPLES above 1 adds a quasi-Newton correction to the adjoint iterations. The default is 0 (off) (code). It can speed up the adjoint convergence (to be reviewed).

Objective function

  • OBJECTIVE_FUNCTION sets the output to differentiate. MARKER_MONITORING sets the surfaces where SU2 evaluates it (code). Examples of values: DRAG, LIFT, MOMENT_Z, EFFICIENCY, TOTAL_HEATFLUX, SURFACE_TOTAL_PRESSURE, SURFACE_PRESSURE_DROP, SURFACE_UNIFORMITY, TOTAL_PRESSURE_LOSS, ENTROPY_GENERATION, CUSTOM_OBJFUNC (code). The full list is on the option reference page.
  • The SURFACE_* objectives use the markers in MARKER_ANALYZE. List the same marker in MARKER_MONITORING too (tutorial).
  • Weighted sum. Give several objectives separated by commas, with OBJECTIVE_WEIGHT and MARKER_MONITORING in the same order (code). See the multi-objective tutorial.
  • Custom expression. With OBJECTIVE_FUNCTION= CUSTOM_OBJFUNC, CUSTOM_OBJFUNC holds a formula of history outputs, for example 'DRAG + 10 * pow(fmax(0.4-LIFT, 0), 2)' (code).
  • In the Python scripts, OPT_OBJECTIVE sets the objective and its scale, for example DRAG * 0.001 (tutorial). Separate several objectives with semicolons. With OPT_COMBINE_OBJECTIVE= YES, SU2 solves one adjoint for the weighted sum, instead of one per objective (tutorial).
  • Fixed lift. To minimize drag at a given lift, use FIXED_CL_MODE= YES with TARGET_CL: the flow solver then changes the angle of attack. The adjoint gives the drag gradient at fixed lift, so you need no lift constraint and no extra adjoint for it (tutorial).

Constraints

  • OPT_CONSTRAINT lists constraints separated by semicolons, in the form ( NAME > value ) * scale, with >, < or = (tutorial).
  • Each flow constraint (for example LIFT) needs its own adjoint solution (tutorial).
  • Geometric constraints come from SU2_GEO: AIRFOIL_THICKNESS for airfoils, STATION1_THICKNESS, STATION2_THICKNESS, … for wings (tutorial). Set GEO_MARKER, GEO_DESCRIPTION (AIRFOIL, WING, FUSELAGE or NACELLE) and, for wings, GEO_LOCATION_STATIONS and GEO_BOUNDS (code, tutorial). Run SU2_GEO once on the baseline to check the values (tutorial).
  • Penalty. You can also write a constraint inside OPT_OBJECTIVE, for example (DRAG = 0.05)*1E6. SU2 then adds a quadratic penalty when the constraint is violated (tutorial).
  • The scale of each constraint sets how strongly the optimizer reacts when the constraint is violated. The tutorials use 0.001 (tutorial).

Design variables

DEFINITION_DV lists the design variables for the Python scripts. Each one has the form ( kind, scale | markers | parameters ). Separate them with semicolons, with no semicolon after the last one (tutorial). The kind is a number (code):

Number Kind Parameters
1 TRANSLATION x, y, z
11 FFD_CONTROL_POINT box tag, i, j, k, x, y, z direction
14 FFD_CAMBER box tag, i, j
15 FFD_TWIST box tag, j, axis end points
16 FFD_THICKNESS box tag, i, j
19 FFD_CONTROL_POINT_2D box tag, i, j, x, y direction
20 FFD_CAMBER_2D box tag, i
21 FFD_THICKNESS_2D box tag, i
30 HICKS_HENNE lower (0) or upper (1) side, x position on a unit chord
34 CST see the test case deformation/cst
35 SURFACE_BUMP x start, x end, x location of the bump
101 ANGLE_OF_ATTACK 1.0

These points come from the tutorials (tutorial):

  • Hicks-Henne bumps (kind 30) are simple for 2D airfoils. FFD control points (kinds 11 and 19) work for any shape, in 2D and 3D.
  • set_ffd_design_var.py writes the DEFINITION_DV list for all control points of a box, for example set_ffd_design_var.py -i 10 -j 8 -k 1 -b WING -m 'UPPER_SIDE, LOWER_SIDE, TIP'. Add --dimension 2 in 2D. Remove the points that should not move.
  • DV_KIND, DV_MARKER, DV_PARAM and DV_VALUE define one deformation for SU2_DEF alone, for example to test a mesh deformation by hand.

FFD boxes

FFD (free-form deformation) puts a box of control points around the surface. Moving a control point bends the surface inside the box smoothly (tutorial).

  • FFD_DEFINITION = (tag, then the 8 corner points x, y, z) in 3D. In 2D, give 4 corners with z = 0, and fill the other 12 values with zeros (tutorial). Start at the corner with the lowest x, y, z. Go along x, then along y, then to the remaining corner of that face. In 3D, repeat for the top face (tutorial).
  • FFD_DEGREE = (i, j, k) degrees. The box has degree + 1 control points in each direction. In 2D, use (i, j, 0) (tutorial).
  • Several boxes: separate them with semicolons in FFD_DEFINITION and FFD_DEGREE (test case).
  • FFD_CONTINUITY keeps the surface smooth where it leaves the box: 2ND_DERIVATIVE (default), 1ST_DERIVATIVE, NO_DERIVATIVE, or USER_INPUT (code). With USER_INPUT, you choose the fixed planes of control points with FFD_FIX_I, FFD_FIX_J and FFD_FIX_K. A plane index larger than the degree fixes nothing (tutorial, test case).
  • Other options: FFD_BLENDING (BEZIER default, or BSPLINE_UNIFORM with FFD_BSPLINE_ORDER), FFD_COORD_SYSTEM (CARTESIAN default, CYLINDRICAL, SPHERICAL, POLAR, with FFD_AXIS), FFD_SYMMETRY_PLANE (default NO) (code).
  • FFD_TOLERANCE (default 1E-10) and FFD_ITERATIONS (default 500) control how SU2 finds the position of each surface point inside the box (code).
  • FFD_INTPREV= YES (default NO) checks the box for self-intersection after a deformation. If SU2 finds one, it reduces the deformation step by step (FFD_INTPREV_ITER, default 10; FFD_INTPREV_DEPTH, default 3) (code).

To add the boxes to your mesh (tutorial):

  1. Set DV_KIND= FFD_SETTING, DV_PARAM= ( 1.0 ) and DV_MARKER to the surfaces to deform.
  2. Run SU2_DEF config.cfg.
  3. SU2_DEF writes the mesh with the boxes to the file in MESH_OUT_FILENAME (default mesh_out). Use that file as MESH_FILENAME from now on.

The box moves only the surface points that lie inside it (tutorial). Make the box enclose the whole region that should change (advice).

Mesh deformation

After the surface moves, SU2_DEF moves the volume mesh by treating it as an elastic solid (tutorial).

  • DEFORM_STIFFNESS_TYPE: WALL_DISTANCE (default), INVERSE_VOLUME or CONSTANT_STIFFNESS (code). WALL_DISTANCE stiffens elements near a wall; INVERSE_VOLUME stiffens small elements wherever they occur. These can help preserve boundary-layer cells, but do not guarantee positive volumes (code, advice).
  • DEFORM_LINEAR_SOLVER (default FGMRES), DEFORM_LINEAR_SOLVER_PREC (default ILU), DEFORM_LINEAR_SOLVER_ITER (default 1000), DEFORM_LINEAR_SOLVER_ERROR (default 1E-14) (code).
  • DEFORM_NONLINEAR_ITER (default 1) splits the deformation into this many smaller steps (code). More steps help with large deformations (advice, to be reviewed).
  • DEFORM_LIMIT (default 1E6) deforms only the cells closer to the wall than this distance (code).
  • With the default legacy SU2_DEF path (DEFORM_MESH= NO), CLinearElasticity uses DEFORM_COEFF as its Poisson ratio. The parser default is 1E6, outside the physical isotropic-elastic interval −1 < ν < 0.5; do not interpret that default as a material recommendation. The species transport tutorial sets 0.0. With DEFORM_MESH= YES, SU2_DEF instead uses CMeshSolver, whose Poisson ratio is DEFORM_POISSONS_RATIO (default 0.3). These options belong to different deformation paths (code).
  • DEFORM_KIND= RBF uses radial basis functions instead of the elastic solid (default ELASTIC) (code). See the test case deformation/naca0012 (test case).
  • Boundaries that are not in DV_MARKER stay fixed. Points on MARKER_SYM boundaries can slide in their plane. If a separate deformation configuration uses MARKER_SYM to allow a planar end boundary to slide, retain the actual inlet/outlet conditions in the flow configuration. Changing a flow outlet into a symmetry boundary changes the physical problem (advice).
  • HOLD_GRID_FIXED= YES with HOLD_GRID_FIXED_COORD keeps the mesh outside a box fixed (code).
  • Set DEFORM_CONSOLE_OUTPUT= YES to see the minimum cell volume after each step (code).

DEFORM_MESH also selects the newer mesh-solver path in SU2_DEF; it is not exclusive to SU2_CFD. In a flow run, use DEFORM_MESH and MARKER_DEFORM_MESH for deforming moving boundaries. The Python shape-optimization workflow calls SU2_DEF (code).

Python scripts

All scripts are in SU2_PY. They take the config file with -f and the number of MPI ranks with -n (code). See also Execution.

  • shape_optimization.py: the full loop of flow, adjoint, gradient, deformation and optimizer (tutorial). Its arguments (code):
    • -g: the gradient method, DISCRETE_ADJOINT (default), CONTINUOUS_ADJOINT, FINDIFF or NONE.
    • -o: the optimizer from SciPy, SLSQP (default), CG, BFGS or POWELL.
    • -q: quiet mode, default True.
    • Each design is written to DESIGNS/DSN_001, DSN_002, … The history of the optimization is in the history_project file (tutorial).
  • discrete_adjoint.py: one flow solution, one adjoint solution and the gradient. -m adj reuses an existing flow solution; -m grad reuses both solutions (code).
  • continuous_adjoint.py: the same with the continuous adjoint (code).
  • finite_differences.py: the gradient by finite differences, with one flow solution per design variable (code).
  • set_ffd_design_var.py: writes DEFINITION_DV lists for FFD boxes (tutorial).

Optimizer settings (tutorial):

  • OPT_ITERATIONS, OPT_ACCURACY: the maximum number of iterations and the requested accuracy.
  • OPT_BOUND_UPPER, OPT_BOUND_LOWER: the bounds of each design variable. The script divides them by OPT_RELAX_FACTOR before it passes them to the optimizer (code).
  • OPT_GRADIENT_FACTOR: scales objective and gradient. The tutorials aim at a gradient norm near 1E-6 for SLSQP (the GNORM column of the optimizer output).
  • OPT_RELAX_FACTOR: scales the first step. Check the size of the first deformation in DESIGNS/DSN_002/DEFORM/log_Deform.out (the Max Diff line in the ONERA M6 tutorial).
  • OPT_LINE_SEARCH_BOUND (default 1E6) bounds the line search in SU2_DEF (code).

FADO. The tutorials Species Transport and Turbulent 3D pipe bend use FADO, a separate Python framework, instead of shape_optimization.py (tutorial). FADO gives more control over the steps and over the optimizer. The Species Transport tutorial shows a full workflow: restart check, FFD setup, mesh deformation test, gradient check, optimization (tutorial).

Check convergence and results

Converge the flow first. The adjoint linearizes the flow around the current solution. A poorly converged flow gives a wrong gradient (advice). Set CONV_RESIDUAL_MINVAL low, and check that the objective no longer changes.

Converge the adjoint. With the compressible solver, the adjoint run stops on RMS_ADJ_DENSITY by default (code). Watch it, and the sensitivity outputs (SENS_GEO, SENS_AOA, SENS_MACH) in the adjoint history (code). The sensitivities should settle to steady values (advice).

Check the restart. Before a gradient check, verify that a flow restart and an adjoint restart reproduce the residuals of a continuous run. The Species Transport tutorial shows a script for this (tutorial).

Check the gradient against finite differences before you optimize (tutorial):

  1. Run discrete_adjoint.py -f config.cfg. The gradient is in a file named after GRAD_OBJFUNC_FILENAME (default of_grad) plus a short name of the objective, for example of_grad_cd.csv for DRAG. The extension follows TABULAR_FORMAT (code).
  2. Run finite_differences.py -f config.cfg. The gradient is in of_grad_findiff, with the same extension. The step comes from FIN_DIFF_STEP; the script uses 0.001 when the option is missing. The template suggests 0.001 times REF_LENGTH (code).
  3. Compare the two files, design variable by design variable. Signs and orders of magnitude must agree. Try two or three step sizes: a step that is too large adds truncation error, and a step that is too small adds noise from the incomplete convergence (advice).

discrete_adjoint.py accepts -v True, but the forward-mode AD calculation and comparison report in discrete_design are commented out in this version. That flag does not validate the gradient. Use the finite-difference workflow above; a forward-mode comparison needs a separately verified driver (code).

Check each new design. Look at the deformed meshes in DESIGNS/DSN_*/DEFORM, the flow solutions in DESIGNS/DSN_*/DIRECT, and the history in history_project (tutorial).

Common problems

Symptom Likely cause What to try
SU2 stops: “MATH_PROBLEM= DISCRETE_ADJOINT requires AD support”. The adjoint config was given to SU2_CFD (code). Use SU2_CFD_AD, or let the Python scripts call it. Build with -Denable-autodiff=true.
The gradient differs from finite differences. The flow or the adjoint is not converged; the finite difference step is too large or too small; the turbulence or the limiter is frozen (advice). Converge both deeper. Try several FIN_DIFF_STEP values. Set FROZEN_VISC_DISC= NO and FROZEN_LIMITER_DISC= NO.
The adjoint diverges or stalls. The flow solution oscillates (limiter, shock, separation), so the adjoint iterations have no steady solution to converge to (advice, to be reviewed). Converge the flow deeper. Freeze the limiter in the flow with LIMITER_ITER. Try FROZEN_LIMITER_DISC= YES or QUASI_NEWTON_NUM_SAMPLES (to be reviewed).
The flow does not converge on a new design. The step was too large, or the shape became unphysical (advice). Lower OPT_RELAX_FACTOR or the bounds. Restart the optimization from its project file with -r (to be reviewed).
SU2_DEF reports: “There are N elements with negative volume”. The deformation is too large for the mesh (code). Lower the step (OPT_RELAX_FACTOR, bounds). Raise DEFORM_NONLINEAR_ITER. Try another DEFORM_STIFFNESS_TYPE or DEFORM_KIND= RBF. FFD_INTPREV= YES checks FFD-box intersections; it does not guarantee a valid volume mesh (code, advice).
The mesh is torn at an outlet or a side boundary. That boundary is fixed while its neighbour moves (tutorial). Allow planar sliding in a separate deformation configuration where appropriate; preserve the physical inlet/outlet types in the flow configuration.
Kinks at the edge of the FFD box. Control points on the box faces move (tutorial). Use FFD_CONTINUITY= 2ND_DERIVATIVE, or fix the outer planes with FFD_FIX_I, FFD_FIX_J, FFD_FIX_K.
Part of the surface does not move. It lies outside the FFD box (tutorial). Enlarge the box and run the FFD_SETTING step again.
The FFD point inversion does not converge. The box is badly shaped, or points sit near its faces (advice, to be reviewed). Raise FFD_ITERATIONS. Make the box larger and closer to a regular hexahedron.
The optimizer stops after one step. The gradient norm is far from the scale that the optimizer expects (tutorial). Change OPT_GRADIENT_FACTOR so that GNORM is near 1E-6.
The thickness constraint has no value. GEO_MARKER or GEO_DESCRIPTION is missing (test case). Set them, and run SU2_GEO on the baseline.

Tutorials:

Test cases (SU2 repository):

User guide pages: Build SU2 on Linux/MacOS, Execution, Advanced AD Techniques, Solver Setup, Setup Guide: Turbomachinery.

Source review: 22 October 2026, against SU2 docs_site at 41ea6a219a. See the review scope and outstanding validation. Setup recommendations remain draft where indicated.



Improve this page