add GVEC as MHD optimizable#481
Conversation
adds a GVEC optimizable class, similar to the VMEC optimizable
* refactor Gvec optimizable to use the run_stages script: allows running GVEC with refinement and current constraint (optimization using picard iterations) * profile objects are now available as iota_profile, pressure_profiel and current_profile, while iota and I_tor are return functions * Gvec init using dictionary of parameters, from_parameter_file classmethod additionally * adapted example parameter file & run script for 1DoF circularCrossSection target Volume
* from_parameters & from_parameter_file classmethods are also available * allow setting iota & current profile afterwards * add default parameters (minimization and radial resolution) * the varyR0_targetVolume example now no longer needs an input file
There was a problem hiding this comment.
Looking very nice! Only major issue is with the use of SurfaceRZFourier as the boundary object, which I believe should be replaced with a SurfaceGVEC or SurfaceRZFourierOnFrame lest users try to access, plot, evaluate, and optimize properties of the boundary directly.
Aditionally, unit tests need to be written to test all the new code. See tests/mhd/vmec.py for a good example to adapt.
This will also involve updating the workflow files to install GVEC.
| ToDo: doc | ||
| """ | ||
|
|
||
| def __init__( |
There was a problem hiding this comment.
In order for the object to be GSONable (to be saved and then loaded again using simsopt methods), all parameters to the __init__ function must be stored either as self.<param> or self._<param>. If you want this feature, parameters needs to be an attribute of self.
src/simsopt/mhd/gvec.py
Outdated
| if f"{key}_mn_max" not in params: | ||
| params[f"{key}_mn_max"] = (boundary.mpol, boundary.ntor) | ||
|
|
||
| if not isinstance(boundary, SurfaceRZFourier): |
There was a problem hiding this comment.
Transformation to SurfaceRZFourier already done above
src/simsopt/mhd/gvec.py
Outdated
| self._state.compute(ds, "V") | ||
| return ds.V.item() | ||
|
|
||
| def aspect(self) -> float: |
There was a problem hiding this comment.
Aspect() should also be a property of the boundary Surface object
|
|
||
| assert np.abs(surf.get_rc(0, 0) - 0.7599088773175) < 1.0e-5 | ||
| assert np.abs(equil.volume() - 0.15) < 1.0e-6 | ||
| assert np.abs(surf.volume() - 0.15) < 1.0e-6 |
There was a problem hiding this comment.
You are evaluating the surfaces' volume, but this is only equal to equil.volume in this case, and is misleading. See other comments on creating a SurfaceGVEC class for representing the surface.
There was a problem hiding this comment.
again only following the VMEC example. But I agree that the current lack of a SurfaceGVEC can be misleading.
* improved handling of parameters: * surface can be specified via the parameters or as an object * profiles can be specified via the parameters, an object or a constant * iota profile is always used, but if current is specified it is only used as the initial guess * removed from_parameters constructor - all features now available in init * add logger property to access the GVEC logger * make paths in the parameterfile absolute when writing parameters for each run
* new argument `keep_gvec_intermediates`: passed to gvec.run with values "all", "stages" or None * new decorator `return_function` to mark all return functions which are then registered with `return_fn_map` * cleaned return functions * vacuum_well is now the vacuum magnetic well depth with the same formual as vmec * removed current & iota return functions that returned arrays as the resolution is not customizable * return functions now use the .state().evaluate(...) * new function `boundary_to_params` & overhaul of `boundary_from_params`: now supports non-stellarator-symmetry * fix current optimization by setting `picard_current` correctly
* Gvec.state is now a property and not a return function * new Gvec.beta_avg return function * new MirrorRatio optimizable based on gvec * new Elongation optimizable based on gvec * new Gvec.from_rundir constructor * Gvec.run_count now starts at 0 * changed Gvec option restart_file -> restart * prototype for restart functionality (wip)
|
I apologize for not updating this in a very long while. |
for SurfaceRZFourier & SurfaceGVECFourier
I have now added a |
|
Nice work! This cleans up the dealing with degrees of freedom. For full integration with simsopt, the SurfaceGvecFourier could be made to inherit from the base For fancy optimization like Rogerio's single-stage, you would want If we do not want to make it a full surface, it should still be its own Optimizable object, but maybe called GVECSurfaceDofs, and live in mhd, as it does not implement any geometry. I urge to implement as a Surface, because that would allow for so many nice things, but I know this is much more work and do not know how easy it is to expose these functions. |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #481 +/- ##
==========================================
- Coverage 90.23% 89.66% -0.57%
==========================================
Files 84 86 +2
Lines 17896 18484 +588
==========================================
+ Hits 16148 16574 +426
- Misses 1748 1910 +162
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
I agree having a proper Surface object would be very nice to have, but exposing these GVEC functions cleanly is not that easy, maybe a re-implementation of the G-Frame (e.g. in JAX) would be faster. It's also not strictly necessary for "normal" stage-1 optimization, so I would really like to postpone this for some later date.
Yes, I'll do that. |
* new gvec parameter file for testing: LandremanPaul2021_QA (converted from vmec input) * added import guard clause for qsc for test_surface_rzfourier
* allows quickly evaluating the root-mean-square * allows targeting straight-fieldline quantities
was previously moved to mhd.gvec_dofs but accidently and should have been deleted
This PR adds an
Optimizable-class for the Galerkin Variational Equilibrium Code (GVEC). GVEC is a flexible 3D ideal MHD equilibrium solver inspired by VMEC with a few notable differences. The two most prominent are:GVEC is developed at the division of Numerical Methods of the Max Planck Institute for Plasma Physics in Garching, Germany. It has recently been released publicly and open source (MIT License).
Details on the implementation of GVEC are partially described in the documentation.
This PR adds a
simsopt.mhd.gvec.Gvecoptimizable, similar to theVmecandSpecoptimizables.phiedge,boundary,pressureandiotaorcurrentprofileleast_squares_mpi_solveis only supported with one MPI process for each GVEC run.iotaor (toroidal)currentprofileiota,iota_axis,volume, etc.GVECQuantityoptimizable can be used to access any of the computable quantities of GVEC.This PR is still work in progress, but we wanted to show our progress as soon as possible. Open ToDo's:
1DOF_circularCrossSection_varyAxis_targetIota_gvec.py1DOF_circularCrossSection_varyR0_targetVolume_gvec.py2DOF_gvecOnly_targetIotaAndVolume.pySurfaceGVECFourierto represent surface DoFs when not using cylindrical coordinatesSurfaceobject, e.g. does not support thegamma()methodLet us know what else you need.