User story
As a stellarator-optimization user, I get VMEC++'s plasma-boundary-shape gradient at a cost independent of the number of boundary DOFs: one linear Hessian solve instead of one equilibrium re-solve per DOF.
Scope
examples/vmecpp_adjoint.py: partition the state into interior and boundary, converge the interior, then one adjoint solve H_II^T lambda = dJ/dx_I (GMRES preconditioned by M^-1) gives the full boundary gradient.
examples/simsopt_vmec_gradient.py: a SIMSOPT Optimizable wrapping it.
Benefit
25x to 263x fewer force evaluations than finite-differencing over the boundary, growing with DOF count. Depends on the gradient and preconditioner exposures (#577, #579) and the exact HVP (#582).
Closes when #581 merges.
User story
As a stellarator-optimization user, I get VMEC++'s plasma-boundary-shape gradient at a cost independent of the number of boundary DOFs: one linear Hessian solve instead of one equilibrium re-solve per DOF.
Scope
examples/vmecpp_adjoint.py: partition the state into interior and boundary, converge the interior, then one adjoint solveH_II^T lambda = dJ/dx_I(GMRES preconditioned byM^-1) gives the full boundary gradient.examples/simsopt_vmec_gradient.py: a SIMSOPTOptimizablewrapping it.Benefit
25x to 263x fewer force evaluations than finite-differencing over the boundary, growing with DOF count. Depends on the gradient and preconditioner exposures (#577, #579) and the exact HVP (#582).
Closes when #581 merges.