Gyredocs
Depth Practice
API

Gyre/Verification

Discipline contract

In one minuteThe interface a multidisciplinary framework integrates against is itself verified. Forward and reverse products are exact transposes, the linear solves invert them, the products agree with finite differences at the solution and at a point the framework names, a stalled linear solve is never silent, and the OpenMDAO implicit component passes OpenMDAO's own derivative checks.

Written at L2 Practice goes to L3 Mechanics 1565 words Markdown

A design framework never sees the flow solver. It sees a handful of operations (MDO integration): evaluate the residual, apply its linearisation forwards and backwards, solve with it, and return outputs. If one of them is slightly inconsistent with the others, the framework’s coupled derivatives are wrong and no test of the flow solver alone would show it. This study checks the operations against each other.

PassedDiscipline contract for MDO integration15 of 15 checks passed · 249.9 s · quick suite

The interface a multidisciplinary framework integrates against is checked on a small inviscid aerofoil case (NACA 0012, M = 0.5, α = 2°, 64 elements of degree 2). (i) The partial-derivative products of residual and outputs (apply_linear) in forward and reverse mode must be transposes of each other, with respect to the state and to all inputs including the surface displacement field, both at the discipline's solution and at a point named by the caller that is not a solution. (ii) The forward products must agree with central finite differences of the residual (apply_nonlinear) and of the outputs, taken along smooth directions (the numerical flux is only piecewise smooth, so a rough direction would test the finite difference and not the derivative). (iii) solve_linear must invert apply_linear in both modes, and the two modes must be transposes of each other. (iv) The reduced (total) products tangent_product and adjoint_product must be transposes of each other. (v) A linear solve that cannot reach its tolerance must raise, or be flagged when the caller asks for that; and adjoint and direct totals, which solve different linear systems of the same linearisation, must approach each other as the tolerance of those solves is tightened. (vi) Wrapped as an OpenMDAO implicit component, the discipline must pass OpenMDAO's own check of partial derivatives, reproduce the discipline's total derivatives, and, coupled to a linear structure in a block Gauss–Seidel cycle, give a coupled total derivative that agrees with a finite difference of re-converged coupled analyses.

  • flow solve convergedyesexpected truepass
  • apply_linear forward vs reverse: largest relative dot-product defect over both points2.51e-16expected < 1e-11 (round-off)pass
  • solve_linear forward vs reverse: largest relative dot-product defect4.05e-12expected < 1e-8 (two Krylov solves to 1e-11)pass
  • solve_linear inverts apply_linear in both modes: largest relative residual, recomputed with apply_linear9.55e-12expected < 1e-9 (solves to 1e-11; preconditioned residual)pass
  • partials (residual, cl, cd, cm, f_surface) with respect to state and inputs vs central differences: largest relative difference1.15e-08expected < 1e-6 (the bound of the linearization study for JVP vs central differences; smooth directions)pass
  • total products, tangent_product vs adjoint_product: relative dot-product defect6.64e-10expected < 1e-7 (two linear solves to 1e-10)pass
  • a linear solve that misses its tolerance raises LinearSolveError and reports the reduction it achieved1.65e-14expected raised, with 0 < reduction < 1e-10pass
  • with on_failure='flag' the same solve returns with info.convergednoexpected falsepass
  • adjoint and direct totals meet as the linear tolerance tightens: largest relative difference at 1e-8, 1e-10, 1e-122.9e-05 / 1.3e-06 / 5.8e-09expected decreasing, below 1e-7 at 1e-12pass
  • OpenMDAO is installed (extra 'mdo')yesexpected truepass
  • OpenMDAO check_partials of the implicit flow component and the functionals component (forward and reverse vs central differences): largest relative error5.65e-09expected < 1e-6pass
  • OpenMDAO totals through the implicit component vs the discipline's adjoint totals (rel., largest)4.14e-16expected < 1e-6 (linear solves to 1e-10)pass
  • coupled flow–structure adjoint through the implicit component vs finite difference (rel.)1.23e-07expected < 5e-6 (finite-difference step 1e-4)pass
  • coupled totals, forward vs reverse mode (rel.)9.71e-10expected < 1e-6 (linear block Gauss–Seidel to 1e-9)pass
  • the coupling is active: largest deflection [chords]0.005555expected > 1e-5pass

Run notes OpenMDAO 3.45.2. The coupled derivative differs from the rigid one by +0.31 %. Measured in this run: largest dot-product defect of apply_linear 2.5e-16, of solve_linear 4.1e-12, of the total products 6.6e-10; largest difference between partials and central differences 1.2e-08; the solve with an unreachable tolerance stopped at a reduction of 1.6e-14.

gyre 0.4.0 · 39979fcf90 · · cpu · quick suite · record (JSON)Same code as this build

Linear operators of the disciplineDiscipline contract for MDO integration
pointcheckleft side / valueright side / referencerelative difference
solution (the discipline's point)apply_linear: forward vs reverse (dot product)1812.391812.392.5091e-16
solution (the discipline's point)residual partials vs central difference (step 1e-06)44.491644.49161.3197e-09
solution (the discipline's point)partials of cl vs central difference (step 1e-06)0.09192210.09192212.7630e-09
solution (the discipline's point)partials of cd vs central difference (step 1e-06)0.1912440.1912441.2509e-10
solution (the discipline's point)partials of cm vs central difference (step 1e-06)0.01444460.01444468.9697e-09
solution (the discipline's point)partials of f_surface vs central difference (step 1e-06)0.5161430.5161435.4903e-10
solution (the discipline's point)solve_linear fwd: |A x − b| / |b| by apply_linear359.5501e-129.5505e-12
solution (the discipline's point)solve_linear rev: |Aᵀ y − c| / |c| by apply_linear356.3456e-126.3456e-12
solution (the discipline's point)solve_linear: forward vs reverse (dot product)7684.667684.661.3401e-12
named point (perturbed state and inputs)apply_linear: forward vs reverse (dot product)1883.391883.390
named point (perturbed state and inputs)residual partials vs central difference (step 1e-06)50.894150.89411.0737e-09
named point (perturbed state and inputs)partials of cl vs central difference (step 1e-06)0.09434230.09434234.3592e-09
named point (perturbed state and inputs)partials of cd vs central difference (step 1e-06)0.1907310.1907311.8486e-10
named point (perturbed state and inputs)partials of cm vs central difference (step 1e-06)0.01466430.01466431.1538e-08
named point (perturbed state and inputs)partials of f_surface vs central difference (step 1e-06)0.5171760.5171762.2628e-10
named point (perturbed state and inputs)solve_linear fwd: |A x − b| / |b| by apply_linear356.8446e-126.8460e-12
named point (perturbed state and inputs)solve_linear rev: |Aᵀ y − c| / |c| by apply_linear363.7119e-123.7120e-12
named point (perturbed state and inputs)solve_linear: forward vs reverse (dot product)7763.847763.844.0510e-12
solution (the discipline's point)tangent_product vs adjoint_product (dot product)-4.14465-4.144656.6374e-10

gyre 0.4.0 · 39979fcf90 · · cpu · quick suite · record (JSON)Same code as this build

  • Forward versus reverse. For random directions the product of the forward derivative with a reverse seed equals the product of the reverse derivative with the forward direction, to round-off. This holds with respect to the state and to every input, including the surface displacement field and the load field, so a framework may use either mode, or mix them, and get the same coupled derivative.
  • Two points. Every check is made at the discipline’s own converged solution and at a point the caller names that is not a solution (a perturbed state and other inputs). A framework that owns the state, as in a full-space or a block-coupled solve, linearises about its own iterate; the discipline must not assume that iterate is converged.
  • Against finite differences. The forward products agree with central differences of the residual and of the outputs along smooth directions. The numerical flux is only piecewise smooth, so a rough direction would measure the finite difference, not the derivative.
  • The linear solves. The solution returned by solve_linear is put back through apply_linear: the residual of that test is the tolerance asked for, in both modes, and the two modes are transposes of each other.
Adjoint and direct totals against the tolerance of their linear solvesDiscipline contract for MDO integration
linear tolerancederivativeadjointdirectrelative difference
1.0000e-08d cl / d alpha7.518157.518155.2558e-08
1.0000e-08d cl / d mach0.1867090.1867042.8636e-05
1.0000e-10d cl / d alpha7.518157.518151.4219e-09
1.0000e-10d cl / d mach0.1867090.1867091.3386e-06
1.0000e-12d cl / d alpha7.518157.518151.5087e-11
1.0000e-12d cl / d mach0.1867090.1867095.7951e-09

gyre 0.4.0 · 39979fcf90 · · cpu · quick suite · record (JSON)Same code as this build

The adjoint and the direct mode solve different linear systems of the same linearisation. The error each leaves in a total derivative is the residual of its solve multiplied by the solution of the other system: the sensitivity of the state for the adjoint mode, the adjoint times the input derivative of the residual for the direct mode. These factors differ by orders of magnitude between inputs, so at one and the same tolerance the modes reach different accuracies; the table shows them approaching each other as the tolerance tightens. A framework that compares modes should do so at a tolerance tight enough for the comparison it wants, and a failure to reach a tolerance is reported, never absorbed: LinearSolveError by default, a flag in the solve record when the caller asks for that.

OpenMDAO integrationDiscipline contract for MDO integration
quantityvalue
check_partials flow.solver: 4 (of, wrt) pairs, directional3.0315e-09
check_partials flow.functionals: 12 (of, wrt) pairs, directional5.6471e-09
totals through the implicit component (reverse) vs FlowDiscipline.totals4.1434e-16
coupled dcl/dα, OpenMDAO reverse mode7.54117
coupled dcl/dα, OpenMDAO forward mode7.54117
coupled dcl/dα, central difference of re-converged coupled analyses7.54117
relative difference, reverse mode vs finite difference1.2307e-07
dcl/dα of the rigid aerofoil7.51815
largest deflection [chords]0.00555541

gyre 0.4.0 · 39979fcf90 · · cpu · quick suite · record (JSON)Same code as this build

The same discipline wrapped as an OpenMDAO implicit component (adapter) passes OpenMDAO’s check_partials in forward and reverse mode, reproduces the discipline’s own total derivatives through OpenMDAO’s linear solver, and, coupled to a linear structural model in a block Gauss–Seidel cycle, returns a coupled total derivative that agrees with a finite difference of re-converged coupled analyses. The record names the OpenMDAO version it ran with.

    ↑ ↓ moveEnter open[ ] change depthResults show section and depth level