diff --git a/README.rst b/README.rst index 17706f083b..329b0fba38 100644 --- a/README.rst +++ b/README.rst @@ -9,61 +9,84 @@ Stellarator Optimization Package |Docs| |UnitTests| |RegressionTests| |Codecov| -DESC solves for and optimizes 3D MHD equilibria using pseudo-spectral numerical methods and automatic differentiation. +DESC solves for and optimizes 3D MHD equilibria using pseudo-spectral numerical methods +and automatic differentiation. + +The theoretical approach and implementation details used by DESC are presented in the +following papers and documented at Theory_. Please cite our work if you use DESC! + +- Dudt, D. & Kolemen, E. (2020). DESC: A Stellarator Equilibrium Solver. + [`Physics of Plasmas `__] + [`pdf `__] +- Panici, D. et al (2023). The DESC Stellarator Code Suite Part I: Quick and accurate equilibria computations. + [`Journal of Plasma Physics `__] + [`pdf `__] +- Conlin, R. et al. (2023). The DESC Stellarator Code Suite Part II: Perturbation and continuation methods. + [`Journal of Plasma Physics `__] + [`pdf `__] +- Dudt, D. et al. (2023). The DESC Stellarator Code Suite Part III: Quasi-symmetry optimization. + [`Journal of Plasma Physics `__] + [`pdf `__] -The theoretical approach and implementation details used by DESC are presented in these papers [1]_ [2]_ [3]_ [4]_ and documented at Theory_. -Please cite our work if you use DESC! - -.. [1] Dudt, D. & Kolemen, E. (2020). DESC: A Stellarator Equilibrium Solver. [`Physics of Plasmas `__] [`pdf `__] -.. [2] Panici, D. et al (2023). The DESC Stellarator Code Suite Part I: Quick and accurate equilibria computations. [`JPP `__] [`pdf `__] -.. [3] Conlin, R. et al. (2023). The DESC Stellarator Code Suite Part II: Perturbation and continuation methods. [`JPP `__] [`pdf `__] -.. [4] Dudt, D. et al. (2023). The DESC Stellarator Code Suite Part III: Quasi-symmetry optimization. [`JPP `__] [`pdf `__] .. _Theory: https://desc-docs.readthedocs.io/en/latest/theory_general.html Quick Start =========== -.. role:: console(code) - :language: console - -The easiest way to install DESC is from pypi: :console:`pip install desc-opt` +The easiest way to install DESC is from PyPI: ``pip install desc-opt`` For more detailed instructions on installing DESC and its dependencies, see Installation_. -The code is run using the syntax :console:`desc ` and the full list of command line options are given in `Command Line Interface`_. (Note that you may have to prepend the command with :console:`python -m`) -DESC can be ran in two ways: +The best place to start learning about DESC is our tutorials: -The first is through an input file specifying the equilibrium and solver options, this way can also can also accept VMEC input files. +- `Basic fixed boundary equilibrium`_: running from a VMEC input, creating an equilibrium from scratch +- `Advanced equilibrium`_: continuation and perturbation methods. +- `Free boundary equilibrium`_: vacuum and or finite beta with external field. +- `Using DESC outputs`_: analysis, plotting, saving to VMEC format. +- `Basic optimization`_: specifying objectives, fixing degrees of freedom. +- `Advanced optimization`_: advanced constraints, precise quasi-symmetry, constrained optimization. +- `Near axis constraints`_: loading solutions from QSC/QIC and fixing near axis expansion. -The second is through a python script, where the equilibrium and solver options are specified programmatically, this method offers much more flexibility over what types of equilibrium solution, optimization and analysis can be performed. -See the tutorial `Script Interface`_ for more detailed information. +For details on the various objectives, constraints, optimizable objects and more, see +the full `api documentation`_. -Refer to `Inputs`_ for documentation on how to format the input file. -The equilibrium solution is output in a HDF5 binary file, whose format is detailed in `Outputs`_. +If all you need is an equilibrium solution, the simplest method is through the command +line by giving an input file specifying the equilibrium and solver options, this +way can also can also accept VMEC input files. -As an example usage of the input file method, to use DESC to solve for the equilibrium of the high-beta, D-shaped plasma described with the DSHAPE input file, the command from the :console:`DESC` directory is -:console:`desc -p desc/examples/DSHAPE`, where the :console:`-p` flag tells DESC to plot the results once it finishes. +The code is run using the syntax ``desc `` and the full list +of command line options are given in `Command Line Interface`_. (Note that you may have +to prepend the command with ``python -m``) -An example of the script usage to solve and optimize an equilibrium, refer to the python script `desc/examples/precise_QA.py`, which can be run from the :console:`DESC` directory from the command line with :console:`python3 desc/examples/precise_QA.py` +Refer to `Inputs`_ for documentation on how to format the input file. + +The equilibrium solution is output in a HDF5 binary file, whose format is detailed in `Outputs`_. .. _Installation: https://desc-docs.readthedocs.io/en/latest/installation.html .. _Command Line Interface: https://desc-docs.readthedocs.io/en/latest/command_line.html .. _Inputs: https://desc-docs.readthedocs.io/en/latest/input.html .. _Outputs: https://desc-docs.readthedocs.io/en/latest/output.html -.. _Script Interface: https://desc-docs.readthedocs.io/en/latest/notebooks/tutorials/02_Script_Interface.html +.. _Basic fixed boundary equilibrium: https://desc-docs.readthedocs.io/en/latest/notebooks/tutorials/basic_equilibrium.html +.. _Advanced equilibrium: https://desc-docs.readthedocs.io/en/latest/notebooks/tutorials/advanced_equilibrium_continuation.html +.. _Free boundary equilibrium: https://desc-docs.readthedocs.io/en/latest/notebooks/tutorials/free_boundary_equilibrium.html +.. _Using DESC outputs: https://desc-docs.readthedocs.io/en/latest/notebooks/tutorials/use_outputs.html +.. _Basic optimization: https://desc-docs.readthedocs.io/en/latest/notebooks/tutorials/basic_optimization.html +.. _Advanced optimization: https://desc-docs.readthedocs.io/en/latest/notebooks/tutorials/advanced_optimization.html +.. _Near axis constraints: https://desc-docs.readthedocs.io/en/latest/notebooks/tutorials/nae_constraint.html +.. _api documentation: https://desc-docs.readthedocs.io/en/latest/api.html Repository Contents =================== - desc_ contains the source code including the main script and supplemental files. Refer to the API_ documentation for details on all of the available functions and classes. - docs_ contains the documentation files. -- examples_ contains example input files along with corresponding DESC solutions, which are also accessible using the `desc.examples.get` function. - tests_ contains routines for automatic testing. +- publications_ contains PDFs of publications by the DESC group, as well as scripts and data to reproduce the results of these papers. .. _desc: https://github.com/PlasmaControl/DESC/tree/master/desc .. _docs: https://github.com/PlasmaControl/DESC/tree/master/docs -.. _examples: https://github.com/PlasmaControl/DESC/tree/master/desc/examples .. _tests: https://github.com/PlasmaControl/DESC/tree/master/tests +.. _publications: https://github.com/PlasmaControl/DESC/tree/master/publications .. _API: https://desc-docs.readthedocs.io/en/latest/api.html Contribute diff --git a/desc/magnetic_fields/_current_potential.py b/desc/magnetic_fields/_current_potential.py index e42e329703..d728cd50cd 100644 --- a/desc/magnetic_fields/_current_potential.py +++ b/desc/magnetic_fields/_current_potential.py @@ -16,14 +16,14 @@ class CurrentPotentialField(_MagneticField, FourierRZToroidalSurface): """Magnetic field due to a surface current potential on a toroidal surface. - surface current K is assumed given by - K = n x ∇ Φ - where: - n is the winding surface unit normal. - Phi is the current potential function, - which is a function of theta and zeta. - This function then uses biot-savart to find the - B field from this current density K on the surface. + Surface current K is assumed given by K = n x ∇ Φ + where: + + - n is the winding surface unit normal. + - Phi is the current potential function, which is a function of theta and zeta. + + This function then uses biot-savart to find the B field from this current + density K on the surface. Parameters ---------- @@ -159,7 +159,7 @@ def potential_dzeta(self, new): def save(self, file_name, file_format=None, file_mode="w"): """Save the object. - **Not supported for this object! + **Not supported for this object!** Parameters ---------- @@ -275,19 +275,21 @@ class FourierCurrentPotentialField( ): """Magnetic field due to a surface current potential on a toroidal surface. - surface current K is assumed given by + Surface current K is assumed given by + + K = n x ∇ Φ + + Φ(θ,ζ) = Φₛᵥ(θ,ζ) + Gζ/2π + Iθ/2π + + where: - K = n x ∇ Φ - Φ(θ,ζ) = Φₛᵥ(θ,ζ) + Gζ/2π + Iθ/2π + - n is the winding surface unit normal. + - Phi is the current potential function, which is a function of theta and zeta, + and is given as a secular linear term in theta/zeta and a double Fourier + series in theta/zeta. - where: - n is the winding surface unit normal. - Phi is the current potential function, - which is a function of theta and zeta, - and is given as a secular linear term in theta/zeta - and a double Fourier series in theta/zeta. - This function then uses biot-savart to find the - B field from this current density K on the surface. + This function then uses biot-savart to find the B field from this current + density K on the surface. Parameters ---------- diff --git a/docs/Makefile b/docs/Makefile index d35b67aa6c..b09f1dc1c8 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -18,9 +18,23 @@ variables.csv: optimizers.csv: python write_optimizers.py +clean: +# generated by sphinx + rm -rf _build/ + rm -rf _api/ +# generated by us + rm -f desc*.csv + rm -f optimizers.csv + rm -f variables.csv + rm -f variables.rst + .PHONY: help Makefile variables.csv optimizers.csv # Catch-all target: route all unknown targets to Sphinx using the new # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). %: Makefile variables.csv optimizers.csv @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + rm -f desc*.csv + rm -f optimizers.csv + rm -f variables.csv + rm -f variables.rst diff --git a/docs/api.rst b/docs/api.rst index 2d14391b21..1375a4c307 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -1,6 +1,6 @@ -================= -API Documentation -================= +==================== +Alphabetical Listing +==================== Basis ***** @@ -123,7 +123,6 @@ IO :recursive: :template: class.rst - desc.io.InputReader desc.io.load Magnetic Fields @@ -134,6 +133,8 @@ Magnetic Fields :recursive: :template: class.rst + desc.magnetic_fields.CurrentPotentialField + desc.magnetic_fields.FourierCurrentPotentialField desc.magnetic_fields.ScaledMagneticField desc.magnetic_fields.SumMagneticField desc.magnetic_fields.ToroidalMagneticField @@ -188,6 +189,7 @@ Objective Functions desc.objectives.GoodCoordinates desc.objectives.HelicalForceBalance desc.objectives.Isodynamicity + desc.objectives.LinearObjectiveFromUser desc.objectives.MagneticWell desc.objectives.MeanCurvature desc.objectives.MercierStability diff --git a/docs/api_continuation.rst b/docs/api_continuation.rst new file mode 100644 index 0000000000..34df787333 --- /dev/null +++ b/docs/api_continuation.rst @@ -0,0 +1,31 @@ +====================== +Solving and Perturbing +====================== + +Continuation +************ +``desc.continuation`` contains the methods used for solving equilibrium problems. +``solve_continuation_automatic`` is usually the easiest method, users desiring more +control over the process can also use ``solve_continuation``. + +.. autosummary:: + :toctree: _api/continuation + :recursive: + + desc.continuation.solve_continuation_automatic + desc.continuation.solve_continuation + + +Perturbations +************* +``desc.perturbations.perturb`` is used inside of the continuation methods but can +also be used alone to perform sensitivity analysis or perform parameter scans. +``optimal_perturb`` is effectively a single step of a constrained optimization solver. + +.. autosummary:: + :toctree: _api/perturbations + :recursive: + + desc.perturbations.perturb + desc.perturbations.optimal_perturb + desc.perturbations.get_deltas diff --git a/docs/api_equilibrium.rst b/docs/api_equilibrium.rst new file mode 100644 index 0000000000..2adc6296c8 --- /dev/null +++ b/docs/api_equilibrium.rst @@ -0,0 +1,69 @@ +========================================== +Equilibrium, Surfaces, and Profile classes +========================================== + + +Equilibrium +*********** +The ``Equilibrium`` is the core class representing an MHD equilibrium configuration. +An ``EquilibriaFamily`` is a ``list`` like object for storing multiple equilibria. + +.. autosummary:: + :toctree: _api/equilibrium + :recursive: + :template: class.rst + + desc.equilibrium.Equilibrium + desc.equilibrium.EquilibriaFamily + + +Geometry +******** +The ``desc.geometry`` module contains important classes such as ``FourierRZToroidalSurface`` +for representing the shape of the plasma boundary, as well as classes for representing +the magnetic axis, cross section, and various space curves. + +.. autosummary:: + :toctree: _api/geometry/ + :recursive: + :template: class.rst + + desc.geometry.FourierRZToroidalSurface + desc.geometry.FourierRZCurve + desc.geometry.FourierXYZCurve + desc.geometry.FourierPlanarCurve + desc.geometry.SplineXYZCurve + desc.geometry.ZernikeRZToroidalSection + + +Profiles +******** +``desc.profiles`` contains objects representing 1-D flux functions such as pressure, +current, rotational transform, temperature, or density. It is also possible to combine +profiles together by addition, multiplication, or scaling. + +.. autosummary:: + :toctree: _api/profiles + :recursive: + :template: class.rst + + desc.profiles.PowerSeriesProfile + desc.profiles.SplineProfile + desc.profiles.MTanhProfile + desc.profiles.ScaledProfile + desc.profiles.SumProfile + desc.profiles.ProductProfile + + +Utilities +********* +``desc.compat`` has utility functions for enforcing sign conventions or rescaling +equilibria to a given size and/or field strength. + +.. autosummary:: + :toctree: _api/compat + :recursive: + + desc.compat.ensure_positive_jacobian + desc.compat.flip_helicity + desc.compat.rescale diff --git a/docs/api_fields.rst b/docs/api_fields.rst new file mode 100644 index 0000000000..7e183117e8 --- /dev/null +++ b/docs/api_fields.rst @@ -0,0 +1,98 @@ +========================= +Magnetic Fields and Coils +========================= + +There are a number of ways for representing arbitrary magnetic fields in the lab +(:math:`R, \phi, Z`) frame. Their common characteristic is a ``compute_magnetic_field`` +method allowing evaluation of :math:`\mathbf{B}` at points in space. + +Magnetic Fields +*************** +The ``desc.magnetic_fields`` module contains classes representing a number of standard +field configurations, as well as classes for combining and scaling these fields. +For interfacing with MAKEGRID type files, the ``SplineMagneticField`` class has a +``from_mgrid`` option allowing you to load an mgrid file and interpolate where needed. +All `MagneticField` objects also have a `save_mgrid` method to save field data so that +it can be read by VMEC and STELLOPT. They also have a `compute_Bnormal` method which accepts +a surface and computes the normal field strength on that surface. + +.. autosummary:: + :toctree: _api/magnetic_fields + :recursive: + :template: class.rst + + desc.magnetic_fields.SplineMagneticField + desc.magnetic_fields.DommaschkPotentialField + desc.magnetic_fields.ScalarPotentialField + desc.magnetic_fields.ToroidalMagneticField + desc.magnetic_fields.VerticalMagneticField + desc.magnetic_fields.PoloidalMagneticField + desc.magnetic_fields.ScaledMagneticField + desc.magnetic_fields.SumMagneticField + +There are also classes for representing a current potential on a winding surface: + +.. autosummary:: + :toctree: _api/magnetic_fields + :recursive: + :template: class.rst + + desc.magnetic_fields.CurrentPotentialField + desc.magnetic_fields.FourierCurrentPotentialField + + +For analyzing the structure of magnetic fields, it is often useful to find the trajectories +of magnetic field lines, which can be done via ``desc.magnetic_fields.field_line_integrate``. + +.. autosummary:: + :toctree: _api/magnetic_fields + :recursive: + :template: class.rst + + desc.magnetic_fields.field_line_integrate + +``desc.magnetic_fields`` also contains a utility function for reading output files from +the BNORM code: + +.. autosummary:: + :toctree: _api/magnetic_fields + :recursive: + :template: class.rst + + desc.magnetic_fields.read_BNORM_file + + + +Coils +***** +``Coil`` objects in ``desc.coils`` are themselves subclasses of ``MagneticField``, allowing +them to be used anywhere that expects a magnetic field type. There are a number of parameterizations +based on the ``Curve`` classes defined in ``desc.geometry`` (which, since they are based on ``Curve`` +classes, can also use the same ``Curve`` conversion methods to convert between coil representations): + +.. autosummary:: + :toctree: _api/coils/ + :recursive: + :template: class.rst + + desc.coils.FourierRZCoil + desc.coils.FourierXYZCoil + desc.coils.FourierPlanarCoil + desc.coils.SplineXYZCoil + +There are also objects for holding a collection of coils with efficient methods for +evaluating the combined field. A ``CoilSet`` must consist of members with the same +parameterization, while a ``MixedCoilSet`` can contain arbitrary types (including +another ``CoilSet``). + +.. autosummary:: + :toctree: _api/coils/ + :recursive: + :template: class.rst + + desc.coils.CoilSet + desc.coils.MixedCoilSet + +DESC ``CoilSet`` or ``MixedCoilSet`` objects can also be created from MAKEGRID-formatted coil text files via +the `from_makegrid_coilfile` method. They can also be saved in a MAKEGRID-formatted text file with +the `save_in_makegrid_format` method. diff --git a/docs/api_io.rst b/docs/api_io.rst new file mode 100644 index 0000000000..ba71d8bbfd --- /dev/null +++ b/docs/api_io.rst @@ -0,0 +1,45 @@ +================== +Saving and Loading +================== + + +IO +*** +Nearly all objects in DESC have an ``object.save`` method to save the object as either +an HDF5 (``.h5``) or Pickle ``.pkl`` format. The function ``desc.io.load`` can then +be used to load a saved object and all of its data. + +.. autosummary:: + :toctree: _api/io/ + :recursive: + :template: class.rst + + desc.io.load + + +Examples +******** +The ``desc.examples`` module contains a number of pre-computed equilibrium solutions to +well known configurations or benchmark problems. + +.. autosummary:: + :toctree: _api/examples + :recursive: + + desc.examples.get + desc.examples.listall + + +VMEC +**** +The ``desc.vmec.VMECIO`` class has a number of methods for interacting with VMEC +equilibria, such as loading a VMEC solution and converting to a DESC ``Equilibrium``, +saving a DESC solution in the VMEC ``wout_*.nc`` format, and plotting comparisons +between solutions. + +.. autosummary:: + :toctree: _api/vmec/ + :recursive: + :template: class.rst + + desc.vmec.VMECIO diff --git a/docs/api_objectives.rst b/docs/api_objectives.rst new file mode 100644 index 0000000000..124d367669 --- /dev/null +++ b/docs/api_objectives.rst @@ -0,0 +1,223 @@ +================================= +Objectives, Optimizers, and Grids +================================= + +Objectives and Constraints +************************** +``desc.objectives`` defines a number of different metrics for stellarator optimization +problems, which can be used as either objectives or constraints depending on how they +are passed to the optimizer. Individual objectives are combined into an ``ObjectiveFunction`` +that is then passed to the ``Optimizer``. + + +ObjectiveFunction +----------------- +.. autosummary:: + :toctree: _api/objectives + :recursive: + :template: class.rst + + desc.objectives.ObjectiveFunction + + +Equilibrium +----------- +.. autosummary:: + :toctree: _api/objectives + :recursive: + :template: class.rst + + desc.objectives.ForceBalance + desc.objectives.ForceBalanceAnisotropic + desc.objectives.Energy + desc.objectives.CurrentDensity + desc.objectives.RadialForceBalance + desc.objectives.HelicalForceBalance + + +Geometry +-------- +.. autosummary:: + :toctree: _api/objectives + :recursive: + :template: class.rst + + desc.objectives.AspectRatio + desc.objectives.Elongation + desc.objectives.Volume + desc.objectives.MeanCurvature + desc.objectives.PrincipalCurvature + desc.objectives.PlasmaVesselDistance + desc.objectives.BScaleLength + desc.objectives.GoodCoordinates + + +Omnigenity +---------- +.. autosummary:: + :toctree: _api/objectives + :recursive: + :template: class.rst + + desc.objectives.QuasisymmetryTwoTerm + desc.objectives.QuasisymmetryTripleProduct + desc.objectives.QuasisymmetryBoozer + desc.objectives.Isodynamicity + + +Stability +--------- +.. autosummary:: + :toctree: _api/objectives + :recursive: + :template: class.rst + + desc.objectives.MagneticWell + desc.objectives.MercierStability + + +Free boundary / Single stage optimization +----------------------------------------- +.. autosummary:: + :toctree: _api/objectives + :recursive: + :template: class.rst + + desc.objectives.BoundaryError + desc.objectives.VacuumBoundaryError + + +Profiles +-------- +.. autosummary:: + :toctree: _api/objectives + :recursive: + :template: class.rst + + desc.objectives.RotationalTransform + desc.objectives.Shear + desc.objectives.ToroidalCurrent + desc.objectives.Pressure + desc.objectives.BootstrapRedlConsistency + + +Fixing degrees of freedom +------------------------- +.. autosummary:: + :toctree: _api/objectives + :recursive: + :template: class.rst + + desc.objectives.FixBoundaryR + desc.objectives.FixBoundaryZ + desc.objectives.FixAxisR + desc.objectives.FixAxisZ + desc.objectives.FixPsi + desc.objectives.FixPressure + desc.objectives.FixIota + desc.objectives.FixCurrent + desc.objectives.FixAtomicNumber + desc.objectives.FixElectronDensity + desc.objectives.FixElectronTemperature + desc.objectives.FixIonTemperature + desc.objectives.FixModeR + desc.objectives.FixModeZ + desc.objectives.FixSumModesR + desc.objectives.FixSumModesZ + desc.objectives.FixThetaSFL + desc.objectives.FixParameter + + +User defined objectives +----------------------- +.. autosummary:: + :toctree: _api/objectives + :recursive: + :template: class.rst + + + desc.objectives.GenericObjective + desc.objectives.ObjectiveFromUser + desc.objectives.LinearObjectiveFromUser + + +Utilities for getting common groups of constraints +-------------------------------------------------- +.. autosummary:: + :toctree: _api/objectives + :recursive: + :template: class.rst + + desc.objectives.get_fixed_boundary_constraints + desc.objectives.get_NAE_constraints + desc.objectives.get_fixed_axis_constraints + desc.objectives.get_equilibrium_objective + + +Optimization +************ +``desc.optimize.Optimizer`` is the primary interface, it contains wrappers for a number +of different methods listed in `Optimizers Supported `_. + +.. autosummary:: + :toctree: _api/optimize + :recursive: + :template: class.rst + + desc.optimize.Optimizer + +There are also a number of optimizers written specifically for DESC that we also offer +with a direct interface similar to ``scipy.optimize.minimize``: + +.. autosummary:: + :toctree: _api/optimize + :recursive: + :template: class.rst + + desc.optimize.lsqtr + desc.optimize.fmintr + desc.optimize.fmin_auglag + desc.optimize.lsq_auglag + desc.optimize.sgd + +DESC also allows you to use custom optimizers by creating a wrapper function and +registering it using ``desc.optimize.register_optimizer``. See `Adding optimizers `_ +for details + +.. autosummary:: + :toctree: _api/optimize + :recursive: + :template: class.rst + + desc.optimize.register_optimizer + + +Grids +***** +A grid defines a set of collocation nodes in computational coordinates where physics +quantities are to be evaluated. DESC offers a number of options with different patterns +and spacing. Each objective generally has a default grid that works for most cases, but +often it is desired to specify where particular objectives should be targeted, such as +targeting quasi-symmetry on particular surfaces. For this a user defined grid can be +created and passed to the corresponding objective. + +.. autosummary:: + :toctree: _api/grid/ + :recursive: + :template: class.rst + + desc.grid.Grid + desc.grid.LinearGrid + desc.grid.QuadratureGrid + desc.grid.ConcentricGrid + +``desc.grid`` also contains utilities for finding the most and least rational surfaces +for a given iota profile, for either avoiding or analyzing rational surfaces. + +.. autosummary:: + :toctree: _api/grid/ + :recursive: + :template: class.rst + + desc.grid.find_least_rational_surfaces + desc.grid.find_most_rational_surfaces diff --git a/docs/api_plotting.rst b/docs/api_plotting.rst new file mode 100644 index 0000000000..f104735ad6 --- /dev/null +++ b/docs/api_plotting.rst @@ -0,0 +1,72 @@ +======== +Plotting +======== + +There are a number of functions for plotting data from an ``Equilibrium`` or other DESC +object in the ``desc.plotting`` module. All functions apart from 3-D methods are based on +Matplotlib, and can plot to specified ``matplotlib.axes.Axes`` objects, or generate their own. +``plot_3d`` and ``plot_coils`` use the Plotly backend which can rotate/pan/zoom to see more detail. + +1-D Line Plots +-------------- +.. autosummary:: + :toctree: _api/plotting + :recursive: + + desc.plotting.plot_1d + desc.plotting.plot_fsa + + +Plotting Flux Surfaces +---------------------- +.. autosummary:: + :toctree: _api/plotting + :recursive: + + desc.plotting.plot_surfaces + desc.plotting.plot_comparison + desc.plotting.plot_boundary + desc.plotting.plot_boundaries + + +Contour Plots of 2-D data +------------------------- +.. autosummary:: + :toctree: _api/plotting + :recursive: + + desc.plotting.plot_2d + desc.plotting.plot_section + + +3-D Plotting +------------ +.. autosummary:: + :toctree: _api/plotting + :recursive: + + desc.plotting.plot_3d + desc.plotting.plot_coils + + +Specialized Plots for QS Metrics +-------------------------------- +.. autosummary:: + :toctree: _api/plotting + :recursive: + + desc.plotting.plot_boozer_surface + desc.plotting.plot_boozer_modes + desc.plotting.plot_qs_error + + +Misc Plotting Utilities +----------------------- +.. autosummary:: + :toctree: _api/plotting + :recursive: + + desc.plotting.plot_coefficients + desc.plotting.plot_basis + desc.plotting.plot_grid + desc.plotting.plot_logo diff --git a/docs/binary_output_format.rst b/docs/binary_output_format.rst index 2b1099dcea..847220740b 100644 --- a/docs/binary_output_format.rst +++ b/docs/binary_output_format.rst @@ -1,10 +1,21 @@ -By default, DESC saves to in the hdf5 self-describing binary format [1]_, [2]_ (".h5" file extension). The file contains all information necessary to reconstruct the python object that was saved. The file structure will depend slightly upon which object was saved (all objects in DESC have a ``save`` method), but generally all objects will contain the following fields: +By default, DESC saves to the hdf5 self-describing binary format [1]_, [2]_ +(".h5" file extension). The file contains all information necessary to reconstruct +the python object that was saved. The file structure will depend slightly upon which +object was saved (all objects in DESC have a ``save`` method), but generally all +objects will contain the following fields: - ``__class__`` : name of the python class of the object - ``__version__`` : which version of DESC created the file -Other fields in the hdf5 file will depend on the type of object, with each attribute of the python object being stored as a data field in the hdf5 file (specifically, all attributes listed in a classes ``_io_attrs_`` property). These may be nested objects, such as an EquilibriaFamily that has the attribute ``_equilibria`` which is a list containing the individual equilibria in the family, and is then indexed by number, for example ``../_equilibria/0``, or an Equilibrium which contains objects for the pressure and iota profiles and spectral bases for R, Z and :math:`\lambda` -In general, all names in the hdf5 file will mirror the python attributes, but with a leading underscore. For example, ``eq.R_lmn`` will be stored as ``../_R_lmn``. +Other fields in the hdf5 file will depend on the type of object, with each attribute +of the python object being stored as a data field in the hdf5 file (specifically, +all attributes listed in a classes ``_io_attrs_`` property). These may be nested +objects, such as an EquilibriaFamily that has the attribute ``_equilibria`` which is +a list containing the individual equilibria in the family, and is then indexed by +number, for example ``../_equilibria/0``, or an Equilibrium which contains objects +for the pressure and iota profiles and spectral bases for R, Z and :math:`\lambda`. +In general, all names in the hdf5 file will mirror the python attributes, but with a +leading underscore. For example, ``eq.R_lmn`` will be stored as ``../_R_lmn``. Below are some examples of common data items and where to find them within a saved Equilibrium: @@ -43,11 +54,19 @@ Below are some examples of common data items and where to find them within a sav - ``/_surface/_R_basis/_modes`` - ``/_surface/_Z_basis/_modes`` -A saved hdf5 file can be loaded by with ``desc.io.load``, and it will return a reconstruction of the object(s) saved within. Some data may not be saved (fields not in ``_io_attrs_``), generally things that require large amounts of memory but are trivially recomputable (i.e., transform matrices). +A saved hdf5 file can be loaded with ``desc.io.load``, and it will return a +reconstruction of the object(s) saved within. Some data may not be saved (fields not +in ``_io_attrs_``), generally things that require large amounts of memory but are +trivially recomputable (i.e., transform matrices). -DESC also has the option of saving to pythons standard binary format, known as ``pickle`` [3]_ (".pkl" file extension). The internal structure of this is somewhat more complicated than hdf5 and is meant only for saving and loading data between python environments. +DESC also has the option of saving to python's standard binary format, known as +``pickle`` [3]_ (".pkl" file extension). The internal structure of this is somewhat +more complicated than hdf5 and is meant only for saving and loading data between +python environments. -The developers strive to maintain backwards and forwards compatibility with saved data, so that equilibria computed in an older version of the code can be loaded in a newer version and vice versa, but we make no guarantees at this time. +The developers strive to maintain backwards and forwards compatibility with saved data, +so that equilibria computed in an older version of the code can be loaded in a newer +version and vice versa, but we make no guarantees at this time. .. [1] https://portal.hdfgroup.org/display/HDF5/HDF5 .. [2] https://docs.h5py.org/en/stable/index.html diff --git a/docs/index.rst b/docs/index.rst index 4474c61c40..b5accd84ac 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -16,20 +16,11 @@ variables optimizers -.. toctree:: - :maxdepth: 1 - :caption: Getting Started - - installation - command_line - input - output - .. toctree:: :maxdepth: 1 :caption: Tutorials - + installation notebooks/tutorials/basic_equilibrium.ipynb notebooks/tutorials/advanced_equilibrium_continuation.ipynb notebooks/tutorials/continuation_step_by_step.ipynb @@ -40,6 +31,28 @@ notebooks/tutorials/nae_constraint.ipynb notebooks/tutorials/bootstrap_current.ipynb +.. toctree:: + :maxdepth: 1 + :caption: Public API + + api_equilibrium + api_objectives + api_io + api_plotting + api_continuation + api_fields + api + + +.. toctree:: + :maxdepth: 1 + :caption: Command Line Interface and I/O + + command_line + input + output + + .. toctree:: :maxdepth: 1 :caption: Developer guides @@ -49,11 +62,6 @@ adding_optimizers notebooks/dev_guide/grid.ipynb -.. toctree:: - :maxdepth: 1 - :caption: Public API - - api Indices and tables diff --git a/docs/notebooks/tutorials/advanced_equilibrium_continuation.ipynb b/docs/notebooks/tutorials/advanced_equilibrium_continuation.ipynb index c1ecfae48e..6fafbcb642 100644 --- a/docs/notebooks/tutorials/advanced_equilibrium_continuation.ipynb +++ b/docs/notebooks/tutorials/advanced_equilibrium_continuation.ipynb @@ -109,7 +109,7 @@ "id": "a4f25167-62df-406b-b577-3731a40be234", "metadata": {}, "source": [ - "### Continuation Method\n", + "## Continuation Method\n", "\n", "- `pres_ratio` (float): Multiplier on the pressure profile. Default = `1.0`.\n", "- `bdry_ratio` (float): Multiplier on the 3D boundary modes. Default = `1.0`.\n", @@ -147,7 +147,7 @@ } }, "source": [ - "#### Without 3-step continuation method\n", + "### Without 3-step continuation method\n", "```\n", "# global parameters \n", "sym = 1 \n", @@ -209,7 +209,7 @@ } }, "source": [ - "#### With 3-step continuation method\n", + "### With 3-step continuation method\n", "```\n", "# global parameters \n", "sym = 1 \n", @@ -271,7 +271,7 @@ } }, "source": [ - "#### Auto generated input\n", + "### Auto generated input\n", "When automatically converting the VMEC input file, DESC only lists the desired final resolutions, which then will trigger the automatic multi-grid continuation method, which is conservative but very robust." ] }, @@ -344,7 +344,7 @@ } }, "source": [ - "#### Loading the results\n", + "## Loading the results\n", "\n", "DESC provides utility functions to load and compare equilibria. These will be covered in detail later in the tutorial. For now, notice that DESC saves solutions as `EquilibriaFamily` objects. An `EquilibriaFamily` is essentially a list of equilibria, which can be indexed to retrieve individual equilibria. Higher indices hold equilibria solved later in the continuation process. You can retrieve the final state of a DESC equilibrium solve with `eq = desc.io.load(\"XXX_output.h5\")[-1]`." ] @@ -441,7 +441,7 @@ } }, "source": [ - "#### Flux surface comparison" + "### Flux surface comparison" ] }, { @@ -483,7 +483,7 @@ } }, "source": [ - "#### Force error comparison" + "## Force error comparison" ] }, { @@ -527,13 +527,21 @@ } }, "source": [ - "#### Analysis\n", + "### Analysis\n", "While the continuation method took a bit longer to run, it yielded a solution with slightly lower normalized force error across the volume as compared to the solution without the continuation method. For strongly shaped equilibria, using the continuation method usually gives _significantly_ better solutions in _less_ time, as well as being extremely robust.\n", "\n", "The force error is still relatively high, this is because we are using a relatively low resolution just to showcase the code functionality. The force error decreases when solved with higher resolution.\n", "\n", "For a more realistic example of using the continuation method to solve a complicated equilibrium, see the [NCSX example input file](https://github.com/PlasmaControl/DESC/blob/master/examples/DESC/NCSX)." ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b230c4ee-c3b0-485e-b3aa-6f42f7e73587", + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { diff --git a/docs/notebooks/tutorials/advanced_optimization.ipynb b/docs/notebooks/tutorials/advanced_optimization.ipynb index a278819af3..30c98b8eb5 100644 --- a/docs/notebooks/tutorials/advanced_optimization.ipynb +++ b/docs/notebooks/tutorials/advanced_optimization.ipynb @@ -70,6 +70,14 @@ "from desc.optimize import Optimizer" ] }, + { + "cell_type": "markdown", + "id": "880591f4-af49-48b1-9b63-f6e8dfd83add", + "metadata": {}, + "source": [ + "## Initial Guess" + ] + }, { "cell_type": "markdown", "id": "6be5cd56-e3e3-4229-b030-5fb9a80e7625", @@ -1220,7 +1228,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.10" + "version": "3.10.11" } }, "nbformat": 4, diff --git a/docs/notebooks/tutorials/basic_equilibrium.ipynb b/docs/notebooks/tutorials/basic_equilibrium.ipynb index ac2399484a..6e6d22b990 100644 --- a/docs/notebooks/tutorials/basic_equilibrium.ipynb +++ b/docs/notebooks/tutorials/basic_equilibrium.ipynb @@ -37,9 +37,11 @@ "cell_type": "markdown", "id": "657f6a8a-d0f0-4f85-acd4-e39c43946a24", "metadata": { + "jp-MarkdownHeadingCollapsed": true, "pycharm": { "name": "#%% md\n" - } + }, + "tags": [] }, "source": [ "## Installing DESC" @@ -164,7 +166,7 @@ } }, "source": [ - "#### Loading the results\n", + "## Loading the results\n", "\n", "DESC provides utility functions to load and compare equilibria. These will be covered in detail later in the tutorial. For now, notice that DESC saves solutions as `EquilibriaFamily` objects. An `EquilibriaFamily` is essentially a list of equilibria, which can be indexed to retrieve individual equilibria. Higher indices hold equilibria solved later in the continuation process. You can retrieve the final state of a DESC equilibrium solve with `eq = desc.io.load(\"XXX_output.h5\")[-1]`." ] diff --git a/docs/notebooks/tutorials/basic_optimization.ipynb b/docs/notebooks/tutorials/basic_optimization.ipynb index 1dd93a3746..43a183098e 100644 --- a/docs/notebooks/tutorials/basic_optimization.ipynb +++ b/docs/notebooks/tutorials/basic_optimization.ipynb @@ -126,6 +126,14 @@ ")" ] }, + { + "cell_type": "markdown", + "id": "41d83a4b-8e55-4be3-b57f-54b023c4f6dd", + "metadata": {}, + "source": [ + "## Initial guess" + ] + }, { "cell_type": "markdown", "id": "db2bd33c", @@ -272,6 +280,8 @@ } }, "source": [ + "## QS metrics\n", + "\n", "The last plot shows the three different QS errors implemented in DESC. Their definitions and the normalized scalar quantities plotted for each flux surface are shown below: \n", "\n", "### Boozer Coordinates\n", @@ -323,6 +333,14 @@ "\\end{equation}" ] }, + { + "cell_type": "markdown", + "id": "6a342471-7bc9-4763-b80e-3de96cdd0496", + "metadata": {}, + "source": [ + "## Optimizer" + ] + }, { "cell_type": "markdown", "id": "3348ce72", @@ -350,6 +368,14 @@ "optimizer = Optimizer(\"proximal-lsq-exact\")" ] }, + { + "cell_type": "markdown", + "id": "9315ebf6-438f-4a13-a27a-947842f28ca9", + "metadata": {}, + "source": [ + "## Specifying constraints" + ] + }, { "cell_type": "markdown", "id": "8a74cacf", @@ -435,7 +461,7 @@ } }, "source": [ - "## Triple Product QS in Volume" + "## Optimizing for Triple Product QS in Volume" ] }, { @@ -728,7 +754,7 @@ } }, "source": [ - "## Two-Term QH at Boundary Surface" + "## Optimizing for Two-Term QH at Boundary Surface" ] }, { diff --git a/docs/notebooks/tutorials/nae_constraint.ipynb b/docs/notebooks/tutorials/nae_constraint.ipynb index b3418cdafb..20dc5fcb94 100644 --- a/docs/notebooks/tutorials/nae_constraint.ipynb +++ b/docs/notebooks/tutorials/nae_constraint.ipynb @@ -125,7 +125,7 @@ "# r is the finite radius to evaluate the NAE surfaces at, this will\n", "# roughly set the aspect ratio of the resulting solution.\n", "# However if this is too large, the surfaces from the NAE may become\n", - "# self-intersecting! The r at which this occurs varies for different NAE \n", + "# self-intersecting! The r at which this occurs varies for different NAE\n", "# solutions, r=0.35 was found to be a reasonable radius for precise QA\n", "r = 0.35\n", "desc_eq = Equilibrium.from_near_axis(\n", @@ -510,6 +510,14 @@ ");" ] }, + { + "cell_type": "markdown", + "id": "6ec6f1e1-a0a6-46c6-80dc-0a347febd5c8", + "metadata": {}, + "source": [ + "## Comparing near axis behavior" + ] + }, { "cell_type": "markdown", "id": "e660fc9b-020a-43ec-b47b-cfc9314e2deb", @@ -625,7 +633,9 @@ " labels=[\"Fixed NAE\"],\n", ")\n", "ax.legend()\n", - "ax.set_ylabel(\"$f_B$\",fontsize=16) # f_B = sqrt(sum(symmetry-breaking modes**2)) / sqrt(sum(all modes**2))" + "ax.set_ylabel(\n", + " \"$f_B$\", fontsize=16\n", + ") # f_B = sqrt(sum(symmetry-breaking modes**2)) / sqrt(sum(all modes**2))" ] }, { @@ -666,11 +676,13 @@ "from desc.plotting import plot_fsa\n", "\n", "rho = np.linspace(0, 1e-1)\n", - "fig, ax, iota_nae = plot_fsa(eq_NAE, \"iota\", rho=rho, return_data=True, lw=6,linecolor=\"g\")\n", + "fig, ax, iota_nae = plot_fsa(\n", + " eq_NAE, \"iota\", rho=rho, return_data=True, lw=6, linecolor=\"g\"\n", + ")\n", "fig, ax, iota_surf = plot_fsa(\n", " desc_eq, \"iota\", rho=rho, ax=ax, return_data=True, linecolor=\"r\", lw=3\n", ")\n", - "plt.plot(rho, np.ones(np.size(rho)) * qsc_eq.iota, linestyle=\"--\", lw=3,c=\"b\")\n", + "plt.plot(rho, np.ones(np.size(rho)) * qsc_eq.iota, linestyle=\"--\", lw=3, c=\"b\")\n", "plt.legend([\"Fixed NAE\", \"Fixed boundary\", \"NAE\"])\n", "print(\n", " \"Relative error in the rotational transform (fixed NAE): \",\n", @@ -718,9 +730,9 @@ "data_nae = eq_NAE.compute([\"|B|\"], grid=grid)\n", "phi = grid.nodes[:, 2]\n", "\n", - "plt.plot(phi, data_surf[\"|B|\"], lw=3,c=\"r\")\n", - "plt.plot(phi, data_nae[\"|B|\"], lw=6,c=\"g\")\n", - "plt.plot(phi, np.ones(np.size(phi)) * qsc_eq.B0, linestyle=\"--\", lw=3,c=\"b\")\n", + "plt.plot(phi, data_surf[\"|B|\"], lw=3, c=\"r\")\n", + "plt.plot(phi, data_nae[\"|B|\"], lw=6, c=\"g\")\n", + "plt.plot(phi, np.ones(np.size(phi)) * qsc_eq.B0, linestyle=\"--\", lw=3, c=\"b\")\n", "plt.xlabel(\"$\\phi$\")\n", "plt.ylabel(\"$|B|$\")\n", "plt.legend([\"Fixed surface\", \"Fixed NAE\", \"NAE\"])\n", @@ -783,9 +795,9 @@ " \"Deviation of theta from Boozer angle (fixed nae)\",\n", " np.mean(np.abs(lam_nae + qsc_eq.iota * qsc_eq.nu_spline(phi))),\n", ")\n", - "plt.plot(phi, lam_surf, lw=3,c=\"r\")\n", - "plt.plot(phi, lam_nae, lw=6,c=\"g\")\n", - "plt.plot(phi, -qsc_eq.iota * qsc_eq.nu_spline(phi), linestyle=\"--\", lw=3,c=\"b\")\n", + "plt.plot(phi, lam_surf, lw=3, c=\"r\")\n", + "plt.plot(phi, lam_nae, lw=6, c=\"g\")\n", + "plt.plot(phi, -qsc_eq.iota * qsc_eq.nu_spline(phi), linestyle=\"--\", lw=3, c=\"b\")\n", "plt.xlabel(\"$\\phi$\")\n", "plt.ylabel(\"$\\lambda$\")\n", "plt.legend([\"Fixed surface\", \"Fixed NAE\", \"NAE\"])\n", @@ -817,7 +829,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.10" + "version": "3.10.11" } }, "nbformat": 4,