SU2 CFD Solver
Theory: shape-optimisation gradients from one adjoint solve
Overview
OpenFOAM is the well-known open-source CFD code — why choose SU2?
When you want to improve shapes automatically. SU2 came out of Stanford's aerospace design lab; beyond solving the flow, it computes efficiently — by the adjoint method — the gradient that says which way to move the shape to cut drag further. When a wing is parametrised by tens to hundreds of variables, the cost of that gradient decides total run time. OpenFOAM wins on range and flexibility of physics models, but SU2 ships the whole shape-optimisation loop (shape deformation, flow solve, adjoint solve, gradient, shape update) out of the box. Choose by purpose.
Adjoint equations
J is the objective (e.g. drag), α the design variables, U the flow solution, R the residual of the discrete equations and ψ the adjoint variables. Solving the right-hand adjoint equation once gives every gradient via the left-hand formula, however many design variables there are. SU2 implements the discrete adjoint — differentiating the discretised equations directly — by algorithmic differentiation.
A tool born from aerofoil design
Bringing the adjoint method seriously into aerodynamic shape design is credited to Jameson's work from the late 1980s, which solved aerofoil inverse design with the adjoint of the flow equations. SU2 was released in 2012 by a Stanford lab in that lineage, and universities and companies worldwide have since joined its development, extending it to turbulence, multiphysics and multi-stage optimisation.
Worked examples
Example 1: gradient cost (2-hour flow solve, 20 iterations)
| Design variables | Finite difference (per gradient) | Adjoint (per gradient) | Ratio | 20 iterations: FD | 20 iterations: adjoint |
|---|---|---|---|---|---|
| 10 | 22 h | 4.6 h | 5 | 440 h (18 days) | 92 h |
| 50 | 102 h | 4.6 h | 22 | 2,040 h (85 days) | 92 h |
| 200 | 402 h | 4.6 h | 87 | 8,040 h (335 days) | 92 h |
Adjoint cost is assumed to be 1.3 times a flow solve (it varies with problem and settings). Adjoint time does not depend on the number of design variables.
Example 2: first-cell height for a turbulent flat-plate check (air, 50 m/s)
| Position x | Re_x | C_f | u_τ | Height for y⁺=1 | Height for y⁺=30 |
|---|---|---|---|---|---|
| 0.1 m | 3.33×10⁵ | 0.00465 | 2.41 m/s | 6.2 μm | 187 μm |
| 0.5 m | 1.67×10⁶ | 0.00337 | 2.05 m/s | 7.3 μm | 219 μm |
| 1.0 m | 3.33×10⁶ | 0.00294 | 1.92 m/s | 7.8 μm | 235 μm |
Wall-resolved turbulence models (such as the standard SA model) target y⁺ ≈ 1; friction is larger near the leading edge, so the first layer must be thinner there. Compare computed skin friction with the correlation above and check for agreement within a few per cent.
How is the configuration file written?
SU2 puts every setting in one text configuration file (.cfg). For a turbulent flat plate, choose equations and model with SOLVER= RANS and KIND_TURB_MODEL= SA, set flow conditions with MACH_NUMBER and REYNOLDS_NUMBER, an adiabatic wall with MARKER_HEATFLUX= ( wall, 0.0 ) and the far field with MARKER_FAR. The usual numerics are a second-order upwind scheme via CONV_NUM_METHOD_FLOW= ROE and MUSCL_FLOW= YES. For shape optimisation, set MATH_PROBLEM= DISCRETE_ADJOINT and OBJECTIVE_FUNCTION= DRAG, parametrise the shape with free-form-deformation (FFD) control points, and loop flow, adjoint and shape updates with the bundled Python script (shape_optimization.py). Starting from an official tutorial configuration and swapping in your mesh and conditions is the least error-prone route.
Workflow
- Reproduce a similar official tutorial as-is.
- Swap in your mesh and check y⁺ and convergence (residual and drag histories).
- Verify friction and pressure against reference solutions on cases like the flat plate.
- Check adjoint gradients against finite differences on a few variables.
- Parametrise with FFD, add constraints (thickness, lift) and run the optimisation.
“An optimisation whose gradients didn't match”
In optimising a duct's pressure loss, the objective refused to fall however many iterations ran. Comparing adjoint gradients with finite differences for two design variables showed not even the signs agreed. The flow solves had been passed to the adjoint before converging adequately. Tightening convergence to four orders of residual reduction, including the turbulence equation, brought gradients within 1% of finite differences, and loss began dropping within a few iterations.
Common mistakes
Mistakes and fixes
| Mistake | Effect | Fix |
|---|---|---|
| Under-converged flow | Wrong gradients | Converge residuals deeply |
| Unchecked gradients | Optimisation stalls | Compare with finite differences |
| Not checking y⁺ | Wrong friction drag | Size first layer from y⁺ |
| No constraints | Unrealistically thin shapes | Thickness and lift constraints |
| FFD box not enclosing the shape | No or broken deformation | Check box placement |
I'd like to learn related topics.
Related pages include OpenFOAM introduction, Elmer multiphysics, Spalart-Allmaras model, sensitivity analysis and inflation layers.
Related Topics
Experience the theory firsthand with the interactive simulator for this field
All Simulators