From c4198c8262efc1aa6b45484ecd1dc02508c413e5 Mon Sep 17 00:00:00 2001 From: YigitElma Date: Sat, 21 Sep 2024 12:52:35 -0400 Subject: [PATCH 01/31] add docstring inheriter --- DEBUG | 1 + desc/objectives/objective_funs.py | 47 ++++++++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) create mode 160000 DEBUG diff --git a/DEBUG b/DEBUG new file mode 160000 index 000000000..631b3dc36 --- /dev/null +++ b/DEBUG @@ -0,0 +1 @@ +Subproject commit 631b3dc36e7eeed9a199e457449e9ae8f0ff7f23 diff --git a/desc/objectives/objective_funs.py b/desc/objectives/objective_funs.py index ffacaf639..d4caf7f86 100644 --- a/desc/objectives/objective_funs.py +++ b/desc/objectives/objective_funs.py @@ -1,6 +1,7 @@ """Base classes for objectives.""" import functools +import re from abc import ABC, abstractmethod import numpy as np @@ -8,6 +9,7 @@ from desc.backend import execute_on_cpu, jit, jnp, tree_flatten, tree_unflatten, use_jax from desc.derivatives import Derivative from desc.io import IOAble +from desc.io.optimizable_io import _CombinedMeta from desc.optimizable import Optimizable from desc.utils import ( PRINT_WIDTH, @@ -784,7 +786,50 @@ def things(self): return self._things -class _Objective(IOAble, ABC): +class DocInheritMeta(type): + """Metaclass to inherit docstrings from parent classes.""" + + def __new__(cls, name, bases, dct): + """Create a new class with inherited docstrings.""" + # Collect the child's docstring + child_doc = dct.get("__doc__", "") or "" + + # Find the immediate parent class that uses DocInheritMeta metaclass + for base in bases: + if isinstance( + base, DocInheritMeta + ): # Ensure it's from a class with DocInheritMeta + parent_doc = base.__doc__ or "" + + # find the "Parameters" section in the parent's docstring + parameters_section = re.search( + r"(Parameters\s*-+\s*.+)", parent_doc, re.DOTALL + ) + + if parameters_section: + # Get only the "Parameters" part of the parent's docstring + parameters_text = parameters_section.group(0) + else: + parameters_text = "" + + # Combine the child docstring with only the parent's parameters section + full_doc = ( + child_doc + "\n " + parameters_text + if parameters_text + else child_doc + ) + dct["__doc__"] = full_doc + + break # Only consider the first base class using DocInheritMeta + + return super().__new__(cls, name, bases, dct) + + +class _CombinedMeta2(DocInheritMeta, _CombinedMeta): + pass + + +class _Objective(IOAble, ABC, metaclass=_CombinedMeta2): """Objective (or constraint) used in the optimization of an Equilibrium. Parameters From f13f21f658f0cf1ecc76979a4fc3ec07f5434747 Mon Sep 17 00:00:00 2001 From: YigitElma Date: Mon, 23 Sep 2024 14:56:57 -0400 Subject: [PATCH 02/31] delete erronous submodule --- DEBUG | 1 - 1 file changed, 1 deletion(-) delete mode 160000 DEBUG diff --git a/DEBUG b/DEBUG deleted file mode 160000 index 631b3dc36..000000000 --- a/DEBUG +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 631b3dc36e7eeed9a199e457449e9ae8f0ff7f23 From 2b2e894e6c8a2c9d2ee07a4c51f8961a3c1108d4 Mon Sep 17 00:00:00 2001 From: YigitElma Date: Mon, 23 Sep 2024 17:04:54 -0400 Subject: [PATCH 03/31] add test and remove docs from _equilibrium --- desc/objectives/_equilibrium.py | 172 +++--------------------------- desc/objectives/objective_funs.py | 125 ++++++++++++++-------- tests/test_objective_funs.py | 18 +++- 3 files changed, 109 insertions(+), 206 deletions(-) diff --git a/desc/objectives/_equilibrium.py b/desc/objectives/_equilibrium.py index dc2f4bbb2..6a9b525d2 100644 --- a/desc/objectives/_equilibrium.py +++ b/desc/objectives/_equilibrium.py @@ -7,7 +7,7 @@ from desc.utils import Timer from .normalization import compute_scaling_factors -from .objective_funs import _Objective +from .objective_funs import _Objective, collect_docs class ForceBalance(_Objective): @@ -33,39 +33,14 @@ class ForceBalance(_Objective): ---------- eq : Equilibrium Equilibrium that will be optimized to satisfy the Objective. - target : {float, ndarray}, optional - Target value(s) of the objective. Only used if bounds is None. - Must be broadcastable to Objective.dim_f. Defaults to ``target=0``. - bounds : tuple of {float, ndarray}, optional - Lower and upper bounds on the objective. Overrides target. - Both bounds must be broadcastable to to Objective.dim_f. - Defaults to ``target=0``. - weight : {float, ndarray}, optional - Weighting to apply to the Objective, relative to other Objectives. - Must be broadcastable to to Objective.dim_f - normalize : bool, optional - Whether to compute the error in physical units or non-dimensionalize. - normalize_target : bool, optional - Whether target and bounds should be normalized before comparing to computed - values. If `normalize` is `True` and the target is in physical units, - this should also be set to True. - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss function - is called on the raw compute value, before any shifting, scaling, or - normalization. - deriv_mode : {"auto", "fwd", "rev"} - Specify how to compute jacobian matrix, either forward mode or reverse mode AD. - "auto" selects forward or reverse mode based on the size of the input and output - of the objective. Has no effect on self.grad or self.hess which always use - reverse mode and forward over reverse mode respectively. grid : Grid, optional Collocation grid containing the nodes to evaluate at. Defaults to ``ConcentricGrid(eq.L_grid, eq.M_grid, eq.N_grid)`` - name : str, optional - Name of the objective function. """ + __doc__ += collect_docs() + _equilibrium = True _coordinates = "rtz" _units = "(N)" @@ -209,35 +184,14 @@ class ForceBalanceAnisotropic(_Objective): ---------- eq : Equilibrium Equilibrium that will be optimized to satisfy the Objective. - target : float, ndarray, optional - Target value(s) of the objective. - Must be broadcastable to Objective.dim_f. Defaults to ``target=0``. - bounds : tuple, optional - Lower and upper bounds on the objective. Overrides target. - Both bounds must be broadcastable to to Objective.dim_f. - Defaults to ``target=0``. - weight : float, ndarray, optional - Weighting to apply to the Objective, relative to other Objectives. - Must be broadcastable to Objective.dim_f. - normalize : bool - Whether to compute the error in physical units or non-dimensionalize. - normalize_target : bool - Whether target should be normalized before comparing to computed values. - if `normalize` is `True` and the target is in physical units, this should also - be set to True. grid : Grid, ndarray, optional - Collocation grid containing the nodes to evaluate at. - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss function - is called on the raw compute value, before any shifting, scaling, or - normalization. grid : Grid, ndarray, optional Collocation grid containing the nodes to evaluate at. Defaults to ``ConcentricGrid(eq.L_grid, eq.M_grid, eq.N_grid)`` - name : str - Name of the objective function. """ + __doc__ += collect_docs() + _units = "(N)" _coordinates = "rtz" _equilibrium = True @@ -363,39 +317,14 @@ class RadialForceBalance(_Objective): ---------- eq : Equilibrium Equilibrium that will be optimized to satisfy the Objective. - target : {float, ndarray}, optional - Target value(s) of the objective. Only used if bounds is None. - Must be broadcastable to Objective.dim_f. Defaults to ``target=0``. - bounds : tuple of {float, ndarray}, optional - Lower and upper bounds on the objective. Overrides target. - Both bounds must be broadcastable to to Objective.dim_f. - Defaults to ``target=0``. - weight : {float, ndarray}, optional - Weighting to apply to the Objective, relative to other Objectives. - Must be broadcastable to to Objective.dim_f - normalize : bool, optional - Whether to compute the error in physical units or non-dimensionalize. - normalize_target : bool, optional - Whether target and bounds should be normalized before comparing to computed - values. If `normalize` is `True` and the target is in physical units, - this should also be set to True. - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss function - is called on the raw compute value, before any shifting, scaling, or - normalization. - deriv_mode : {"auto", "fwd", "rev"} - Specify how to compute jacobian matrix, either forward mode or reverse mode AD. - "auto" selects forward or reverse mode based on the size of the input and output - of the objective. Has no effect on self.grad or self.hess which always use - reverse mode and forward over reverse mode respectively. grid : Grid, optional Collocation grid containing the nodes to evaluate at. Defaults to ``ConcentricGrid(eq.L_grid, eq.M_grid, eq.N_grid)`` - name : str, optional - Name of the objective function. """ + __doc__ += collect_docs() + _equilibrium = True _coordinates = "rtz" _units = "(N)" @@ -521,39 +450,14 @@ class HelicalForceBalance(_Objective): ---------- eq : Equilibrium Equilibrium that will be optimized to satisfy the Objective. - target : {float, ndarray}, optional - Target value(s) of the objective. Only used if bounds is None. - Must be broadcastable to Objective.dim_f. Defaults to ``target=0``. - bounds : tuple of {float, ndarray}, optional - Lower and upper bounds on the objective. Overrides target. - Both bounds must be broadcastable to to Objective.dim_f. - Defaults to ``target=0``. - weight : {float, ndarray}, optional - Weighting to apply to the Objective, relative to other Objectives. - Must be broadcastable to to Objective.dim_f - normalize : bool, optional - Whether to compute the error in physical units or non-dimensionalize. - normalize_target : bool, optional - Whether target and bounds should be normalized before comparing to computed - values. If `normalize` is `True` and the target is in physical units, - this should also be set to True. - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss function - is called on the raw compute value, before any shifting, scaling, or - normalization. - deriv_mode : {"auto", "fwd", "rev"} - Specify how to compute jacobian matrix, either forward mode or reverse mode AD. - "auto" selects forward or reverse mode based on the size of the input and output - of the objective. Has no effect on self.grad or self.hess which always use - reverse mode and forward over reverse mode respectively. grid : Grid, optional Collocation grid containing the nodes to evaluate at. Defaults to ``ConcentricGrid(eq.L_grid, eq.M_grid, eq.N_grid)`` - name : str, optional - Name of the objective function. """ + __doc__ += collect_docs() + _equilibrium = True _coordinates = "rtz" _units = "(N)" @@ -675,41 +579,16 @@ class Energy(_Objective): ---------- eq : Equilibrium Equilibrium that will be optimized to satisfy the Objective. - target : {float, ndarray}, optional - Target value(s) of the objective. Only used if bounds is None. - Must be broadcastable to Objective.dim_f. Defaults to ``target=0``. - bounds : tuple of {float, ndarray}, optional - Lower and upper bounds on the objective. Overrides target. - Both bounds must be broadcastable to to Objective.dim_f. - Defaults to ``target=0``. - weight : {float, ndarray}, optional - Weighting to apply to the Objective, relative to other Objectives. - Must be broadcastable to to Objective.dim_f - normalize : bool, optional - Whether to compute the error in physical units or non-dimensionalize. - normalize_target : bool, optional - Whether target and bounds should be normalized before comparing to computed - values. If `normalize` is `True` and the target is in physical units, - this should also be set to True. - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss function - is called on the raw compute value, before any shifting, scaling, or - normalization. - deriv_mode : {"auto", "fwd", "rev"} - Specify how to compute jacobian matrix, either forward mode or reverse mode AD. - "auto" selects forward or reverse mode based on the size of the input and output - of the objective. Has no effect on self.grad or self.hess which always use - reverse mode and forward over reverse mode respectively. grid : Grid, optional Collocation grid containing the nodes to evaluate at. Defaults to ``QuadratureGrid(eq.L_grid, eq.M_grid, eq.N_grid)`` gamma : float, optional Adiabatic (compressional) index. Default = 0. - name : str, optional - Name of the objective function. """ + __doc__ += collect_docs() + _scalar = True _coordinates = "" _equilibrium = True @@ -844,39 +723,14 @@ class CurrentDensity(_Objective): ---------- eq : Equilibrium Equilibrium that will be optimized to satisfy the Objective. - target : {float, ndarray}, optional - Target value(s) of the objective. Only used if bounds is None. - Must be broadcastable to Objective.dim_f. Defaults to ``target=0``. - bounds : tuple of {float, ndarray}, optional - Lower and upper bounds on the objective. Overrides target. - Both bounds must be broadcastable to to Objective.dim_f. - Defaults to ``target=0``. - weight : {float, ndarray}, optional - Weighting to apply to the Objective, relative to other Objectives. - Must be broadcastable to to Objective.dim_f - normalize : bool, optional - Whether to compute the error in physical units or non-dimensionalize. - normalize_target : bool, optional - Whether target and bounds should be normalized before comparing to computed - values. If `normalize` is `True` and the target is in physical units, - this should also be set to True. - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss function - is called on the raw compute value, before any shifting, scaling, or - normalization. - deriv_mode : {"auto", "fwd", "rev"} - Specify how to compute jacobian matrix, either forward mode or reverse mode AD. - "auto" selects forward or reverse mode based on the size of the input and output - of the objective. Has no effect on self.grad or self.hess which always use - reverse mode and forward over reverse mode respectively. grid : Grid, optional Collocation grid containing the nodes to evaluate at. Defaults to ``ConcentricGrid(eq.L_grid, eq.M_grid, eq.N_grid)`` - name : str, optional - Name of the objective function. """ + __doc__ += collect_docs() + _equilibrium = True _coordinates = "rtz" _units = "(A*m)" diff --git a/desc/objectives/objective_funs.py b/desc/objectives/objective_funs.py index d4caf7f86..fc7c73316 100644 --- a/desc/objectives/objective_funs.py +++ b/desc/objectives/objective_funs.py @@ -1,7 +1,6 @@ """Base classes for objectives.""" import functools -import re from abc import ABC, abstractmethod import numpy as np @@ -9,7 +8,6 @@ from desc.backend import execute_on_cpu, jit, jnp, tree_flatten, tree_unflatten, use_jax from desc.derivatives import Derivative from desc.io import IOAble -from desc.io.optimizable_io import _CombinedMeta from desc.optimizable import Optimizable from desc.utils import ( PRINT_WIDTH, @@ -21,6 +19,84 @@ unique_list, ) +doc_target = """ + target : {float, ndarray}, optional + Target value(s) of the objective. Only used if bounds is None. + Must be broadcastable to Objective.dim_f. +""" +doc_bounds = """ + bounds : tuple of {float, ndarray}, optional + Lower and upper bounds on the objective. Overrides target. + Both bounds must be broadcastable to to Objective.dim_f +""" +doc_weight = """ + weight : {float, ndarray}, optional + Weighting to apply to the Objective, relative to other Objectives. + Must be broadcastable to to Objective.dim_f +""" +doc_normalize = """ + normalize : bool, optional + Whether to compute the error in physical units or non-dimensionalize. +""" +doc_normalize_target = """ + normalize_target : bool, optional + Whether target and bounds should be normalized before comparing to computed + values. If `normalize` is `True` and the target is in physical units, + this should also be set to True. +""" +doc_loss_function = """ + loss_function : {None, 'mean', 'min', 'max'}, optional + Loss function to apply to the objective values once computed. This loss function + is called on the raw compute value, before any shifting, scaling, or + normalization. +""" +doc_deriv_mode = """ + deriv_mode : {"auto", "fwd", "rev"} + Specify how to compute jacobian matrix, either forward mode or reverse mode AD. + "auto" selects forward or reverse mode based on the size of the input and output + of the objective. Has no effect on self.grad or self.hess which always use + reverse mode and forward over reverse mode respectively. +""" +doc_name = """ + name : str, optional + Name of the objective. +""" +docs = { + "target": doc_target, + "bounds": doc_bounds, + "weight": doc_weight, + "normalize": doc_normalize, + "normalize_target": doc_normalize_target, + "loss_function": doc_loss_function, + "deriv_mode": doc_deriv_mode, + "name": doc_name, +} + + +def collect_docs(exclude=None): + """Collect default parameters for the docstring of Objective. + + Parameters + ---------- + exclude : list, optional + List of strings to exclude from the docstring. If None, all default parameters + are included. Use this argument if you want to specify a special docstring for + a specific parameter in your objective definition. + + Returns + ------- + doc_params : str + String of default parameters for the docstring. + + """ + doc_params = "" + for key in docs.keys(): + if exclude is not None and key in exclude: + continue + doc_params += docs[key].rstrip() + + return doc_params + class ObjectiveFunction(IOAble): """Objective function comprised of one or more Objectives. @@ -786,50 +862,7 @@ def things(self): return self._things -class DocInheritMeta(type): - """Metaclass to inherit docstrings from parent classes.""" - - def __new__(cls, name, bases, dct): - """Create a new class with inherited docstrings.""" - # Collect the child's docstring - child_doc = dct.get("__doc__", "") or "" - - # Find the immediate parent class that uses DocInheritMeta metaclass - for base in bases: - if isinstance( - base, DocInheritMeta - ): # Ensure it's from a class with DocInheritMeta - parent_doc = base.__doc__ or "" - - # find the "Parameters" section in the parent's docstring - parameters_section = re.search( - r"(Parameters\s*-+\s*.+)", parent_doc, re.DOTALL - ) - - if parameters_section: - # Get only the "Parameters" part of the parent's docstring - parameters_text = parameters_section.group(0) - else: - parameters_text = "" - - # Combine the child docstring with only the parent's parameters section - full_doc = ( - child_doc + "\n " + parameters_text - if parameters_text - else child_doc - ) - dct["__doc__"] = full_doc - - break # Only consider the first base class using DocInheritMeta - - return super().__new__(cls, name, bases, dct) - - -class _CombinedMeta2(DocInheritMeta, _CombinedMeta): - pass - - -class _Objective(IOAble, ABC, metaclass=_CombinedMeta2): +class _Objective(IOAble, ABC): """Objective (or constraint) used in the optimization of an Equilibrium. Parameters diff --git a/tests/test_objective_funs.py b/tests/test_objective_funs.py index 4711907ab..00fbfc764 100644 --- a/tests/test_objective_funs.py +++ b/tests/test_objective_funs.py @@ -77,7 +77,7 @@ ) from desc.objectives._free_boundary import BoundaryErrorNESTOR from desc.objectives.normalization import compute_scaling_factors -from desc.objectives.objective_funs import _Objective +from desc.objectives.objective_funs import _Objective, collect_docs from desc.objectives.utils import softmax, softmin from desc.profiles import FourierZernikeProfile, PowerSeriesProfile from desc.utils import PRINT_WIDTH @@ -2845,3 +2845,19 @@ def test_objective_print_widths(): + "change the name or increase the PRINT_WIDTH in the " + "desc/utils.py file. The former is preferred." ) + + +def test_objective_docstring(): + """Test that the objective docstring and collect_docs are consistent.""" + objective_docs = _Objective.__doc__.rstrip() + doc_header = ( + "Objective (or constraint) used in the optimization of an Equilibrium.\n\n" + + " Parameters\n" + + " ----------\n" + + " things : Optimizable or tuple/list of Optimizable\n" + + " Objects that will be optimized to satisfy the Objective.\n" + ) + collected_docs = collect_docs().strip() + collected_docs = doc_header + " " + collected_docs + + assert objective_docs == collected_docs From 06512fe8ac6268ffde60d0150cdae26ee91a6f56 Mon Sep 17 00:00:00 2001 From: YigitElma Date: Mon, 23 Sep 2024 17:07:56 -0400 Subject: [PATCH 04/31] fix str concetanation spacing --- desc/objectives/_equilibrium.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/desc/objectives/_equilibrium.py b/desc/objectives/_equilibrium.py index 6a9b525d2..639cc53f8 100644 --- a/desc/objectives/_equilibrium.py +++ b/desc/objectives/_equilibrium.py @@ -39,7 +39,7 @@ class ForceBalance(_Objective): """ - __doc__ += collect_docs() + __doc__ = __doc__.rstrip() + collect_docs() _equilibrium = True _coordinates = "rtz" @@ -190,7 +190,7 @@ class ForceBalanceAnisotropic(_Objective): """ - __doc__ += collect_docs() + __doc__ = __doc__.rstrip() + collect_docs() _units = "(N)" _coordinates = "rtz" @@ -323,7 +323,7 @@ class RadialForceBalance(_Objective): """ - __doc__ += collect_docs() + __doc__ = __doc__.rstrip() + collect_docs() _equilibrium = True _coordinates = "rtz" @@ -456,7 +456,7 @@ class HelicalForceBalance(_Objective): """ - __doc__ += collect_docs() + __doc__ = __doc__.rstrip() + collect_docs() _equilibrium = True _coordinates = "rtz" @@ -587,7 +587,7 @@ class Energy(_Objective): """ - __doc__ += collect_docs() + __doc__ = __doc__.rstrip() + collect_docs() _scalar = True _coordinates = "" @@ -729,7 +729,7 @@ class CurrentDensity(_Objective): """ - __doc__ += collect_docs() + __doc__ = __doc__.rstrip() + collect_docs() _equilibrium = True _coordinates = "rtz" From 48f3b111b8b212634bcc0f872d5b467ba63f01b8 Mon Sep 17 00:00:00 2001 From: YigitElma Date: Mon, 23 Sep 2024 17:23:20 -0400 Subject: [PATCH 05/31] apply to bootstrap and coils --- desc/objectives/_bootstrap.py | 32 +---- desc/objectives/_coils.py | 212 +++------------------------------- 2 files changed, 23 insertions(+), 221 deletions(-) diff --git a/desc/objectives/_bootstrap.py b/desc/objectives/_bootstrap.py index 5887da06f..099b73a1f 100644 --- a/desc/objectives/_bootstrap.py +++ b/desc/objectives/_bootstrap.py @@ -9,7 +9,7 @@ from desc.utils import Timer, errorif, warnif from .normalization import compute_scaling_factors -from .objective_funs import _Objective +from .objective_funs import _Objective, collect_docs class BootstrapRedlConsistency(_Objective): @@ -31,31 +31,6 @@ class BootstrapRedlConsistency(_Objective): ---------- eq : Equilibrium Equilibrium that will be optimized to satisfy the Objective. - target : {float, ndarray}, optional - Target value(s) of the objective. Only used if bounds is None. - Must be broadcastable to Objective.dim_f. Defaults to ``target=0``. - bounds : tuple of {float, ndarray}, optional - Lower and upper bounds on the objective. Overrides target. - Both bounds must be broadcastable to to Objective.dim_f. - Defaults to ``target=0``. - weight : {float, ndarray}, optional - Weighting to apply to the Objective, relative to other Objectives. - Must be broadcastable to to Objective.dim_f - normalize : bool, optional - Whether to compute the error in physical units or non-dimensionalize. - normalize_target : bool, optional - Whether target and bounds should be normalized before comparing to computed - values. If `normalize` is `True` and the target is in physical units, - this should also be set to True. - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss function - is called on the raw compute value, before any shifting, scaling, or - normalization. - deriv_mode : {"auto", "fwd", "rev"} - Specify how to compute jacobian matrix, either forward mode or reverse mode AD. - "auto" selects forward or reverse mode based on the size of the input and output - of the objective. Has no effect on self.grad or self.hess which always use - reverse mode and forward over reverse mode respectively. grid : Grid, optional Collocation grid containing the nodes to evaluate at. Defaults to ``LinearGrid(eq.L_grid, eq.M_grid, eq.N_grid)`` @@ -64,10 +39,11 @@ class BootstrapRedlConsistency(_Objective): First entry must be M=1. Second entry is the toroidal mode number N, used for evaluating the Redl bootstrap current formula. Set to 0 for axisymmetry or quasi-axisymmetry; set to +/-NFP for quasi-helical symmetry. - name : str, optional - Name of the objective function. + """ + __doc__ = __doc__.rstrip() + collect_docs() + _coordinates = "r" _units = "(T A m^-2)" _print_value_fmt = "Bootstrap current self-consistency error: " diff --git a/desc/objectives/_coils.py b/desc/objectives/_coils.py index 04f295491..b029c6057 100644 --- a/desc/objectives/_coils.py +++ b/desc/objectives/_coils.py @@ -17,7 +17,7 @@ from desc.utils import Timer, errorif, safenorm, warnif from .normalization import compute_scaling_factors -from .objective_funs import _Objective +from .objective_funs import _Objective, collect_docs class _CoilObjective(_Objective): @@ -29,39 +29,18 @@ class _CoilObjective(_Objective): Coil for which the data keys will be optimized. data_keys : list of str data keys that will be optimized when this class is inherited. - target : float, ndarray, optional - Target value(s) of the objective. Only used if bounds is None. - Must be broadcastable to Objective.dim_f. - bounds : tuple of float, ndarray, optional - Lower and upper bounds on the objective. Overrides target. - Both bounds must be broadcastable to to Objective.dim_f - weight : float, ndarray, optional - Weighting to apply to the Objective, relative to other Objectives. - Must be broadcastable to to Objective.dim_f - normalize : bool, optional - Whether to compute the error in physical units or non-dimensionalize. - normalize_target : bool, optional - Whether target and bounds should be normalized before comparing to computed - values. If `normalize` is `True` and the target is in physical units, - this should also be set to True. - be set to True. loss_function : {None, 'mean', 'min', 'max'}, optional Loss function to apply to the objective values once computed. This loss function is called on the raw compute value, before any shifting, scaling, or normalization. Operates over all coils, not each individual coil. - deriv_mode : {"auto", "fwd", "rev"} - Specify how to compute jacobian matrix, either forward mode or reverse mode AD. - "auto" selects forward or reverse mode based on the size of the input and output - of the objective. Has no effect on self.grad or self.hess which always use - reverse mode and forward over reverse mode respectively. grid : Grid, list, optional Collocation grid containing the nodes to evaluate at. If a list, must have the same structure as coil. - name : str, optional - Name of the objective function. """ + __doc__ = __doc__.rstrip() + collect_docs(exclude=["loss_function"]) + def __init__( self, coil, @@ -226,37 +205,18 @@ class CoilLength(_CoilObjective): Target value(s) of the objective. Only used if bounds is None. Must be broadcastable to Objective.dim_f. If array, it has to be flattened according to the number of inputs. Defaults to ``target=2*np.pi``. - bounds : tuple of float, ndarray, optional - Lower and upper bounds on the objective. Overrides target. - Both bounds must be broadcastable to to Objective.dim_f. - Defaults to ``target=2*np.pi``. - weight : float, ndarray, optional - Weighting to apply to the Objective, relative to other Objectives. - Must be broadcastable to to Objective.dim_f - normalize : bool, optional - Whether to compute the error in physical units or non-dimensionalize. - normalize_target : bool, optional - Whether target and bounds should be normalized before comparing to computed - values. If `normalize` is `True` and the target is in physical units, - this should also be set to True. - be set to True. loss_function : {None, 'mean', 'min', 'max'}, optional Loss function to apply to the objective values once computed. This loss function is called on the raw compute value, before any shifting, scaling, or normalization. Operates over all coils, not each individual coil. - deriv_mode : {"auto", "fwd", "rev"} - Specify how to compute jacobian matrix, either forward mode or reverse mode AD. - "auto" selects forward or reverse mode based on the size of the input and output - of the objective. Has no effect on self.grad or self.hess which always use - reverse mode and forward over reverse mode respectively. grid : Grid, optional Collocation grid containing the nodes to evaluate at. Defaults to ``LinearGrid(N=2 * coil.N + 5)`` - name : str, optional - Name of the objective function. """ + __doc__ = __doc__.rstrip() + collect_docs(exclude=["target", "loss_function"]) + _scalar = False # Not always a scalar, if a coilset is passed in _units = "(m)" _print_value_fmt = "Coil length: " @@ -351,37 +311,18 @@ class CoilCurvature(_CoilObjective): Target value(s) of the objective. Only used if bounds is None. Must be broadcastable to Objective.dim_f. If array, it has to be flattened according to the number of inputs. Defaults to ``bounds=(0,1)``. - bounds : tuple of float, ndarray, optional - Lower and upper bounds on the objective. Overrides target. - Both bounds must be broadcastable to to Objective.dim_f. - Defaults to ``bounds=(0,1)``. - weight : float, ndarray, optional - Weighting to apply to the Objective, relative to other Objectives. - Must be broadcastable to to Objective.dim_f - normalize : bool, optional - Whether to compute the error in physical units or non-dimensionalize. - normalize_target : bool, optional - Whether target and bounds should be normalized before comparing to computed - values. If `normalize` is `True` and the target is in physical units, - this should also be set to True. - be set to True. loss_function : {None, 'mean', 'min', 'max'}, optional Loss function to apply to the objective values once computed. This loss function is called on the raw compute value, before any shifting, scaling, or normalization. Operates over all coils, not each individual coil. - deriv_mode : {"auto", "fwd", "rev"} - Specify how to compute jacobian matrix, either forward mode or reverse mode AD. - "auto" selects forward or reverse mode based on the size of the input and output - of the objective. Has no effect on self.grad or self.hess which always use - reverse mode and forward over reverse mode respectively. grid : Grid, optional Collocation grid containing the nodes to evaluate at. Defaults to ``LinearGrid(N=2 * coil.N + 5)`` - name : str, optional - Name of the objective function. """ + __doc__ = __doc__.rstrip() + collect_docs(exclude=["target", "loss_function"]) + _scalar = False _units = "(m^-1)" _print_value_fmt = "Coil curvature: " @@ -471,37 +412,18 @@ class CoilTorsion(_CoilObjective): Target value(s) of the objective. Only used if bounds is None. Must be broadcastable to Objective.dim_f. If array, it has to be flattened according to the number of inputs. Defaults to ``target=0``. - bounds : tuple of float, ndarray, optional - Lower and upper bounds on the objective. Overrides target. - Both bounds must be broadcastable to to Objective.dim_f. - Defaults to ``target=0``. - weight : float, ndarray, optional - Weighting to apply to the Objective, relative to other Objectives. - Must be broadcastable to to Objective.dim_f - normalize : bool, optional - Whether to compute the error in physical units or non-dimensionalize. - normalize_target : bool, optional - Whether target and bounds should be normalized before comparing to computed - values. If `normalize` is `True` and the target is in physical units, - this should also be set to True. - be set to True. loss_function : {None, 'mean', 'min', 'max'}, optional Loss function to apply to the objective values once computed. This loss function is called on the raw compute value, before any shifting, scaling, or normalization. Operates over all coils, not each individual coil. - deriv_mode : {"auto", "fwd", "rev"} - Specify how to compute jacobian matrix, either forward mode or reverse mode AD. - "auto" selects forward or reverse mode based on the size of the input and output - of the objective. Has no effect on self.grad or self.hess which always use - reverse mode and forward over reverse mode respectively. grid : Grid, optional Collocation grid containing the nodes to evaluate at. Defaults to ``LinearGrid(N=2 * coil.N + 5)`` - name : str, optional - Name of the objective function. """ + __doc__ = __doc__.rstrip() + collect_docs(exclude=["target", "loss_function"]) + _scalar = False _units = "(m^-1)" _print_value_fmt = "Coil torsion: " @@ -591,37 +513,18 @@ class CoilCurrentLength(CoilLength): Target value(s) of the objective. Only used if bounds is None. Must be broadcastable to Objective.dim_f. If array, it has to be flattened according to the number of inputs. Defaults to ``target=0``. - bounds : tuple of float, ndarray, optional - Lower and upper bounds on the objective. Overrides target. - Both bounds must be broadcastable to to Objective.dim_f. - Defaults to ``target=0``. - weight : float, ndarray, optional - Weighting to apply to the Objective, relative to other Objectives. - Must be broadcastable to to Objective.dim_f - normalize : bool, optional - Whether to compute the error in physical units or non-dimensionalize. - normalize_target : bool, optional - Whether target and bounds should be normalized before comparing to computed - values. If `normalize` is `True` and the target is in physical units, - this should also be set to True. - be set to True. loss_function : {None, 'mean', 'min', 'max'}, optional Loss function to apply to the objective values once computed. This loss function is called on the raw compute value, before any shifting, scaling, or normalization. Operates over all coils, not each individual coil. - deriv_mode : {"auto", "fwd", "rev"} - Specify how to compute jacobian matrix, either forward mode or reverse mode AD. - "auto" selects forward or reverse mode based on the size of the input and output - of the objective. Has no effect on self.grad or self.hess which always use - reverse mode and forward over reverse mode respectively. grid : Grid, optional Collocation grid containing the nodes to evaluate at. Defaults to ``LinearGrid(N=2 * coil.N + 5)`` - name : str, optional - Name of the objective function. """ + __doc__ = __doc__.rstrip() + collect_docs(exclude=["target", "loss_function"]) + _scalar = False _units = "(A*m)" _print_value_fmt = "Coil current length: " @@ -719,37 +622,19 @@ class CoilSetMinDistance(_Objective): Target value(s) of the objective. Only used if bounds is None. Must be broadcastable to Objective.dim_f. If array, it has to be flattened according to the number of inputs. - bounds : tuple of float, ndarray, optional - Lower and upper bounds on the objective. Overrides target. - Both bounds must be broadcastable to to Objective.dim_f - weight : float, ndarray, optional - Weighting to apply to the Objective, relative to other Objectives. - Must be broadcastable to to Objective.dim_f - normalize : bool, optional - Whether to compute the error in physical units or non-dimensionalize. - normalize_target : bool, optional - Whether target and bounds should be normalized before comparing to computed - values. If `normalize` is `True` and the target is in physical units, - this should also be set to True. - be set to True. loss_function : {None, 'mean', 'min', 'max'}, optional Loss function to apply to the objective values once computed. This loss function is called on the raw compute value, before any shifting, scaling, or normalization. Operates over all coils, not each individial coil. - deriv_mode : {"auto", "fwd", "rev"} - Specify how to compute jacobian matrix, either forward mode or reverse mode AD. - "auto" selects forward or reverse mode based on the size of the input and output - of the objective. Has no effect on self.grad or self.hess which always use - reverse mode and forward over reverse mode respectively. grid : Grid, list, optional Collocation grid used to discretize each coil. Defaults to the default grid for the given coil-type, see ``coils.py`` and ``curve.py`` for more details. If a list, must have the same structure as coils. - name : str, optional - Name of the objective function. """ + __doc__ = __doc__.rstrip() + collect_docs(exclude=["target", "loss_function"]) + _scalar = False _units = "(m)" _print_value_fmt = "Minimum coil-coil distance: " @@ -873,32 +758,10 @@ class PlasmaCoilSetMinDistance(_Objective): to satisfy the Objective. coil : CoilSet Coil(s) that are to be optimized. - target : float, ndarray, optional - Target value(s) of the objective. Only used if bounds is None. - Must be broadcastable to Objective.dim_f. If array, it has to - be flattened according to the number of inputs. - bounds : tuple of float, ndarray, optional - Lower and upper bounds on the objective. Overrides target. - Both bounds must be broadcastable to to Objective.dim_f - weight : float, ndarray, optional - Weighting to apply to the Objective, relative to other Objectives. - Must be broadcastable to to Objective.dim_f - normalize : bool, optional - Whether to compute the error in physical units or non-dimensionalize. - normalize_target : bool, optional - Whether target and bounds should be normalized before comparing to computed - values. If `normalize` is `True` and the target is in physical units, - this should also be set to True. - be set to True. loss_function : {None, 'mean', 'min', 'max'}, optional Loss function to apply to the objective values once computed. This loss function is called on the raw compute value, before any shifting, scaling, or normalization. Operates over all coils, not each individial coil. - deriv_mode : {"auto", "fwd", "rev"} - Specify how to compute jacobian matrix, either forward mode or reverse mode AD. - "auto" selects forward or reverse mode based on the size of the input and output - of the objective. Has no effect on self.grad or self.hess which always use - reverse mode and forward over reverse mode respectively. plasma_grid : Grid, optional Collocation grid containing the nodes to evaluate plasma geometry at. Defaults to ``LinearGrid(M=eq.M_grid, N=eq.N_grid)``. @@ -919,11 +782,11 @@ class PlasmaCoilSetMinDistance(_Objective): during optimization, and self.things = [eq] only. If False, the coil coordinates are computed at every iteration. False by default, so that self.things = [coil, eq]. - name : str, optional - Name of the objective function. """ + __doc__ = __doc__.rstrip() + collect_docs(exclude=["target", "loss_function"]) + _scalar = False _units = "(m)" _print_value_fmt = "Minimum plasma-coil distance: " @@ -1118,22 +981,6 @@ class QuadraticFlux(_Objective): field : MagneticField External field produced by coils or other source, which will be optimized to minimize the normal field error on the provided equilibrium's surface. - target : float, ndarray, optional - Target value(s) of the objective. Only used if bounds is None. - len(target) must be equal to Objective.dim_f. - Default target is zero. - bounds : tuple, optional - Lower and upper bounds on the objective. Overrides target. - len(bounds[0]) and len(bounds[1]) must be equal to Objective.dim_f - weight : float, ndarray, optional - Weighting to apply to the Objective, relative to other Objectives. - len(weight) must be equal to Objective.dim_f - normalize : bool - Whether to compute the error in physical units or non-dimensionalize. - normalize_target : bool - Whether target and bounds should be normalized before comparing to computed - values. If `normalize` is `True` and the target is in physical units, - this should also be set to True. source_grid : Grid, optional Collocation grid containing the nodes for plasma source terms. Default grid is detailed in the docs for ``compute_B_plasma`` @@ -1149,11 +996,11 @@ class QuadraticFlux(_Objective): vacuum : bool If true, B_plasma (the contribution to the normal field on the boundary from the plasma currents) is set to zero. - name : str - Name of the objective function. """ + __doc__ = __doc__.rstrip() + collect_docs(exclude=["loss_function"]) + _scalar = False _linear = False _print_value_fmt = "Boundary normal field error: " @@ -1326,30 +1173,10 @@ class ToroidalFlux(_Objective): field : MagneticField MagneticField object, the parameters of this will be optimized to minimize the objective. - target : {float, ndarray}, optional - Target value(s) of the objective. Only used if bounds is None. - Defaults to eq.Psi. Must be broadcastable to Objective.dim_f. - bounds : tuple of {float, ndarray}, optional - Lower and upper bounds on the objective. Overrides target. - Both bounds must be broadcastable to to Objective.dim_f - weight : {float, ndarray}, optional - Weighting to apply to the Objective, relative to other Objectives. - Must be broadcastable to to Objective.dim_f - normalize : bool, optional - Whether to compute the error in physical units or non-dimensionalize. - normalize_target : bool - Whether target should be normalized before comparing to computed values. - if `normalize` is `True` and the target is in physical units, this should also - be set to True. loss_function : {None, 'mean', 'min', 'max'}, optional Loss function to apply to the objective values once computed. This function is called on the raw compute value, before any shifting, scaling, or normalization. Note: has no effect for this objective - deriv_mode : {"auto", "fwd", "rev"} - Specify how to compute jacobian matrix, either forward mode or reverse mode AD. - "auto" selects forward or reverse mode based on the size of the input and output - of the objective. Has no effect on self.grad or self.hess which always use - reverse mode and forward over reverse mode respectively. field_grid : Grid, optional Grid containing the nodes to evaluate field source at on the winding surface. (used if e.g. field is a CoilSet or @@ -1359,12 +1186,11 @@ class ToroidalFlux(_Objective): Collocation grid containing the nodes to evaluate the normal magnetic field at plasma geometry at. Defaults to a LinearGrid(L=eq.L_grid, M=eq.M_grid, zeta=jnp.array(0.0), NFP=eq.NFP). - name : str, optional - Name of the objective function. - """ + __doc__ = __doc__.rstrip() + collect_docs(exclude=["loss_function"]) + _coordinates = "rtz" _units = "(Wb)" _print_value_fmt = "Toroidal Flux: " From aae5612c48a5f483dcd9d7829d0c4c0ba20178de Mon Sep 17 00:00:00 2001 From: YigitElma Date: Mon, 23 Sep 2024 20:29:59 -0400 Subject: [PATCH 06/31] apply to free boundary --- desc/objectives/_free_boundary.py | 91 +++---------------------------- 1 file changed, 9 insertions(+), 82 deletions(-) diff --git a/desc/objectives/_free_boundary.py b/desc/objectives/_free_boundary.py index 62d5984ae..239f26761 100644 --- a/desc/objectives/_free_boundary.py +++ b/desc/objectives/_free_boundary.py @@ -11,7 +11,7 @@ from desc.grid import LinearGrid from desc.integrals import DFTInterpolator, FFTInterpolator, virtual_casing_biot_savart from desc.nestor import Nestor -from desc.objectives.objective_funs import _Objective +from desc.objectives.objective_funs import _Objective, collect_docs from desc.utils import PRINT_WIDTH, Timer, errorif, warnif from .normalization import compute_scaling_factors @@ -38,31 +38,6 @@ class VacuumBoundaryError(_Objective): Equilibrium that will be optimized to satisfy the Objective. field : MagneticField External field produced by coils or other sources outside the plasma. - target : float, ndarray, optional - Target value(s) of the objective. Only used if bounds is None. - Must be broadcastable to Objective.dim_f. Defaults to ``target=0``. - bounds : tuple, optional - Lower and upper bounds on the objective. Overrides target. - Both bounds must be broadcastable to to Objective.dim_f. - Defaults to ``target=0``. - weight : float, ndarray, optional - Weighting to apply to the Objective, relative to other Objectives. - Must be broadcastable to Objective.dim_f. - normalize : bool - Whether to compute the error in physical units or non-dimensionalize. - normalize_target : bool - Whether target and bounds should be normalized before comparing to computed - values. If `normalize` is `True` and the target is in physical units, - this should also be set to True. - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss function - is called on the raw compute value, before any shifting, scaling, or - normalization. - deriv_mode : {"auto", "fwd", "rev"} - Specify how to compute jacobian matrix, either forward mode or reverse mode AD. - "auto" selects forward or reverse mode based on the size of the input and output - of the objective. Has no effect on self.grad or self.hess which always use - reverse mode and forward over reverse mode respectively. grid : Grid, optional Collocation grid containing the nodes to evaluate error at. Should be at rho=1. Defaults to ``LinearGrid(M=eq.M_grid, N=eq.N_grid)`` @@ -71,11 +46,11 @@ class VacuumBoundaryError(_Objective): field_fixed : bool Whether to assume the field is fixed. For free boundary solve, should be fixed. For single stage optimization, should be False (default). - name : str - Name of the objective function. """ + __doc__ = __doc__.rstrip() + collect_docs() + _scalar = False _linear = False _print_value_fmt = "Boundary Error: " @@ -366,31 +341,6 @@ class BoundaryError(_Objective): Equilibrium that will be optimized to satisfy the Objective. field : MagneticField External field produced by coils. - target : float, ndarray, optional - Target value(s) of the objective. Only used if bounds is None. - Must be broadcastable to Objective.dim_f. Defaults to ``target=0``. - bounds : tuple, optional - Lower and upper bounds on the objective. Overrides target. - Both bounds must be broadcastable to to Objective.dim_f. - Defaults to ``target=0``. - weight : float, ndarray, optional - Weighting to apply to the Objective, relative to other Objectives. - Must be broadcastable to Objective.dim_f. - normalize : bool - Whether to compute the error in physical units or non-dimensionalize. - normalize_target : bool - Whether target and bounds should be normalized before comparing to computed - values. If `normalize` is `True` and the target is in physical units, - this should also be set to True. - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss function - is called on the raw compute value, before any shifting, scaling, or - normalization. - deriv_mode : {"auto", "fwd", "rev"} - Specify how to compute jacobian matrix, either forward mode or reverse mode AD. - "auto" selects forward or reverse mode based on the size of the input and output - of the objective. Has no effect on self.grad or self.hess which always use - reverse mode and forward over reverse mode respectively. s, q : integer Hyperparameters for singular integration scheme, s is roughly equal to the size of the local singular grid with respect to the global grid, q is the order of @@ -408,10 +358,12 @@ class BoundaryError(_Objective): loop : bool If True, evaluate integral using loops, as opposed to vmap. Slower, but uses less memory. - name : str - Name of the objective function. + """ + + __doc__ = __doc__.rstrip() + collect_docs() + __doc__ += """ Examples -------- Assigning a surface current to the equilibrium: @@ -834,42 +786,17 @@ class BoundaryErrorNESTOR(_Objective): Equilibrium that will be optimized to satisfy the Objective. field : MagneticField External field produced by coils. - target : float, ndarray, optional - Target value(s) of the objective. Only used if bounds is None. - Must be broadcastable to Objective.dim_f. Defaults to ``target=0``. - bounds : tuple, optional - Lower and upper bounds on the objective. Overrides target. - Both bounds must be broadcastable to to Objective.dim_f. - Defaults to ``target=0``. - weight : float, ndarray, optional - Weighting to apply to the Objective, relative to other Objectives. - Must be broadcastable to Objective.dim_f. mf, nf : integer maximum poloidal and toroidal mode numbers to use for NESTOR scalar potential. ntheta, nzeta : int number of grid points in poloidal, toroidal directions to use in NESTOR. field_grid : Grid, optional Grid used to discretize field. - normalize : bool - Whether to compute the error in physical units or non-dimensionalize. - normalize_target : bool - Whether target and bounds should be normalized before comparing to computed - values. If `normalize` is `True` and the target is in physical units, - this should also be set to True. - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss function - is called on the raw compute value, before any shifting, scaling, or - normalization. - deriv_mode : {"auto", "fwd", "rev"} - Specify how to compute jacobian matrix, either forward mode or reverse mode AD. - "auto" selects forward or reverse mode based on the size of the input and output - of the objective. Has no effect on self.grad or self.hess which always use - reverse mode and forward over reverse mode respectively. - name : str - Name of the objective function. """ + __doc__ = __doc__.rstrip() + collect_docs() + _scalar = False _linear = False _print_value_fmt = "Boundary magnetic pressure error: " From 4ee5d7861b15bb3a55873b9b25cb2aa8a8268245 Mon Sep 17 00:00:00 2001 From: YigitElma Date: Mon, 23 Sep 2024 20:33:30 -0400 Subject: [PATCH 07/31] apply to generic --- desc/objectives/_free_boundary.py | 1 - desc/objectives/_generic.py | 85 ++++--------------------------- 2 files changed, 9 insertions(+), 77 deletions(-) diff --git a/desc/objectives/_free_boundary.py b/desc/objectives/_free_boundary.py index 239f26761..ea58d0192 100644 --- a/desc/objectives/_free_boundary.py +++ b/desc/objectives/_free_boundary.py @@ -362,7 +362,6 @@ class BoundaryError(_Objective): """ __doc__ = __doc__.rstrip() + collect_docs() - __doc__ += """ Examples -------- diff --git a/desc/objectives/_generic.py b/desc/objectives/_generic.py index 46e45a995..c0b83e3d1 100644 --- a/desc/objectives/_generic.py +++ b/desc/objectives/_generic.py @@ -14,7 +14,7 @@ from desc.utils import errorif, parse_argname_change from .linear_objectives import _FixedObjective -from .objective_funs import _Objective +from .objective_funs import _Objective, collect_docs class GenericObjective(_Objective): @@ -26,40 +26,14 @@ class GenericObjective(_Objective): Name of the quantity to compute. thing : Optimizable Object that will be optimized to satisfy the Objective. - target : {float, ndarray}, optional - Target value(s) of the objective. Only used if bounds is None. - Must be broadcastable to Objective.dim_f. Defaults to ``target=0``. - bounds : tuple of {float, ndarray}, optional - Lower and upper bounds on the objective. Overrides target. - Both bounds must be broadcastable to to Objective.dim_f. - Defaults to ``target=0``. - weight : {float, ndarray}, optional - Weighting to apply to the Objective, relative to other Objectives. - Must be broadcastable to to Objective.dim_f. - normalize : bool, optional - Whether to compute the error in physical units or non-dimensionalize. - Has no effect for this objective - normalize_target : bool, optional - Whether target and bounds should be normalized before comparing to computed - values. If `normalize` is `True` and the target is in physical units, - this should also be set to True. Note: Has no effect on this objective. - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss function - is called on the raw compute value, before any shifting, scaling, or - normalization. - deriv_mode : {"auto", "fwd", "rev"} - Specify how to compute jacobian matrix, either forward mode or reverse mode AD. - "auto" selects forward or reverse mode based on the size of the input and output - of the objective. Has no effect on self.grad or self.hess which always use - reverse mode and forward over reverse mode respectively. grid : Grid, optional Collocation grid containing the nodes to evaluate at. Defaults to ``QuadratureGrid(eq.L_grid, eq.M_grid, eq.N_grid)`` if thing is an Equilibrium. - name : str, optional - Name of the objective function. """ + __doc__ = __doc__.rstrip() + collect_docs() + _print_value_fmt = "Generic objective value: " def __init__( @@ -187,28 +161,11 @@ class LinearObjectiveFromUser(_FixedObjective): Custom objective function. thing : Optimizable Object whose degrees of freedom are being constrained. - target : dict of {float, ndarray}, optional - Target value(s) of the objective. Only used if bounds is None. - Must be broadcastable to Objective.dim_f. Defaults to ``target=0``. - bounds : tuple of dict {float, ndarray}, optional - Lower and upper bounds on the objective. Overrides target. - Both bounds must be broadcastable to to Objective.dim_f. - Defaults to ``target=0``. - weight : dict of {float, ndarray}, optional - Weighting to apply to the Objective, relative to other Objectives. - Should be a scalar or have the same tree structure as thing.params. - normalize : bool, optional - Whether to compute the error in physical units or non-dimensionalize. - Has no effect for this objective. - normalize_target : bool, optional - Whether target and bounds should be normalized before comparing to computed - values. If `normalize` is `True` and the target is in physical units, - this should also be set to True. Has no effect for this objective. - name : str, optional - Name of the objective function. """ + __doc__ = __doc__.rstrip() + collect_docs() + _scalar = False _linear = True _fixed = True @@ -311,38 +268,14 @@ class ObjectiveFromUser(_Objective): Custom objective function. thing : Optimizable Object that will be optimized to satisfy the Objective. - target : {float, ndarray}, optional - Target value(s) of the objective. Only used if bounds is None. - Must be broadcastable to Objective.dim_f. Defaults to ``target=0``. - bounds : tuple of {float, ndarray}, optional - Lower and upper bounds on the objective. Overrides target. - Both bounds must be broadcastable to to Objective.dim_f. - Defaults to ``target=0``. - weight : {float, ndarray}, optional - Weighting to apply to the Objective, relative to other Objectives. - Must be broadcastable to to Objective.dim_f - normalize : bool, optional - Whether to compute the error in physical units or non-dimensionalize. - Has no effect for this objective. - normalize_target : bool, optional - Whether target and bounds should be normalized before comparing to computed - values. If `normalize` is `True` and the target is in physical units, - this should also be set to True. - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss function - is called on the raw compute value, before any shifting, scaling, or - normalization. - deriv_mode : {"auto", "fwd", "rev"} - Specify how to compute jacobian matrix, either forward mode or reverse mode AD. - "auto" selects forward or reverse mode based on the size of the input and output - of the objective. Has no effect on self.grad or self.hess which always use - reverse mode and forward over reverse mode respectively. grid : Grid, optional Collocation grid containing the nodes to evaluate at. Defaults to ``QuadratureGrid(eq.L_grid, eq.M_grid, eq.N_grid)`` if thing is an Equilibrium. - name : str, optional - Name of the objective function. + """ + + __doc__ = __doc__.rstrip() + collect_docs() + __doc__ += """ Examples -------- .. code-block:: python From a8f702980a1bd67d7baa4a3ee226a4e8c3e4e140 Mon Sep 17 00:00:00 2001 From: YigitElma Date: Mon, 23 Sep 2024 20:38:01 -0400 Subject: [PATCH 08/31] apply to geometry --- desc/objectives/_geometry.py | 238 +++-------------------------------- 1 file changed, 18 insertions(+), 220 deletions(-) diff --git a/desc/objectives/_geometry.py b/desc/objectives/_geometry.py index e405609c7..d7a2c29a3 100644 --- a/desc/objectives/_geometry.py +++ b/desc/objectives/_geometry.py @@ -9,7 +9,7 @@ from desc.utils import Timer, errorif, parse_argname_change, safenorm, warnif from .normalization import compute_scaling_factors -from .objective_funs import _Objective +from .objective_funs import _Objective, collect_docs from .utils import check_if_points_are_inside_perimeter, softmin @@ -21,41 +21,15 @@ class AspectRatio(_Objective): eq : Equilibrium or FourierRZToroidalSurface Equilibrium or FourierRZToroidalSurface that will be optimized to satisfy the Objective. - target : {float, ndarray}, optional - Target value(s) of the objective. Only used if bounds is None. - Must be broadcastable to Objective.dim_f. Defaults to ``target=2``. - bounds : tuple of {float, ndarray}, optional - Lower and upper bounds on the objective. Overrides target. - Both bounds must be broadcastable to to Objective.dim_f. - Defaults to ``target=2``. - weight : {float, ndarray}, optional - Weighting to apply to the Objective, relative to other Objectives. - Must be broadcastable to to Objective.dim_f - normalize : bool, optional - Whether to compute the error in physical units or non-dimensionalize. - Has no effect for this objective. - normalize_target : bool, optional - Whether target and bounds should be normalized before comparing to computed - values. If `normalize` is `True` and the target is in physical units, - this should also be set to True. Note: Has no effect for this objective. - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss function - is called on the raw compute value, before any shifting, scaling, or - normalization. Note: Has no effect for this objective. - deriv_mode : {"auto", "fwd", "rev"} - Specify how to compute jacobian matrix, either forward mode or reverse mode AD. - "auto" selects forward or reverse mode based on the size of the input and output - of the objective. Has no effect on self.grad or self.hess which always use - reverse mode and forward over reverse mode respectively. grid : Grid, optional Collocation grid containing the nodes to evaluate at. Defaults to ``QuadratureGrid(eq.L_grid, eq.M_grid, eq.N_grid)`` for ``Equilibrium`` or ``LinearGrid(M=2*eq.M, N=2*eq.N)`` for ``FourierRZToroidalSurface``. - name : str, optional - Name of the objective function. """ + __doc__ = __doc__.rstrip() + collect_docs() + _scalar = True _units = "(dimensionless)" _print_value_fmt = "Aspect ratio: " @@ -183,41 +157,15 @@ class Elongation(_Objective): eq : Equilibrium or FourierRZToroidalSurface Equilibrium or FourierRZToroidalSurface that will be optimized to satisfy the Objective. - target : {float, ndarray}, optional - Target value(s) of the objective. Only used if bounds is None. - Must be broadcastable to Objective.dim_f. Defaults to ``target=1``. - bounds : tuple of {float, ndarray}, optional - Lower and upper bounds on the objective. Overrides target. - Both bounds must be broadcastable to to Objective.dim_f. - Defaults to ``target=1``. - weight : {float, ndarray}, optional - Weighting to apply to the Objective, relative to other Objectives. - Must be broadcastable to to Objective.dim_f - normalize : bool, optional - Whether to compute the error in physical units or non-dimensionalize. - Has no effect for this objective. - normalize_target : bool, optional - Whether target and bounds should be normalized before comparing to computed - values. If `normalize` is `True` and the target is in physical units, - this should also be set to True. Note: Has no effect for this objective. - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss function - is called on the raw compute value, before any shifting, scaling, or - normalization. Note: Has no effect for this objective. - deriv_mode : {"auto", "fwd", "rev"} - Specify how to compute jacobian matrix, either forward mode or reverse mode AD. - "auto" selects forward or reverse mode based on the size of the input and output - of the objective. Has no effect on self.grad or self.hess which always use - reverse mode and forward over reverse mode respectively. grid : Grid, optional Collocation grid containing the nodes to evaluate at. Defaults to ``QuadratureGrid(eq.L_grid, eq.M_grid, eq.N_grid)`` for ``Equilibrium`` or ``LinearGrid(M=2*eq.M, N=2*eq.N)`` for ``FourierRZToroidalSurface``. - name : str, optional - Name of the objective function. """ + __doc__ = __doc__.rstrip() + collect_docs() + _scalar = True _units = "(dimensionless)" _print_value_fmt = "Elongation: " @@ -344,41 +292,15 @@ class Volume(_Objective): eq : Equilibrium or FourierRZToroidalSurface Equilibrium or FourierRZToroidalSurface that will be optimized to satisfy the Objective. - target : {float, ndarray}, optional - Target value(s) of the objective. Only used if bounds is None. - Must be broadcastable to Objective.dim_f. Defaults to ``target=1``. - bounds : tuple of {float, ndarray}, optional - Lower and upper bounds on the objective. Overrides target. - Both bounds must be broadcastable to to Objective.dim_f. - Defaults to ``target=1``. - weight : {float, ndarray}, optional - Weighting to apply to the Objective, relative to other Objectives. - Must be broadcastable to to Objective.dim_f - normalize : bool, optional - Whether to compute the error in physical units or non-dimensionalize. - normalize_target : bool, optional - Whether target and bounds should be normalized before comparing to computed - values. If `normalize` is `True` and the target is in physical units, - this should also be set to True. - be set to True. - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss function - is called on the raw compute value, before any shifting, scaling, or - normalization. Note: Has no effect for this objective. - deriv_mode : {"auto", "fwd", "rev"} - Specify how to compute jacobian matrix, either forward mode or reverse mode AD. - "auto" selects forward or reverse mode based on the size of the input and output - of the objective. Has no effect on self.grad or self.hess which always use - reverse mode and forward over reverse mode respectively. grid : Grid, optional Collocation grid containing the nodes to evaluate at. Defaults to ``QuadratureGrid(eq.L_grid, eq.M_grid, eq.N_grid)`` for ``Equilibrium`` or ``LinearGrid(M=2*eq.M, N=2*eq.N)`` for ``FourierRZToroidalSurface``. - name : str, optional - Name of the objective function. """ + __doc__ = __doc__.rstrip() + collect_docs() + _scalar = True _units = "(m^3)" _print_value_fmt = "Plasma volume: " @@ -531,31 +453,6 @@ class PlasmaVesselDistance(_Objective): Equilibrium that will be optimized to satisfy the Objective. surface : Surface Bounding surface to penalize distance to. - target : {float, ndarray}, optional - Target value(s) of the objective. Only used if bounds is None. - Must be broadcastable to Objective.dim_f. Defaults to ``bounds=(1,np.inf)``. - bounds : tuple of {float, ndarray}, optional - Lower and upper bounds on the objective. Overrides target. - Both bounds must be broadcastable to to Objective.dim_f. - Defaults to ``bounds=(1,np.inf)``. - weight : {float, ndarray}, optional - Weighting to apply to the Objective, relative to other Objectives. - Must be broadcastable to to Objective.dim_f - normalize : bool, optional - Whether to compute the error in physical units or non-dimensionalize. - normalize_target : bool - Whether target should be normalized before comparing to computed values. - if `normalize` is `True` and the target is in physical units, this should also - be set to True. - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss function - is called on the raw compute value, before any shifting, scaling, or - normalization. - deriv_mode : {"auto", "fwd", "rev"} - Specify how to compute jacobian matrix, either forward mode or reverse mode AD. - "auto" selects forward or reverse mode based on the size of the input and output - of the objective. Has no effect on self.grad or self.hess which always use - reverse mode and forward over reverse mode respectively. surface_grid : Grid, optional Collocation grid containing the nodes to evaluate surface geometry at. Defaults to ``LinearGrid(M=eq.M_grid, N=eq.N_grid)``. @@ -584,10 +481,11 @@ class PlasmaVesselDistance(_Objective): the array by 2/min_val to ensure that softmin_alpha*array>1. Making softmin_alpha larger than this minimum value will make the softmin a more accurate approximation of the true min. - name : str, optional - Name of the objective function. + """ + __doc__ = __doc__.rstrip() + collect_docs() + _coordinates = "rtz" _units = "(m)" _print_value_fmt = "Plasma-vessel distance: " @@ -893,40 +791,15 @@ class MeanCurvature(_Objective): eq : Equilibrium or FourierRZToroidalSurface Equilibrium or FourierRZToroidalSurface that will be optimized to satisfy the Objective. - target : {float, ndarray}, optional - Target value(s) of the objective. Only used if bounds is None. - Must be broadcastable to Objective.dim_f. Defaults to ``bounds=(-np.inf, 0)``. - bounds : tuple of {float, ndarray}, optional - Lower and upper bounds on the objective. Overrides target. - Both bounds must be broadcastable to to Objective.dim_f. - Defaults to ``bounds=(-np.inf, 0)``. - weight : {float, ndarray}, optional - Weighting to apply to the Objective, relative to other Objectives. - Must be broadcastable to to Objective.dim_f - normalize : bool, optional - Whether to compute the error in physical units or non-dimensionalize. - normalize_target : bool - Whether target should be normalized before comparing to computed values. - if `normalize` is `True` and the target is in physical units, this should also - be set to True. - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss function - is called on the raw compute value, before any shifting, scaling, or - normalization. - deriv_mode : {"auto", "fwd", "rev"} - Specify how to compute jacobian matrix, either forward mode or reverse mode AD. - "auto" selects forward or reverse mode based on the size of the input and output - of the objective. Has no effect on self.grad or self.hess which always use - reverse mode and forward over reverse mode respectively. grid : Grid, optional Collocation grid containing the nodes to evaluate at. Defaults to ``LinearGrid(M=eq.M_grid, N=eq.N_grid)`` for ``Equilibrium`` or ``LinearGrid(M=2*eq.M, N=2*eq.N)`` for ``FourierRZToroidalSurface``. - name : str, optional - Name of the objective function. """ + __doc__ = __doc__.rstrip() + collect_docs() + _coordinates = "rtz" _units = "(m^-1)" _print_value_fmt = "Mean curvature: " @@ -1053,40 +926,15 @@ class PrincipalCurvature(_Objective): eq : Equilibrium or FourierRZToroidalSurface Equilibrium or FourierRZToroidalSurface that will be optimized to satisfy the Objective. - target : {float, ndarray}, optional - Target value(s) of the objective. Only used if bounds is None. - Must be broadcastable to Objective.dim_f. Defaults to ``target=1``. - bounds : tuple of {float, ndarray}, optional - Lower and upper bounds on the objective. Overrides target. - Both bounds must be broadcastable to to Objective.dim_f. - Defaults to ``target=1``. - weight : {float, ndarray}, optional - Weighting to apply to the Objective, relative to other Objectives. - Must be broadcastable to to Objective.dim_f - normalize : bool, optional - Whether to compute the error in physical units or non-dimensionalize. - normalize_target : bool - Whether target should be normalized before comparing to computed values. - if `normalize` is `True` and the target is in physical units, this should also - be set to True. - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss function - is called on the raw compute value, before any shifting, scaling, or - normalization. - deriv_mode : {"auto", "fwd", "rev"} - Specify how to compute jacobian matrix, either forward mode or reverse mode AD. - "auto" selects forward or reverse mode based on the size of the input and output - of the objective. Has no effect on self.grad or self.hess which always use - reverse mode and forward over reverse mode respectively. grid : Grid, optional Collocation grid containing the nodes to evaluate at. Defaults to ``LinearGrid(M=eq.M_grid, N=eq.N_grid)`` for ``Equilibrium`` or ``LinearGrid(M=2*eq.M, N=2*eq.N)`` for ``FourierRZToroidalSurface``. - name : str, optional - Name of the objective function. """ + __doc__ = __doc__.rstrip() + collect_docs() + _coordinates = "rtz" _units = "(m^-1)" _print_value_fmt = "Principal curvature: " @@ -1209,39 +1057,14 @@ class BScaleLength(_Objective): ---------- eq : Equilibrium Equilibrium that will be optimized to satisfy the Objective. - target : {float, ndarray}, optional - Target value(s) of the objective. Only used if bounds is None. - Must be broadcastable to Objective.dim_f. Defaults to ``bounds=(1,np.inf)``. - bounds : tuple of {float, ndarray}, optional - Lower and upper bounds on the objective. Overrides target. - Both bounds must be broadcastable to to Objective.dim_f. - Defaults to ``bounds=(1,np.inf)``. - weight : {float, ndarray}, optional - Weighting to apply to the Objective, relative to other Objectives. - Must be broadcastable to to Objective.dim_f - normalize : bool, optional - Whether to compute the error in physical units or non-dimensionalize. - normalize_target : bool - Whether target should be normalized before comparing to computed values. - if `normalize` is `True` and the target is in physical units, this should also - be set to True. - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss function - is called on the raw compute value, before any shifting, scaling, or - normalization. - deriv_mode : {"auto", "fwd", "rev"} - Specify how to compute jacobian matrix, either forward mode or reverse mode AD. - "auto" selects forward or reverse mode based on the size of the input and output - of the objective. Has no effect on self.grad or self.hess which always use - reverse mode and forward over reverse mode respectively. grid : Grid, optional Collocation grid containing the nodes to evaluate at. Defaults to ``LinearGrid(M=eq.M_grid, N=eq.N_grid)``. - name : str, optional - Name of the objective function. """ + __doc__ = __doc__.rstrip() + collect_docs() + _coordinates = "rtz" _units = "(m)" _print_value_fmt = "Magnetic field scale length: " @@ -1361,38 +1184,13 @@ class GoodCoordinates(_Objective): Equilibrium that will be optimized to satisfy the Objective. sigma : float Relative weight between the Jacobian and radial terms. - target : {float, ndarray}, optional - Target value(s) of the objective. Only used if bounds is None. - Must be broadcastable to Objective.dim_f. Defaults to ``target=0``. - bounds : tuple of {float, ndarray}, optional - Lower and upper bounds on the objective. Overrides target. - Both bounds must be broadcastable to to Objective.dim_f. - Defaults to ``target=0``. - weight : {float, ndarray}, optional - Weighting to apply to the Objective, relative to other Objectives. - Must be broadcastable to to Objective.dim_f - normalize : bool, optional - Whether to compute the error in physical units or non-dimensionalize. - normalize_target : bool, optional - Whether target and bounds should be normalized before comparing to computed - values. If `normalize` is `True` and the target is in physical units, - this should also be set to True. - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss function - is called on the raw compute value, before any shifting, scaling, or - normalization. - deriv_mode : {"auto", "fwd", "rev"} - Specify how to compute jacobian matrix, either forward mode or reverse mode AD. - "auto" selects forward or reverse mode based on the size of the input and output - of the objective. Has no effect on self.grad or self.hess which always use - reverse mode and forward over reverse mode respectively. grid : Grid, optional Collocation grid containing the nodes to evaluate at. - name : str, optional - Name of the objective function. """ + __doc__ = __doc__.rstrip() + collect_docs() + _scalar = False _units = "(dimensionless)" _print_value_fmt = "Coordinate goodness : " From ce943ff57f8b07bb064f600df2d47ef690713dbe Mon Sep 17 00:00:00 2001 From: YigitElma Date: Mon, 23 Sep 2024 20:40:53 -0400 Subject: [PATCH 09/31] apply to omnigenity --- desc/objectives/_omnigenity.py | 148 +++------------------------------ 1 file changed, 11 insertions(+), 137 deletions(-) diff --git a/desc/objectives/_omnigenity.py b/desc/objectives/_omnigenity.py index 1eb7a8da6..5717da0b7 100644 --- a/desc/objectives/_omnigenity.py +++ b/desc/objectives/_omnigenity.py @@ -10,7 +10,7 @@ from desc.vmec_utils import ptolemy_linear_transform from .normalization import compute_scaling_factors -from .objective_funs import _Objective +from .objective_funs import _Objective, collect_docs class QuasisymmetryBoozer(_Objective): @@ -20,31 +20,6 @@ class QuasisymmetryBoozer(_Objective): ---------- eq : Equilibrium Equilibrium that will be optimized to satisfy the Objective. - target : {float, ndarray}, optional - Target value(s) of the objective. Only used if bounds is None. - Must be broadcastable to Objective.dim_f. Defaults to ``target=0``. - bounds : tuple of {float, ndarray}, optional - Lower and upper bounds on the objective. Overrides target. - Both bounds must be broadcastable to to Objective.dim_f. - Defaults to ``target=0``. - weight : {float, ndarray}, optional - Weighting to apply to the Objective, relative to other Objectives. - Must be broadcastable to to Objective.dim_f - normalize : bool, optional - Whether to compute the error in physical units or non-dimensionalize. - normalize_target : bool, optional - Whether target and bounds should be normalized before comparing to computed - values. If `normalize` is `True` and the target is in physical units, - this should also be set to True. - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss function - is called on the raw compute value, before any shifting, scaling, or - normalization. - deriv_mode : {"auto", "fwd", "rev"} - Specify how to compute jacobian matrix, either forward mode or reverse mode AD. - "auto" selects forward or reverse mode based on the size of the input and output - of the objective. Has no effect on self.grad or self.hess which always use - reverse mode and forward over reverse mode respectively. grid : Grid, optional Collocation grid containing the nodes to evaluate at. Must be a LinearGrid with sym=False. @@ -55,11 +30,11 @@ class QuasisymmetryBoozer(_Objective): Poloidal resolution of Boozer transformation. Default = 2 * eq.M. N_booz : int, optional Toroidal resolution of Boozer transformation. Default = 2 * eq.N. - name : str, optional - Name of the objective function. """ + __doc__ = __doc__.rstrip() + collect_docs() + _units = "(T)" _print_value_fmt = "Quasi-symmetry Boozer error: " @@ -237,41 +212,16 @@ class QuasisymmetryTwoTerm(_Objective): ---------- eq : Equilibrium Equilibrium that will be optimized to satisfy the Objective. - target : {float, ndarray}, optional - Target value(s) of the objective. Only used if bounds is None. - Must be broadcastable to Objective.dim_f. Defaults to ``target=0``. - bounds : tuple of {float, ndarray}, optional - Lower and upper bounds on the objective. Overrides target. - Both bounds must be broadcastable to to Objective.dim_f. - Defaults to ``target=0``. - weight : {float, ndarray}, optional - Weighting to apply to the Objective, relative to other Objectives. - Must be broadcastable to to Objective.dim_f - normalize : bool, optional - Whether to compute the error in physical units or non-dimensionalize. - normalize_target : bool, optional - Whether target and bounds should be normalized before comparing to computed - values. If `normalize` is `True` and the target is in physical units, - this should also be set to True. - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss function - is called on the raw compute value, before any shifting, scaling, or - normalization. - deriv_mode : {"auto", "fwd", "rev"} - Specify how to compute jacobian matrix, either forward mode or reverse mode AD. - "auto" selects forward or reverse mode based on the size of the input and output - of the objective. Has no effect on self.grad or self.hess which always use - reverse mode and forward over reverse mode respectively. grid : Grid, optional Collocation grid containing the nodes to evaluate at. Defaults to ``LinearGrid(M=eq.M_grid, N=eq.N_grid)``. helicity : tuple, optional Type of quasi-symmetry (M, N). - name : str, optional - Name of the objective function. """ + __doc__ = __doc__.rstrip() + collect_docs() + _coordinates = "rtz" _units = "(T^3)" _print_value_fmt = "Quasi-symmetry two-term error: " @@ -424,39 +374,14 @@ class QuasisymmetryTripleProduct(_Objective): ---------- eq : Equilibrium Equilibrium that will be optimized to satisfy the Objective. - target : {float, ndarray}, optional - Target value(s) of the objective. Only used if bounds is None. - Must be broadcastable to Objective.dim_f. Defaults to ``target=0``. - bounds : tuple of {float, ndarray}, optional - Lower and upper bounds on the objective. Overrides target. - Both bounds must be broadcastable to to Objective.dim_f. - Defaults to ``target=0``. - weight : {float, ndarray}, optional - Weighting to apply to the Objective, relative to other Objectives. - Must be broadcastable to to Objective.dim_f - normalize : bool, optional - Whether to compute the error in physical units or non-dimensionalize. - normalize_target : bool, optional - Whether target and bounds should be normalized before comparing to computed - values. If `normalize` is `True` and the target is in physical units, - this should also be set to True. - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss function - is called on the raw compute value, before any shifting, scaling, or - normalization. - deriv_mode : {"auto", "fwd", "rev"} - Specify how to compute jacobian matrix, either forward mode or reverse mode AD. - "auto" selects forward or reverse mode based on the size of the input and output - of the objective. Has no effect on self.grad or self.hess which always use - reverse mode and forward over reverse mode respectively. grid : Grid, optional Collocation grid containing the nodes to evaluate at. Defaults to ``LinearGrid(M=eq.M_grid, N=eq.N_grid)``. - name : str, optional - Name of the objective function. """ + __doc__ = __doc__.rstrip() + collect_docs() + _coordinates = "rtz" _units = "(T^4/m^2)" _print_value_fmt = "Quasi-symmetry error: " @@ -575,31 +500,6 @@ class Omnigenity(_Objective): Equilibrium to be optimized to satisfy the Objective. field : OmnigenousField Omnigenous magnetic field to be optimized to satisfy the Objective. - target : {float, ndarray}, optional - Target value(s) of the objective. Only used if bounds is None. - Must be broadcastable to Objective.dim_f. Defaults to ``target=0``. - bounds : tuple of {float, ndarray}, optional - Lower and upper bounds on the objective. Overrides target. - Both bounds must be broadcastable to to Objective.dim_f. - Defaults to ``target=0``. - weight : {float, ndarray}, optional - Weighting to apply to the Objective, relative to other Objectives. - Must be broadcastable to to Objective.dim_f - normalize : bool - Whether to compute the error in physical units or non-dimensionalize. - normalize_target : bool - Whether target and bounds should be normalized before comparing to computed - values. If `normalize` is `True` and the target is in physical units, - this should also be set to True. - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss function - is called on the raw compute value, before any shifting, scaling, or - normalization. - deriv_mode : {"auto", "fwd", "rev"} - Specify how to compute jacobian matrix, either forward mode or reverse mode AD. - "auto" selects forward or reverse mode based on the size of the input and output - of the objective. Has no effect on self.grad or self.hess which always use - reverse mode and forward over reverse mode respectively. eq_grid : Grid, optional Collocation grid containing the nodes to evaluate at for equilibrium data. Defaults to a linearly space grid on the rho=1 surface. @@ -630,11 +530,11 @@ class Omnigenity(_Objective): computation time during optimization and self.things = [eq] only. If False, the field is allowed to change during the optimization and its associated data are re-computed at every iteration (Default). - name : str - Name of the objective function. """ + __doc__ = __doc__.rstrip() + collect_docs() + _coordinates = "rtz" _units = "(T)" _print_value_fmt = "Omnigenity error: " @@ -936,40 +836,14 @@ class Isodynamicity(_Objective): ---------- eq : Equilibrium Equilibrium that will be optimized to satisfy the Objective. - target : {float, ndarray}, optional - Target value(s) of the objective. Only used if bounds is None. - Must be broadcastable to Objective.dim_f. Defaults to ``target=0``. - bounds : tuple of {float, ndarray}, optional - Lower and upper bounds on the objective. Overrides target. - Both bounds must be broadcastable to to Objective.dim_f. - Defaults to ``target=0``. - weight : {float, ndarray}, optional - Weighting to apply to the Objective, relative to other Objectives. - Must be broadcastable to to Objective.dim_f - normalize : bool, optional - Whether to compute the error in physical units or non-dimensionalize. - normalize_target : bool, optional - Whether target and bounds should be normalized before comparing to computed - values. If `normalize` is `True` and the target is in physical units, - this should also be set to True. - Has no effect for this objective. - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss function - is called on the raw compute value, before any shifting, scaling, or - normalization. - deriv_mode : {"auto", "fwd", "rev"} - Specify how to compute jacobian matrix, either forward mode or reverse mode AD. - "auto" selects forward or reverse mode based on the size of the input and output - of the objective. Has no effect on self.grad or self.hess which always use - reverse mode and forward over reverse mode respectively. grid : Grid, optional Collocation grid containing the nodes to evaluate at. Defaults to ``LinearGrid(M=eq.M_grid, N=eq.N_grid)``. - name : str, optional - Name of the objective function. """ + __doc__ = __doc__.rstrip() + collect_docs() + _coordinates = "rtz" _units = "(dimensionless)" _print_value_fmt = "Isodynamicity error: " From 728c70d0e41abdfef3acc89d2d69eadc65911f43 Mon Sep 17 00:00:00 2001 From: YigitElma Date: Mon, 23 Sep 2024 20:42:12 -0400 Subject: [PATCH 10/31] apply to power balance --- desc/objectives/_power_balance.py | 60 +++---------------------------- 1 file changed, 5 insertions(+), 55 deletions(-) diff --git a/desc/objectives/_power_balance.py b/desc/objectives/_power_balance.py index 299b24835..0efe0d81b 100644 --- a/desc/objectives/_power_balance.py +++ b/desc/objectives/_power_balance.py @@ -6,7 +6,7 @@ from desc.utils import Timer, errorif from .normalization import compute_scaling_factors -from .objective_funs import _Objective +from .objective_funs import _Objective, collect_docs class FusionPower(_Objective): @@ -24,41 +24,16 @@ class FusionPower(_Objective): ---------- eq : Equilibrium Equilibrium that will be optimized to satisfy the Objective. - target : {float, ndarray}, optional - Target value(s) of the objective. Only used if bounds is None. - Must be broadcastable to Objective.dim_f. Defaults to ``target=1e9``. - bounds : tuple of {float, ndarray}, optional - Lower and upper bounds on the objective. Overrides target. - Both bounds must be broadcastable to to Objective.dim_f. - Defaults to ``target=1e9``. - weight : {float, ndarray}, optional - Weighting to apply to the Objective, relative to other Objectives. - Must be broadcastable to to Objective.dim_f - normalize : bool, optional - Whether to compute the error in physical units or non-dimensionalize. - normalize_target : bool, optional - Whether target and bounds should be normalized before comparing to computed - values. If `normalize` is `True` and the target is in physical units, - this should also be set to True. - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss function - is called on the raw compute value, before any shifting, scaling, or - normalization. Note: Has no effect for this objective. - deriv_mode : {"auto", "fwd", "rev"} - Specify how to compute jacobian matrix, either forward mode or reverse mode AD. - "auto" selects forward or reverse mode based on the size of the input and output - of the objective. Has no effect on self.grad or self.hess which always use - reverse mode and forward over reverse mode respectively. fuel : str, optional Fusion fuel, assuming a 50/50 mix. One of {'DT'}. Default = 'DT'. grid : Grid, optional Collocation grid used to compute the intermediate quantities. Defaults to ``QuadratureGrid(eq.L_grid, eq.M_grid, eq.N_grid, eq.NFP)``. - name : str, optional - Name of the objective function. """ + __doc__ = __doc__.rstrip() + collect_docs() + _scalar = True _units = "(W)" _print_value_fmt = "Fusion power: " @@ -207,31 +182,6 @@ class HeatingPowerISS04(_Objective): ---------- eq : Equilibrium Equilibrium that will be optimized to satisfy the Objective. - target : {float, ndarray}, optional - Target value(s) of the objective. Only used if bounds is None. - Must be broadcastable to Objective.dim_f. Defaults to ``target=0``. - bounds : tuple of {float, ndarray}, optional - Lower and upper bounds on the objective. Overrides target. - Both bounds must be broadcastable to to Objective.dim_f. - Defaults to ``target=0``. - weight : {float, ndarray}, optional - Weighting to apply to the Objective, relative to other Objectives. - Must be broadcastable to to Objective.dim_f - normalize : bool, optional - Whether to compute the error in physical units or non-dimensionalize. - normalize_target : bool, optional - Whether target and bounds should be normalized before comparing to computed - values. If `normalize` is `True` and the target is in physical units, - this should also be set to True. - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss function - is called on the raw compute value, before any shifting, scaling, or - normalization. Note: Has no effect for this objective. - deriv_mode : {"auto", "fwd", "rev"} - Specify how to compute jacobian matrix, either forward mode or reverse mode AD. - "auto" selects forward or reverse mode based on the size of the input and output - of the objective. Has no effect on self.grad or self.hess which always use - reverse mode and forward over reverse mode respectively. H_ISS04 : float, optional ISS04 confinement enhancement factor. Default = 1. gamma : float, optional @@ -239,11 +189,11 @@ class HeatingPowerISS04(_Objective): grid : Grid, optional Collocation grid used to compute the intermediate quantities. Defaults to ``QuadratureGrid(eq.L_grid, eq.M_grid, eq.N_grid, eq.NFP)``. - name : str, optional - Name of the objective function. """ + __doc__ = __doc__.rstrip() + collect_docs() + _scalar = True _units = "(W)" _print_value_fmt = "Heating power: " From 4ef121e6f87a4ed5cbe1bb8f90eb613d140d4bb4 Mon Sep 17 00:00:00 2001 From: YigitElma Date: Mon, 23 Sep 2024 20:45:13 -0400 Subject: [PATCH 11/31] apply to profiles --- desc/objectives/_profiles.py | 90 ++++-------------------------------- 1 file changed, 9 insertions(+), 81 deletions(-) diff --git a/desc/objectives/_profiles.py b/desc/objectives/_profiles.py index d53ee4f08..301829a4f 100644 --- a/desc/objectives/_profiles.py +++ b/desc/objectives/_profiles.py @@ -8,7 +8,7 @@ from desc.utils import Timer, warnif from .normalization import compute_scaling_factors -from .objective_funs import _Objective +from .objective_funs import _Objective, collect_docs from .utils import _parse_callable_target_bounds @@ -30,32 +30,14 @@ class Pressure(_Objective): If a callable, each should take a single argument `rho` and return the desired bound (lower or upper) of the profile at those locations. Defaults to ``target=0``. - weight : {float, ndarray}, optional - Weighting to apply to the Objective, relative to other Objectives. - Must be broadcastable to to Objective.dim_f - normalize : bool, optional - Whether to compute the error in physical units or non-dimensionalize. - normalize_target : bool, optional - Whether target and bounds should be normalized before comparing to computed - values. If `normalize` is `True` and the target is in physical units, - this should also be set to True. - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss function - is called on the raw compute value, before any shifting, scaling, or - normalization. - deriv_mode : {"auto", "fwd", "rev"} - Specify how to compute jacobian matrix, either forward mode or reverse mode AD. - "auto" selects forward or reverse mode based on the size of the input and output - of the objective. Has no effect on self.grad or self.hess which always use - reverse mode and forward over reverse mode respectively. grid : Grid, optional Collocation grid containing the nodes to evaluate at. Defaults to ``LinearGrid(L=eq.L_grid)``. - name : str, optional - Name of the objective function. """ + __doc__ = __doc__.rstrip() + collect_docs(exclude=["target", "bounds"]) + _coordinates = "r" _units = "(Pa)" _print_value_fmt = "Pressure: " @@ -186,34 +168,16 @@ class RotationalTransform(_Objective): If a callable, each should take a single argument `rho` and return the desired bound (lower or upper) of the profile at those locations. Defaults to ``target=0``. - weight : {float, ndarray}, optional - Weighting to apply to the Objective, relative to other Objectives. - Must be broadcastable to to Objective.dim_f - normalize : bool, optional - Whether to compute the error in physical units or non-dimensionalize. - normalize_target : bool, optional - Whether target and bounds should be normalized before comparing to computed - values. If `normalize` is `True` and the target is in physical units, - this should also be set to True. Note: has no effect for this objective. - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss function - is called on the raw compute value, before any shifting, scaling, or - normalization. - deriv_mode : {"auto", "fwd", "rev"} - Specify how to compute jacobian matrix, either forward mode or reverse mode AD. - "auto" selects forward or reverse mode based on the size of the input and output - of the objective. Has no effect on self.grad or self.hess which always use - reverse mode and forward over reverse mode respectively. grid : Grid, optional Collocation grid containing the nodes to evaluate at. Defaults to ``LinearGrid(L=eq.L_grid, M=eq.M_grid, N=eq.N_grid)``. Note that it should have poloidal and toroidal resolution, as flux surface averages are required. - name : str, optional - Name of the objective function. """ + __doc__ = __doc__.rstrip() + collect_docs(exclude=["target", "bounds"]) + _coordinates = "r" _units = "(dimensionless)" _print_value_fmt = "Rotational transform: " @@ -357,34 +321,16 @@ class Shear(_Objective): If a callable, each should take a single argument `rho` and return the desired bound (lower or upper) of the profile at those locations. Defaults to ``target=0``. - weight : {float, ndarray}, optional - Weighting to apply to the Objective, relative to other Objectives. - Must be broadcastable to to Objective.dim_f - normalize : bool, optional - Whether to compute the error in physical units or non-dimensionalize. - normalize_target : bool, optional - Whether target and bounds should be normalized before comparing to computed - values. If `normalize` is `True` and the target is in physical units, - this should also be set to True. Note: has no effect for this objective. - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss function - is called on the raw compute value, before any shifting, scaling, or - normalization. - deriv_mode : {"auto", "fwd", "rev"} - Specify how to compute jacobian matrix, either forward mode or reverse mode AD. - "auto" selects forward or reverse mode based on the size of the input and output - of the objective. Has no effect on self.grad or self.hess which always use - reverse mode and forward over reverse mode respectively. grid : Grid, optional Collocation grid containing the nodes to evaluate at. Defaults to ``LinearGrid(L=eq.L_grid, M=eq.M_grid, N=eq.N_grid)``. Note that it should have poloidal and toroidal resolution, as flux surface averages are required. - name : str, optional - Name of the objective function. """ + __doc__ = __doc__.rstrip() + collect_docs(exclude=["target", "bounds"]) + _coordinates = "r" _units = "(dimensionless)" _print_value_fmt = "Shear: " @@ -524,34 +470,16 @@ class ToroidalCurrent(_Objective): If a callable, each should take a single argument `rho` and return the desired bound (lower or upper) of the profile at those locations. Defaults to ``target=0``. - weight : {float, ndarray}, optional - Weighting to apply to the Objective, relative to other Objectives. - Must be broadcastable to to Objective.dim_f - normalize : bool, optional - Whether to compute the error in physical units or non-dimensionalize. - normalize_target : bool, optional - Whether target and bounds should be normalized before comparing to computed - values. If `normalize` is `True` and the target is in physical units, - this should also be set to True. - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss function - is called on the raw compute value, before any shifting, scaling, or - normalization. - deriv_mode : {"auto", "fwd", "rev"} - Specify how to compute jacobian matrix, either forward mode or reverse mode AD. - "auto" selects forward or reverse mode based on the size of the input and output - of the objective. Has no effect on self.grad or self.hess which always use - reverse mode and forward over reverse mode respectively. grid : Grid, optional Collocation grid containing the nodes to evaluate at. Defaults to ``LinearGrid(L=eq.L_grid, M=eq.M_grid, N=eq.N_grid)``. Note that it should have poloidal and toroidal resolution, as flux surface averages are required. - name : str, optional - Name of the objective function. """ + __doc__ = __doc__.rstrip() + collect_docs(exclude=["target", "bounds"]) + _coordinates = "r" _units = "(A)" _print_value_fmt = "Toroidal current: " From d79c512beae6744585a13ce1eb48dd1fbaaeb755 Mon Sep 17 00:00:00 2001 From: YigitElma Date: Mon, 23 Sep 2024 20:46:53 -0400 Subject: [PATCH 12/31] apply to stability --- desc/objectives/_stability.py | 46 ++++------------------------------- 1 file changed, 5 insertions(+), 41 deletions(-) diff --git a/desc/objectives/_stability.py b/desc/objectives/_stability.py index 47b77f7d9..32921278e 100644 --- a/desc/objectives/_stability.py +++ b/desc/objectives/_stability.py @@ -8,7 +8,7 @@ from desc.utils import Timer, warnif from .normalization import compute_scaling_factors -from .objective_funs import _Objective +from .objective_funs import _Objective, collect_docs from .utils import _parse_callable_target_bounds @@ -38,34 +38,16 @@ class MercierStability(_Objective): If a callable, each should take a single argument `rho` and return the desired bound (lower or upper) of the profile at those locations. Defaults to ``bounds=(0, np.inf)`` - weight : {float, ndarray}, optional - Weighting to apply to the Objective, relative to other Objectives. - Must be broadcastable to to Objective.dim_f - normalize : bool, optional - Whether to compute the error in physical units or non-dimensionalize. - normalize_target : bool, optional - Whether target and bounds should be normalized before comparing to computed - values. If `normalize` is `True` and the target is in physical units, - this should also be set to True. - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss function - is called on the raw compute value, before any shifting, scaling, or - normalization. - deriv_mode : {"auto", "fwd", "rev"} - Specify how to compute jacobian matrix, either forward mode or reverse mode AD. - "auto" selects forward or reverse mode based on the size of the input and output - of the objective. Has no effect on self.grad or self.hess which always use - reverse mode and forward over reverse mode respectively. grid : Grid, optional Collocation grid containing the nodes to evaluate at. Defaults to ``LinearGrid(L=eq.L_grid, M=eq.M_grid, N=eq.N_grid)``. Note that it should have poloidal and toroidal resolution, as flux surface averages are required. - name : str, optional - Name of the objective function. """ + __doc__ = __doc__.rstrip() + collect_docs(exclude=["target", "bounds"]) + _coordinates = "r" _units = "(Wb^-2)" _print_value_fmt = "Mercier Stability: " @@ -219,34 +201,16 @@ class MagneticWell(_Objective): If a callable, each should take a single argument `rho` and return the desired bound (lower or upper) of the profile at those locations. Defaults to ``bounds=(0, np.inf)`` - weight : {float, ndarray}, optional - Weighting to apply to the Objective, relative to other Objectives. - Must be broadcastable to to Objective.dim_f - normalize : bool, optional - Whether to compute the error in physical units or non-dimensionalize. - normalize_target : bool, optional - Whether target and bounds should be normalized before comparing to computed - values. If `normalize` is `True` and the target is in physical units, - this should also be set to True. Note: Has no effect for this objective. - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss function - is called on the raw compute value, before any shifting, scaling, or - normalization. - deriv_mode : {"auto", "fwd", "rev"} - Specify how to compute jacobian matrix, either forward mode or reverse mode AD. - "auto" selects forward or reverse mode based on the size of the input and output - of the objective. Has no effect on self.grad or self.hess which always use - reverse mode and forward over reverse mode respectively. grid : Grid, optional Collocation grid containing the nodes to evaluate at. Defaults to ``LinearGrid(L=eq.L_grid, M=eq.M_grid, N=eq.N_grid)``. Note that it should have poloidal and toroidal resolution, as flux surface averages are required. - name : str, optional - Name of the objective function. """ + __doc__ = __doc__.rstrip() + collect_docs(exclude=["target", "bounds"]) + _coordinates = "r" _units = "(dimensionless)" _print_value_fmt = "Magnetic Well: " From ae8b41caa5443b8c96dd89e47283cf1df4f6b85a Mon Sep 17 00:00:00 2001 From: YigitElma Date: Wed, 25 Sep 2024 15:10:36 -0400 Subject: [PATCH 13/31] fix the ordering with overwrite method --- desc/objectives/_coils.py | 102 +++++++++++++----------------- desc/objectives/_profiles.py | 64 ++++++------------- desc/objectives/_stability.py | 44 ++++++------- desc/objectives/objective_funs.py | 18 +++--- 4 files changed, 94 insertions(+), 134 deletions(-) diff --git a/desc/objectives/_coils.py b/desc/objectives/_coils.py index b029c6057..51adcbf85 100644 --- a/desc/objectives/_coils.py +++ b/desc/objectives/_coils.py @@ -29,17 +29,21 @@ class _CoilObjective(_Objective): Coil for which the data keys will be optimized. data_keys : list of str data keys that will be optimized when this class is inherited. - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss function - is called on the raw compute value, before any shifting, scaling, or - normalization. Operates over all coils, not each individual coil. grid : Grid, list, optional Collocation grid containing the nodes to evaluate at. If a list, must have the same structure as coil. """ - __doc__ = __doc__.rstrip() + collect_docs(exclude=["loss_function"]) + overwrite = { + "loss_function": """ + loss_function : {None, 'mean', 'min', 'max'}, optional + Loss function to apply to the objective values once computed. This loss function + is called on the raw compute value, before any shifting, scaling, or + normalization. Operates over all coils, not each individual coil. + """, + } + __doc__ = __doc__.rstrip() + collect_docs(overwrite=overwrite) def __init__( self, @@ -194,6 +198,17 @@ def compute(self, params, constants=None): return data +overwrite_coil_length = _CoilObjective.overwrite.copy() +overwrite_coil_length[ + "target" +] = """ + target : float, ndarray, optional + Target value(s) of the objective. Only used if bounds is None. + Must be broadcastable to Objective.dim_f. If array, it has to + be flattened according to the number of inputs. + """ + + class CoilLength(_CoilObjective): """Coil length. @@ -201,21 +216,15 @@ class CoilLength(_CoilObjective): ---------- coil : CoilSet or Coil Coil(s) that are to be optimized - target : float, ndarray, optional - Target value(s) of the objective. Only used if bounds is None. - Must be broadcastable to Objective.dim_f. If array, it has to - be flattened according to the number of inputs. Defaults to ``target=2*np.pi``. - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss function - is called on the raw compute value, before any shifting, scaling, or - normalization. Operates over all coils, not each individual coil. grid : Grid, optional Collocation grid containing the nodes to evaluate at. Defaults to ``LinearGrid(N=2 * coil.N + 5)`` """ - __doc__ = __doc__.rstrip() + collect_docs(exclude=["target", "loss_function"]) + overwrite = overwrite_coil_length.copy() + overwrite["target"] += " Defaults to ``target=2*np.pi``." + __doc__ = __doc__.rstrip() + collect_docs(overwrite=overwrite) _scalar = False # Not always a scalar, if a coilset is passed in _units = "(m)" @@ -307,21 +316,14 @@ class CoilCurvature(_CoilObjective): ---------- coil : CoilSet or Coil Coil(s) that are to be optimized - target : float, ndarray, optional - Target value(s) of the objective. Only used if bounds is None. - Must be broadcastable to Objective.dim_f. If array, it has to - be flattened according to the number of inputs. Defaults to ``bounds=(0,1)``. - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss function - is called on the raw compute value, before any shifting, scaling, or - normalization. Operates over all coils, not each individual coil. grid : Grid, optional Collocation grid containing the nodes to evaluate at. Defaults to ``LinearGrid(N=2 * coil.N + 5)`` """ - __doc__ = __doc__.rstrip() + collect_docs(exclude=["target", "loss_function"]) + overwrite = overwrite_coil_length + __doc__ = __doc__.rstrip() + collect_docs(overwrite=overwrite) _scalar = False _units = "(m^-1)" @@ -408,21 +410,15 @@ class CoilTorsion(_CoilObjective): ---------- coil : CoilSet or Coil Coil(s) that are to be optimized - target : float, ndarray, optional - Target value(s) of the objective. Only used if bounds is None. - Must be broadcastable to Objective.dim_f. If array, it has to - be flattened according to the number of inputs. Defaults to ``target=0``. - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss function - is called on the raw compute value, before any shifting, scaling, or - normalization. Operates over all coils, not each individual coil. grid : Grid, optional Collocation grid containing the nodes to evaluate at. Defaults to ``LinearGrid(N=2 * coil.N + 5)`` """ - __doc__ = __doc__.rstrip() + collect_docs(exclude=["target", "loss_function"]) + overwrite = overwrite_coil_length.copy() + overwrite["target"] += " Defaults to ``target=0``." + __doc__ = __doc__.rstrip() + collect_docs(overwrite=overwrite) _scalar = False _units = "(m^-1)" @@ -509,21 +505,15 @@ class CoilCurrentLength(CoilLength): ---------- coil : CoilSet or Coil Coil(s) that are to be optimized - target : float, ndarray, optional - Target value(s) of the objective. Only used if bounds is None. - Must be broadcastable to Objective.dim_f. If array, it has to - be flattened according to the number of inputs. Defaults to ``target=0``. - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss function - is called on the raw compute value, before any shifting, scaling, or - normalization. Operates over all coils, not each individual coil. grid : Grid, optional Collocation grid containing the nodes to evaluate at. Defaults to ``LinearGrid(N=2 * coil.N + 5)`` """ - __doc__ = __doc__.rstrip() + collect_docs(exclude=["target", "loss_function"]) + overwrite = overwrite_coil_length.copy() + overwrite["target"] += " Defaults to ``target=0``." + __doc__ = __doc__.rstrip() + collect_docs(overwrite=overwrite) _scalar = False _units = "(A*m)" @@ -618,14 +608,6 @@ class CoilSetMinDistance(_Objective): ---------- coil : CoilSet Coil(s) that are to be optimized. - target : float, ndarray, optional - Target value(s) of the objective. Only used if bounds is None. - Must be broadcastable to Objective.dim_f. If array, it has to - be flattened according to the number of inputs. - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss function - is called on the raw compute value, before any shifting, scaling, or - normalization. Operates over all coils, not each individial coil. grid : Grid, list, optional Collocation grid used to discretize each coil. Defaults to the default grid for the given coil-type, see ``coils.py`` and ``curve.py`` for more details. @@ -633,7 +615,7 @@ class CoilSetMinDistance(_Objective): """ - __doc__ = __doc__.rstrip() + collect_docs(exclude=["target", "loss_function"]) + __doc__ = __doc__.rstrip() + collect_docs(overwrite=overwrite_coil_length) _scalar = False _units = "(m)" @@ -758,10 +740,6 @@ class PlasmaCoilSetMinDistance(_Objective): to satisfy the Objective. coil : CoilSet Coil(s) that are to be optimized. - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss function - is called on the raw compute value, before any shifting, scaling, or - normalization. Operates over all coils, not each individial coil. plasma_grid : Grid, optional Collocation grid containing the nodes to evaluate plasma geometry at. Defaults to ``LinearGrid(M=eq.M_grid, N=eq.N_grid)``. @@ -785,7 +763,8 @@ class PlasmaCoilSetMinDistance(_Objective): """ - __doc__ = __doc__.rstrip() + collect_docs(exclude=["target", "loss_function"]) + overwrite = {"loss_function": overwrite_coil_length["loss_function"]} + __doc__ = __doc__.rstrip() + collect_docs(overwrite=overwrite) _scalar = False _units = "(m)" @@ -999,7 +978,8 @@ class QuadraticFlux(_Objective): """ - __doc__ = __doc__.rstrip() + collect_docs(exclude=["loss_function"]) + overwrite = {"loss_function": ""} + __doc__ = __doc__.rstrip() + collect_docs(overwrite=overwrite) _scalar = False _linear = False @@ -1189,7 +1169,15 @@ class ToroidalFlux(_Objective): """ - __doc__ = __doc__.rstrip() + collect_docs(exclude=["loss_function"]) + overwrite = { + "loss_function": """ + loss_function : {None, 'mean', 'min', 'max'}, optional + Loss function to apply to the objective values once computed. This function + is called on the raw compute value, before any shifting, scaling, or + normalization. Note: has no effect for this objective. + """ + } + __doc__ = __doc__.rstrip() + collect_docs(overwrite=overwrite) _coordinates = "rtz" _units = "(Wb)" diff --git a/desc/objectives/_profiles.py b/desc/objectives/_profiles.py index 301829a4f..255555a4a 100644 --- a/desc/objectives/_profiles.py +++ b/desc/objectives/_profiles.py @@ -11,32 +11,39 @@ from .objective_funs import _Objective, collect_docs from .utils import _parse_callable_target_bounds - -class Pressure(_Objective): - """Target pressure profile. - - Parameters - ---------- - eq : Equilibrium - Equilibrium that will be optimized to satisfy the Objective. +profile_overwrite = { + "target": """ target : {float, ndarray, callable}, optional Target value(s) of the objective. Only used if bounds is None. Must be broadcastable to Objective.dim_f. If a callable, should take a single argument `rho` and return the desired value of the profile at those locations. Defaults to ``target=0``. + """, + "bounds": """ bounds : tuple of {float, ndarray, callable}, optional Lower and upper bounds on the objective. Overrides target. Both bounds must be broadcastable to to Objective.dim_f If a callable, each should take a single argument `rho` and return the desired bound (lower or upper) of the profile at those locations. Defaults to ``target=0``. + """, +} + + +class Pressure(_Objective): + """Target pressure profile. + + Parameters + ---------- + eq : Equilibrium + Equilibrium that will be optimized to satisfy the Objective. grid : Grid, optional Collocation grid containing the nodes to evaluate at. Defaults to ``LinearGrid(L=eq.L_grid)``. """ - __doc__ = __doc__.rstrip() + collect_docs(exclude=["target", "bounds"]) + __doc__ = __doc__.rstrip() + collect_docs(overwrite=profile_overwrite) _coordinates = "r" _units = "(Pa)" @@ -157,17 +164,6 @@ class RotationalTransform(_Objective): ---------- eq : Equilibrium Equilibrium that will be optimized to satisfy the Objective. - target : {float, ndarray, callable}, optional - Target value(s) of the objective. Only used if bounds is None. - Must be broadcastable to Objective.dim_f. If a callable, should take a - single argument `rho` and return the desired value of the profile at those - locations. Defaults to ``target=0``. - bounds : tuple of {float, ndarray, callable}, optional - Lower and upper bounds on the objective. Overrides target. - Both bounds must be broadcastable to to Objective.dim_f - If a callable, each should take a single argument `rho` and return the - desired bound (lower or upper) of the profile at those locations. - Defaults to ``target=0``. grid : Grid, optional Collocation grid containing the nodes to evaluate at. Defaults to ``LinearGrid(L=eq.L_grid, M=eq.M_grid, N=eq.N_grid)``. Note that @@ -176,7 +172,7 @@ class RotationalTransform(_Objective): """ - __doc__ = __doc__.rstrip() + collect_docs(exclude=["target", "bounds"]) + __doc__ = __doc__.rstrip() + collect_docs(overwrite=profile_overwrite) _coordinates = "r" _units = "(dimensionless)" @@ -310,17 +306,6 @@ class Shear(_Objective): ---------- eq : Equilibrium Equilibrium that will be optimized to satisfy the Objective. - target : {float, ndarray, callable}, optional - Target value(s) of the objective. Only used if bounds is None. - Must be broadcastable to Objective.dim_f. If a callable, should take a - single argument `rho` and return the desired value of the profile at those - locations. Defaults to ``target=0``. - bounds : tuple of {float, ndarray, callable}, optional - Lower and upper bounds on the objective. Overrides target. - Both bounds must be broadcastable to to Objective.dim_f - If a callable, each should take a single argument `rho` and return the - desired bound (lower or upper) of the profile at those locations. - Defaults to ``target=0``. grid : Grid, optional Collocation grid containing the nodes to evaluate at. Defaults to ``LinearGrid(L=eq.L_grid, M=eq.M_grid, N=eq.N_grid)``. Note that @@ -329,7 +314,7 @@ class Shear(_Objective): """ - __doc__ = __doc__.rstrip() + collect_docs(exclude=["target", "bounds"]) + __doc__ = __doc__.rstrip() + collect_docs(overwrite=profile_overwrite) _coordinates = "r" _units = "(dimensionless)" @@ -459,17 +444,6 @@ class ToroidalCurrent(_Objective): ---------- eq : Equilibrium Equilibrium that will be optimized to satisfy the Objective. - target : {float, ndarray, callable}, optional - Target value(s) of the objective. Only used if bounds is None. - Must be broadcastable to Objective.dim_f. If a callable, should take a - single argument `rho` and return the desired value of the profile at those - locations. Defaults to ``target=0``. - bounds : tuple of {float, ndarray, callable}, optional - Lower and upper bounds on the objective. Overrides target. - Both bounds must be broadcastable to to Objective.dim_f - If a callable, each should take a single argument `rho` and return the - desired bound (lower or upper) of the profile at those locations. - Defaults to ``target=0``. grid : Grid, optional Collocation grid containing the nodes to evaluate at. Defaults to ``LinearGrid(L=eq.L_grid, M=eq.M_grid, N=eq.N_grid)``. Note that @@ -478,7 +452,7 @@ class ToroidalCurrent(_Objective): """ - __doc__ = __doc__.rstrip() + collect_docs(exclude=["target", "bounds"]) + __doc__ = __doc__.rstrip() + collect_docs(overwrite=profile_overwrite) _coordinates = "r" _units = "(A)" diff --git a/desc/objectives/_stability.py b/desc/objectives/_stability.py index 32921278e..d61133bdf 100644 --- a/desc/objectives/_stability.py +++ b/desc/objectives/_stability.py @@ -11,6 +11,24 @@ from .objective_funs import _Objective, collect_docs from .utils import _parse_callable_target_bounds +overwrite_stability = { + "target": """ + target : {float, ndarray, callable}, optional + Target value(s) of the objective. Only used if bounds is None. + Must be broadcastable to Objective.dim_f. If a callable, should take a + single argument `rho` and return the desired value of the profile at those + locations. Defaults to ``bounds=(0, np.inf)`` + """, + "bounds": """ + bounds : tuple of {float, ndarray, callable}, optional + Lower and upper bounds on the objective. Overrides target. + Both bounds must be broadcastable to to Objective.dim_f + If a callable, each should take a single argument `rho` and return the + desired bound (lower or upper) of the profile at those locations. + Defaults to ``bounds=(0, np.inf)`` + """, +} + class MercierStability(_Objective): """The Mercier criterion is a fast proxy for MHD stability. @@ -27,17 +45,6 @@ class MercierStability(_Objective): ---------- eq : Equilibrium Equilibrium that will be optimized to satisfy the Objective. - target : {float, ndarray, callable}, optional - Target value(s) of the objective. Only used if bounds is None. - Must be broadcastable to Objective.dim_f. If a callable, should take a - single argument `rho` and return the desired value of the profile at those - locations. Defaults to ``bounds=(0, np.inf)`` - bounds : tuple of {float, ndarray, callable}, optional - Lower and upper bounds on the objective. Overrides target. - Both bounds must be broadcastable to to Objective.dim_f - If a callable, each should take a single argument `rho` and return the - desired bound (lower or upper) of the profile at those locations. - Defaults to ``bounds=(0, np.inf)`` grid : Grid, optional Collocation grid containing the nodes to evaluate at. Defaults to ``LinearGrid(L=eq.L_grid, M=eq.M_grid, N=eq.N_grid)``. Note that @@ -46,7 +53,7 @@ class MercierStability(_Objective): """ - __doc__ = __doc__.rstrip() + collect_docs(exclude=["target", "bounds"]) + __doc__ = __doc__.rstrip() + collect_docs(overwrite=overwrite_stability) _coordinates = "r" _units = "(Wb^-2)" @@ -190,17 +197,6 @@ class MagneticWell(_Objective): ---------- eq : Equilibrium Equilibrium that will be optimized to satisfy the Objective. - target : {float, ndarray, callable}, optional - Target value(s) of the objective. Only used if bounds is None. - Must be broadcastable to Objective.dim_f. If a callable, should take a - single argument `rho` and return the desired value of the profile at those - locations. Defaults to ``bounds=(0, np.inf)`` - bounds : tuple of {float, ndarray, callable}, optional - Lower and upper bounds on the objective. Overrides target. - Both bounds must be broadcastable to to Objective.dim_f - If a callable, each should take a single argument `rho` and return the - desired bound (lower or upper) of the profile at those locations. - Defaults to ``bounds=(0, np.inf)`` grid : Grid, optional Collocation grid containing the nodes to evaluate at. Defaults to ``LinearGrid(L=eq.L_grid, M=eq.M_grid, N=eq.N_grid)``. Note that @@ -209,7 +205,7 @@ class MagneticWell(_Objective): """ - __doc__ = __doc__.rstrip() + collect_docs(exclude=["target", "bounds"]) + __doc__ = __doc__.rstrip() + collect_docs(overwrite=overwrite_stability) _coordinates = "r" _units = "(dimensionless)" diff --git a/desc/objectives/objective_funs.py b/desc/objectives/objective_funs.py index fc7c73316..3ba84c6d3 100644 --- a/desc/objectives/objective_funs.py +++ b/desc/objectives/objective_funs.py @@ -73,15 +73,16 @@ } -def collect_docs(exclude=None): +def collect_docs(overwrite=None): """Collect default parameters for the docstring of Objective. Parameters ---------- - exclude : list, optional - List of strings to exclude from the docstring. If None, all default parameters - are included. Use this argument if you want to specify a special docstring for - a specific parameter in your objective definition. + overwrite : dict, optional + Dict of strings to overwrite from the _Objective's docstring. If None, + all default parameters are included as they are. Use this argument if + you want to specify a special docstring for a specific parameter in + your objective definition. Returns ------- @@ -91,9 +92,10 @@ def collect_docs(exclude=None): """ doc_params = "" for key in docs.keys(): - if exclude is not None and key in exclude: - continue - doc_params += docs[key].rstrip() + if overwrite is not None and key in overwrite.keys(): + doc_params += overwrite[key].rstrip() + else: + doc_params += docs[key].rstrip() return doc_params From 005d6ab83c472840a982a22df1e5ab931df5f279 Mon Sep 17 00:00:00 2001 From: YigitElma Date: Wed, 25 Sep 2024 15:51:44 -0400 Subject: [PATCH 14/31] fix coil docs --- desc/objectives/_coils.py | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/desc/objectives/_coils.py b/desc/objectives/_coils.py index 51adcbf85..1c74c90fa 100644 --- a/desc/objectives/_coils.py +++ b/desc/objectives/_coils.py @@ -38,9 +38,10 @@ class _CoilObjective(_Objective): overwrite = { "loss_function": """ loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss function - is called on the raw compute value, before any shifting, scaling, or - normalization. Operates over all coils, not each individual coil. + Loss function to apply to the objective values once computed. This loss + function is called on the raw compute value, before any shifting, + scaling, or normalization. Operates over all coils, not each individual + coil. """, } __doc__ = __doc__.rstrip() + collect_docs(overwrite=overwrite) @@ -205,8 +206,7 @@ def compute(self, params, constants=None): target : float, ndarray, optional Target value(s) of the objective. Only used if bounds is None. Must be broadcastable to Objective.dim_f. If array, it has to - be flattened according to the number of inputs. - """ + be flattened according to the number of inputs. """ class CoilLength(_CoilObjective): @@ -223,7 +223,7 @@ class CoilLength(_CoilObjective): """ overwrite = overwrite_coil_length.copy() - overwrite["target"] += " Defaults to ``target=2*np.pi``." + overwrite["target"] += " Defaults to ``target=2*np.pi``.\n" __doc__ = __doc__.rstrip() + collect_docs(overwrite=overwrite) _scalar = False # Not always a scalar, if a coilset is passed in @@ -323,6 +323,7 @@ class CoilCurvature(_CoilObjective): """ overwrite = overwrite_coil_length + overwrite["target"] += "\n" __doc__ = __doc__.rstrip() + collect_docs(overwrite=overwrite) _scalar = False @@ -417,7 +418,7 @@ class CoilTorsion(_CoilObjective): """ overwrite = overwrite_coil_length.copy() - overwrite["target"] += " Defaults to ``target=0``." + overwrite["target"] += "Defaults to ``target=0``.\n" __doc__ = __doc__.rstrip() + collect_docs(overwrite=overwrite) _scalar = False @@ -512,7 +513,7 @@ class CoilCurrentLength(CoilLength): """ overwrite = overwrite_coil_length.copy() - overwrite["target"] += " Defaults to ``target=0``." + overwrite["target"] += "Defaults to ``target=0``.\n" __doc__ = __doc__.rstrip() + collect_docs(overwrite=overwrite) _scalar = False @@ -615,7 +616,9 @@ class CoilSetMinDistance(_Objective): """ - __doc__ = __doc__.rstrip() + collect_docs(overwrite=overwrite_coil_length) + overwrite = overwrite_coil_length.copy() + overwrite["target"] += "\n" + __doc__ = __doc__.rstrip() + collect_docs(overwrite=overwrite) _scalar = False _units = "(m)" @@ -1171,10 +1174,10 @@ class ToroidalFlux(_Objective): overwrite = { "loss_function": """ - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This function - is called on the raw compute value, before any shifting, scaling, or - normalization. Note: has no effect for this objective. + loss_function : {None, 'mean', 'min', 'max'}, optional + Loss function to apply to the objective values once computed. This function + is called on the raw compute value, before any shifting, scaling, or + normalization. Note: has no effect for this objective. """ } __doc__ = __doc__.rstrip() + collect_docs(overwrite=overwrite) From 6da22914ea67a3def413d1c66371740c511808c1 Mon Sep 17 00:00:00 2001 From: YigitElma Date: Wed, 25 Sep 2024 16:09:14 -0400 Subject: [PATCH 15/31] fix more coil doc issues --- desc/objectives/_coils.py | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/desc/objectives/_coils.py b/desc/objectives/_coils.py index 1c74c90fa..3b5c607f1 100644 --- a/desc/objectives/_coils.py +++ b/desc/objectives/_coils.py @@ -37,11 +37,11 @@ class _CoilObjective(_Objective): overwrite = { "loss_function": """ - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss - function is called on the raw compute value, before any shifting, - scaling, or normalization. Operates over all coils, not each individual - coil. + loss_function : {None, 'mean', 'min', 'max'}, optional + Loss function to apply to the objective values once computed. This loss + function is called on the raw compute value, before any shifting, + scaling, or normalization. Operates over all coils, not each individual + coil. """, } __doc__ = __doc__.rstrip() + collect_docs(overwrite=overwrite) @@ -223,7 +223,9 @@ class CoilLength(_CoilObjective): """ overwrite = overwrite_coil_length.copy() - overwrite["target"] += " Defaults to ``target=2*np.pi``.\n" + overwrite["target"] = ( + overwrite["target"].rstrip() + " Defaults to ``target=2*np.pi``.\n" + ) __doc__ = __doc__.rstrip() + collect_docs(overwrite=overwrite) _scalar = False # Not always a scalar, if a coilset is passed in @@ -323,7 +325,7 @@ class CoilCurvature(_CoilObjective): """ overwrite = overwrite_coil_length - overwrite["target"] += "\n" + overwrite["target"] = overwrite["target"].rstrip() + "\n" __doc__ = __doc__.rstrip() + collect_docs(overwrite=overwrite) _scalar = False @@ -418,7 +420,7 @@ class CoilTorsion(_CoilObjective): """ overwrite = overwrite_coil_length.copy() - overwrite["target"] += "Defaults to ``target=0``.\n" + overwrite["target"] = overwrite["target"].rstrip() + " Defaults to ``target=0``.\n" __doc__ = __doc__.rstrip() + collect_docs(overwrite=overwrite) _scalar = False @@ -513,7 +515,7 @@ class CoilCurrentLength(CoilLength): """ overwrite = overwrite_coil_length.copy() - overwrite["target"] += "Defaults to ``target=0``.\n" + overwrite["target"] = overwrite["target"].rstrip() + " Defaults to ``target=0``.\n" __doc__ = __doc__.rstrip() + collect_docs(overwrite=overwrite) _scalar = False @@ -617,7 +619,7 @@ class CoilSetMinDistance(_Objective): """ overwrite = overwrite_coil_length.copy() - overwrite["target"] += "\n" + overwrite["target"] = overwrite["target"].rstrip() + "\n" __doc__ = __doc__.rstrip() + collect_docs(overwrite=overwrite) _scalar = False From 3823559d82583900d7e2bb0046c2debc2a185ba7 Mon Sep 17 00:00:00 2001 From: YigitElma Date: Wed, 25 Sep 2024 16:33:05 -0400 Subject: [PATCH 16/31] remove forgotton loss_function doc from toroidal flux objective --- desc/objectives/_coils.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/desc/objectives/_coils.py b/desc/objectives/_coils.py index 3b5c607f1..2925089c0 100644 --- a/desc/objectives/_coils.py +++ b/desc/objectives/_coils.py @@ -1158,10 +1158,6 @@ class ToroidalFlux(_Objective): field : MagneticField MagneticField object, the parameters of this will be optimized to minimize the objective. - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This function - is called on the raw compute value, before any shifting, scaling, or - normalization. Note: has no effect for this objective field_grid : Grid, optional Grid containing the nodes to evaluate field source at on the winding surface. (used if e.g. field is a CoilSet or From b04b703a39235e80bc00878b4cc4bfe0228b8568 Mon Sep 17 00:00:00 2001 From: YigitElma Date: Fri, 27 Sep 2024 11:44:08 -0400 Subject: [PATCH 17/31] add jac_chunk_size to collect_docs: --- desc/objectives/objective_funs.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/desc/objectives/objective_funs.py b/desc/objectives/objective_funs.py index 62164a1af..9eba5f503 100644 --- a/desc/objectives/objective_funs.py +++ b/desc/objectives/objective_funs.py @@ -73,6 +73,19 @@ name : str, optional Name of the objective. """ +doc_jac_chunk_size = """ + jac_chunk_size : int or "auto", optional + Will calculate the Jacobian + ``jac_chunk_size`` columns at a time, instead of all at once. + The memory usage of the Jacobian calculation is roughly + ``memory usage = m0 + m1*jac_chunk_size``: the smaller the chunk size, + the less memory the Jacobian calculation will require (with some baseline + memory usage). The time it takes to compute the Jacobian is roughly + ``t= t0 + t1/jac_chunk_size` so the larger the ``jac_chunk_size``, the faster + the calculation takes, at the cost of requiring more memory. + If None, it will use the largest size i.e ``obj.dim_x``. + Defaults to ``chunk_size=None``. +""" docs = { "target": doc_target, "bounds": doc_bounds, @@ -82,6 +95,7 @@ "loss_function": doc_loss_function, "deriv_mode": doc_deriv_mode, "name": doc_name, + "jac_chunk_size": doc_jac_chunk_size, } From 72f256a06477f11ebeb7d26a9aadef0c7279ae67 Mon Sep 17 00:00:00 2001 From: YigitElma Date: Sat, 28 Sep 2024 14:24:58 -0400 Subject: [PATCH 18/31] make fixes for default values --- desc/objectives/_bootstrap.py | 4 +- desc/objectives/_coils.py | 81 ++++++++++++------------------- desc/objectives/_equilibrium.py | 24 ++++++--- desc/objectives/_free_boundary.py | 12 +++-- desc/objectives/_generic.py | 12 +++-- desc/objectives/_geometry.py | 47 +++++++++++++++--- desc/objectives/_omnigenity.py | 20 ++++++-- desc/objectives/_power_balance.py | 8 ++- desc/objectives/objective_funs.py | 53 +++++++++++++++++++- 9 files changed, 182 insertions(+), 79 deletions(-) diff --git a/desc/objectives/_bootstrap.py b/desc/objectives/_bootstrap.py index 966eedda2..9f6850cb2 100644 --- a/desc/objectives/_bootstrap.py +++ b/desc/objectives/_bootstrap.py @@ -42,7 +42,9 @@ class BootstrapRedlConsistency(_Objective): """ - __doc__ = __doc__.rstrip() + collect_docs() + __doc__ = __doc__.rstrip() + collect_docs( + target_default="``target=0``.", bounds_default="``target=0``." + ) _coordinates = "r" _units = "(T A m^-2)" diff --git a/desc/objectives/_coils.py b/desc/objectives/_coils.py index 7b24adb15..d63f0bee3 100644 --- a/desc/objectives/_coils.py +++ b/desc/objectives/_coils.py @@ -35,16 +35,9 @@ class _CoilObjective(_Objective): """ - overwrite = { - "loss_function": """ - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss - function is called on the raw compute value, before any shifting, - scaling, or normalization. Operates over all coils, not each individual - coil. - """, - } - __doc__ = __doc__.rstrip() + collect_docs(overwrite=overwrite) + __doc__ = __doc__.rstrip() + collect_docs( + coil=True, + ) def __init__( self, @@ -201,16 +194,6 @@ def compute(self, params, constants=None): return data -overwrite_coil_length = _CoilObjective.overwrite.copy() -overwrite_coil_length[ - "target" -] = """ - target : float, ndarray, optional - Target value(s) of the objective. Only used if bounds is None. - Must be broadcastable to Objective.dim_f. If array, it has to - be flattened according to the number of inputs. """ - - class CoilLength(_CoilObjective): """Coil length. @@ -224,11 +207,11 @@ class CoilLength(_CoilObjective): """ - overwrite = overwrite_coil_length.copy() - overwrite["target"] = ( - overwrite["target"].rstrip() + " Defaults to ``target=2*np.pi``.\n" + __doc__ = __doc__.rstrip() + collect_docs( + target_default="``target=2*np.pi``.", + bounds_default="``target=2*np.pi``.", + coil=True, ) - __doc__ = __doc__.rstrip() + collect_docs(overwrite=overwrite) _scalar = False # Not always a scalar, if a coilset is passed in _units = "(m)" @@ -328,9 +311,11 @@ class CoilCurvature(_CoilObjective): """ - overwrite = overwrite_coil_length - overwrite["target"] = overwrite["target"].rstrip() + "\n" - __doc__ = __doc__.rstrip() + collect_docs(overwrite=overwrite) + __doc__ = __doc__.rstrip() + collect_docs( + target_default="``bounds=(0,1).``", + bounds_default="``bounds=(0,1).``", + coil=True, + ) _scalar = False _units = "(m^-1)" @@ -425,9 +410,11 @@ class CoilTorsion(_CoilObjective): """ - overwrite = overwrite_coil_length.copy() - overwrite["target"] = overwrite["target"].rstrip() + " Defaults to ``target=0``.\n" - __doc__ = __doc__.rstrip() + collect_docs(overwrite=overwrite) + __doc__ = __doc__.rstrip() + collect_docs( + target_default="``target=0``.", + bounds_default="``target=0``.", + coil=True, + ) _scalar = False _units = "(m^-1)" @@ -522,9 +509,11 @@ class CoilCurrentLength(CoilLength): """ - overwrite = overwrite_coil_length.copy() - overwrite["target"] = overwrite["target"].rstrip() + " Defaults to ``target=0``.\n" - __doc__ = __doc__.rstrip() + collect_docs(overwrite=overwrite) + __doc__ = __doc__.rstrip() + collect_docs( + target_default="``target=0``.", + bounds_default="``target=0``.", + coil=True, + ) _scalar = False _units = "(A*m)" @@ -628,9 +617,7 @@ class CoilSetMinDistance(_Objective): """ - overwrite = overwrite_coil_length.copy() - overwrite["target"] = overwrite["target"].rstrip() + "\n" - __doc__ = __doc__.rstrip() + collect_docs(overwrite=overwrite) + __doc__ = __doc__.rstrip() + collect_docs(coil=True) _scalar = False _units = "(m)" @@ -780,8 +767,7 @@ class PlasmaCoilSetMinDistance(_Objective): """ - overwrite = {"loss_function": overwrite_coil_length["loss_function"]} - __doc__ = __doc__.rstrip() + collect_docs(overwrite=overwrite) + __doc__ = __doc__.rstrip() + collect_docs(coil=True) _scalar = False _units = "(m)" @@ -997,8 +983,11 @@ class QuadraticFlux(_Objective): """ - overwrite = {"loss_function": ""} - __doc__ = __doc__.rstrip() + collect_docs(overwrite=overwrite) + __doc__ = __doc__.rstrip() + collect_docs( + target_default="``target=0``.", + bounds_default="``target=0``.", + loss_detail=" Note: has no effect for this objective.", + ) _scalar = False _linear = False @@ -1186,15 +1175,9 @@ class ToroidalFlux(_Objective): """ - overwrite = { - "loss_function": """ - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This function - is called on the raw compute value, before any shifting, scaling, or - normalization. Note: has no effect for this objective. - """ - } - __doc__ = __doc__.rstrip() + collect_docs(overwrite=overwrite) + __doc__ = __doc__.rstrip() + collect_docs( + loss_detail=" Note: has no effect for this objective." + ) _coordinates = "rtz" _units = "(Wb)" diff --git a/desc/objectives/_equilibrium.py b/desc/objectives/_equilibrium.py index 68497b230..7be04509e 100644 --- a/desc/objectives/_equilibrium.py +++ b/desc/objectives/_equilibrium.py @@ -39,7 +39,9 @@ class ForceBalance(_Objective): """ - __doc__ = __doc__.rstrip() + collect_docs() + __doc__ = __doc__.rstrip() + collect_docs( + target_default="``target=0``.", bounds_default="``target=0``." + ) _equilibrium = True _coordinates = "rtz" @@ -192,7 +194,9 @@ class ForceBalanceAnisotropic(_Objective): """ - __doc__ = __doc__.rstrip() + collect_docs() + __doc__ = __doc__.rstrip() + collect_docs( + target_default="``target=0``.", bounds_default="``target=0``." + ) _units = "(N)" _coordinates = "rtz" @@ -327,7 +331,9 @@ class RadialForceBalance(_Objective): """ - __doc__ = __doc__.rstrip() + collect_docs() + __doc__ = __doc__.rstrip() + collect_docs( + target_default="``target=0``.", bounds_default="``target=0``." + ) _equilibrium = True _coordinates = "rtz" @@ -462,7 +468,9 @@ class HelicalForceBalance(_Objective): """ - __doc__ = __doc__.rstrip() + collect_docs() + __doc__ = __doc__.rstrip() + collect_docs( + target_default="``target=0``.", bounds_default="``target=0``." + ) _equilibrium = True _coordinates = "rtz" @@ -595,7 +603,9 @@ class Energy(_Objective): """ - __doc__ = __doc__.rstrip() + collect_docs() + __doc__ = __doc__.rstrip() + collect_docs( + target_default="``target=0``.", bounds_default="``target=0``." + ) _scalar = True _coordinates = "" @@ -739,7 +749,9 @@ class CurrentDensity(_Objective): """ - __doc__ = __doc__.rstrip() + collect_docs() + __doc__ = __doc__.rstrip() + collect_docs( + target_default="``target=0``.", bounds_default="``target=0``." + ) _equilibrium = True _coordinates = "rtz" diff --git a/desc/objectives/_free_boundary.py b/desc/objectives/_free_boundary.py index 7892da859..569a0611e 100644 --- a/desc/objectives/_free_boundary.py +++ b/desc/objectives/_free_boundary.py @@ -49,7 +49,9 @@ class VacuumBoundaryError(_Objective): """ - __doc__ = __doc__.rstrip() + collect_docs() + __doc__ = __doc__.rstrip() + collect_docs( + target_default="``target=0``.", bounds_default="``target=0``." + ) _scalar = False _linear = False @@ -363,7 +365,9 @@ class BoundaryError(_Objective): """ - __doc__ = __doc__.rstrip() + collect_docs() + __doc__ = __doc__.rstrip() + collect_docs( + target_default="``target=0``.", bounds_default="``target=0``." + ) __doc__ += """ Examples -------- @@ -798,7 +802,9 @@ class BoundaryErrorNESTOR(_Objective): """ - __doc__ = __doc__.rstrip() + collect_docs() + __doc__ = __doc__.rstrip() + collect_docs( + target_default="``target=0``.", bounds_default="``target=0``." + ) _scalar = False _linear = False diff --git a/desc/objectives/_generic.py b/desc/objectives/_generic.py index 07666fd99..8e16e61cf 100644 --- a/desc/objectives/_generic.py +++ b/desc/objectives/_generic.py @@ -32,7 +32,9 @@ class GenericObjective(_Objective): """ - __doc__ = __doc__.rstrip() + collect_docs() + __doc__ = __doc__.rstrip() + collect_docs( + target_default="``target=0``.", bounds_default="``target=0``." + ) _print_value_fmt = "Generic objective value: " @@ -166,7 +168,9 @@ class LinearObjectiveFromUser(_FixedObjective): """ - __doc__ = __doc__.rstrip() + collect_docs() + __doc__ = __doc__.rstrip() + collect_docs( + target_default="``target=0``.", bounds_default="``target=0``." + ) _scalar = False _linear = True @@ -278,7 +282,9 @@ class ObjectiveFromUser(_Objective): """ - __doc__ = __doc__.rstrip() + collect_docs() + __doc__ = __doc__.rstrip() + collect_docs( + target_default="``target=0``.", bounds_default="``target=0``." + ) __doc__ += """ Examples -------- diff --git a/desc/objectives/_geometry.py b/desc/objectives/_geometry.py index 1ba6c8426..ae6061395 100644 --- a/desc/objectives/_geometry.py +++ b/desc/objectives/_geometry.py @@ -28,7 +28,13 @@ class AspectRatio(_Objective): """ - __doc__ = __doc__.rstrip() + collect_docs() + __doc__ = __doc__.rstrip() + collect_docs( + target_default="``target=2``.", + bounds_default="``target=2``.", + normalize_detail=" Note: Has no effect for this objective.", + normalize_target_detail=" Note: Has no effect for this objective.", + loss_detail=" Note: Has no effect for this objective.", + ) _scalar = True _units = "(dimensionless)" @@ -166,7 +172,13 @@ class Elongation(_Objective): """ - __doc__ = __doc__.rstrip() + collect_docs() + __doc__ = __doc__.rstrip() + collect_docs( + target_default="``target=1``.", + bounds_default="``target=1``.", + normalize_detail=" Note: Has no effect for this objective.", + normalize_target_detail=" Note: Has no effect for this objective.", + loss_detail=" Note: Has no effect for this objective.", + ) _scalar = True _units = "(dimensionless)" @@ -303,7 +315,11 @@ class Volume(_Objective): """ - __doc__ = __doc__.rstrip() + collect_docs() + __doc__ = __doc__.rstrip() + collect_docs( + target_default="``target=1``.", + bounds_default="``target=1``.", + loss_detail=" Note: Has no effect for this objective.", + ) _scalar = True _units = "(m^3)" @@ -490,7 +506,10 @@ class PlasmaVesselDistance(_Objective): """ - __doc__ = __doc__.rstrip() + collect_docs() + __doc__ = __doc__.rstrip() + collect_docs( + target_default="``bounds=(1,np.inf)``.", + bounds_default="``bounds=(1,np.inf)``.", + ) _coordinates = "rtz" _units = "(m)" @@ -806,7 +825,10 @@ class MeanCurvature(_Objective): """ - __doc__ = __doc__.rstrip() + collect_docs() + __doc__ = __doc__.rstrip() + collect_docs( + target_default="``bounds=(-np.inf,0)``.", + bounds_default="``bounds=(-np.inf,0)``.", + ) _coordinates = "rtz" _units = "(m^-1)" @@ -943,7 +965,10 @@ class PrincipalCurvature(_Objective): """ - __doc__ = __doc__.rstrip() + collect_docs() + __doc__ = __doc__.rstrip() + collect_docs( + target_default="``target=1``.", + bounds_default="``target=1``.", + ) _coordinates = "rtz" _units = "(m^-1)" @@ -1075,7 +1100,10 @@ class BScaleLength(_Objective): """ - __doc__ = __doc__.rstrip() + collect_docs() + __doc__ = __doc__.rstrip() + collect_docs( + target_default="``bounds=(1,np.inf)``.", + bounds_default="``bounds=(1,np.inf)``.", + ) _coordinates = "rtz" _units = "(m)" @@ -1203,7 +1231,10 @@ class GoodCoordinates(_Objective): """ - __doc__ = __doc__.rstrip() + collect_docs() + __doc__ = __doc__.rstrip() + collect_docs( + target_default="``target=0``.", + bounds_default="``target=0``.", + ) _scalar = False _units = "(dimensionless)" diff --git a/desc/objectives/_omnigenity.py b/desc/objectives/_omnigenity.py index fbd0cbf47..e992a970d 100644 --- a/desc/objectives/_omnigenity.py +++ b/desc/objectives/_omnigenity.py @@ -33,7 +33,9 @@ class QuasisymmetryBoozer(_Objective): """ - __doc__ = __doc__.rstrip() + collect_docs() + __doc__ = __doc__.rstrip() + collect_docs( + target_default="``target=0``.", bounds_default="``target=0``." + ) _units = "(T)" _print_value_fmt = "Quasi-symmetry Boozer error: " @@ -222,7 +224,9 @@ class QuasisymmetryTwoTerm(_Objective): """ - __doc__ = __doc__.rstrip() + collect_docs() + __doc__ = __doc__.rstrip() + collect_docs( + target_default="``target=0``.", bounds_default="``target=0``." + ) _coordinates = "rtz" _units = "(T^3)" @@ -384,7 +388,9 @@ class QuasisymmetryTripleProduct(_Objective): """ - __doc__ = __doc__.rstrip() + collect_docs() + __doc__ = __doc__.rstrip() + collect_docs( + target_default="``target=0``.", bounds_default="``target=0``." + ) _coordinates = "rtz" _units = "(T^4/m^2)" @@ -539,7 +545,9 @@ class Omnigenity(_Objective): """ - __doc__ = __doc__.rstrip() + collect_docs() + __doc__ = __doc__.rstrip() + collect_docs( + target_default="``target=0``.", bounds_default="``target=0``." + ) _coordinates = "rtz" _units = "(T)" @@ -850,7 +858,9 @@ class Isodynamicity(_Objective): """ - __doc__ = __doc__.rstrip() + collect_docs() + __doc__ = __doc__.rstrip() + collect_docs( + target_default="``target=0``.", bounds_default="``target=0``." + ) _coordinates = "rtz" _units = "(dimensionless)" diff --git a/desc/objectives/_power_balance.py b/desc/objectives/_power_balance.py index c4f01dc7c..e72bcb5f1 100644 --- a/desc/objectives/_power_balance.py +++ b/desc/objectives/_power_balance.py @@ -32,7 +32,9 @@ class FusionPower(_Objective): """ - __doc__ = __doc__.rstrip() + collect_docs() + __doc__ = __doc__.rstrip() + collect_docs( + target_default="``target=1e9``.", bounds_default="``target=1e9``." + ) _scalar = True _units = "(W)" @@ -194,7 +196,9 @@ class HeatingPowerISS04(_Objective): """ - __doc__ = __doc__.rstrip() + collect_docs() + __doc__ = __doc__.rstrip() + collect_docs( + target_default="``target=0``.", bounds_default="``target=0``." + ) _scalar = True _units = "(W)" diff --git a/desc/objectives/objective_funs.py b/desc/objectives/objective_funs.py index 9eba5f503..b8d23769c 100644 --- a/desc/objectives/objective_funs.py +++ b/desc/objectives/objective_funs.py @@ -99,7 +99,15 @@ } -def collect_docs(overwrite=None): +def collect_docs( + overwrite=None, + target_default="", + bounds_default="", + normalize_detail=None, + normalize_target_detail=None, + loss_detail=None, + coil=False, +): """Collect default parameters for the docstring of Objective. Parameters @@ -109,6 +117,19 @@ def collect_docs(overwrite=None): all default parameters are included as they are. Use this argument if you want to specify a special docstring for a specific parameter in your objective definition. + target_default : str, optional + Default value for the target parameter. + bounds_default : str, optional + Default value for the bounds parameter. + normalize_detail : str, optional + Additional information about the normalize parameter. + normalize_target_detail : str, optional + Additional information about the normalize_target parameter. + loss_detail : str, optional + Additional information about the loss function. + coil : bool, optional + Whether the objective is a coil objective. If True, adds extra docs to + target and loss_function. Returns ------- @@ -121,7 +142,35 @@ def collect_docs(overwrite=None): if overwrite is not None and key in overwrite.keys(): doc_params += overwrite[key].rstrip() else: - doc_params += docs[key].rstrip() + if key == "target": + target = "" + if coil: + target += "If array, it has to be flattened according to the " + +"number of inputs." + if target_default != "": + target += " Defaults to " + target_default + doc_params += docs[key].rstrip() + target + elif key == "bounds" and bounds_default != "": + doc_params += docs[key].rstrip() + " Defaults to " + bounds_default + elif key == "loss_function": + loss = "" + if coil: + loss = " Operates over all coils, not each individual coil." + if loss_detail is not None: + loss += loss_detail + doc_params += docs[key].rstrip() + loss + elif key == "normalize": + norm = "" + if normalize_detail is not None: + norm += normalize_detail + doc_params += docs[key].rstrip() + norm + elif key == "normalize_target": + norm_target = "" + if normalize_target_detail is not None: + norm_target = normalize_target_detail + doc_params += docs[key].rstrip() + norm_target + else: + doc_params += docs[key].rstrip() return doc_params From bd9b47f84f7537c3e46d4718975ac4b1cb2bbb36 Mon Sep 17 00:00:00 2001 From: YigitElma Date: Sat, 28 Sep 2024 16:48:14 -0400 Subject: [PATCH 19/31] fix bug --- desc/objectives/objective_funs.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/desc/objectives/objective_funs.py b/desc/objectives/objective_funs.py index b8d23769c..758efbb4d 100644 --- a/desc/objectives/objective_funs.py +++ b/desc/objectives/objective_funs.py @@ -145,13 +145,17 @@ def collect_docs( if key == "target": target = "" if coil: - target += "If array, it has to be flattened according to the " - +"number of inputs." + target += ( + "If array, it has to be flattened according to the " + + "number of inputs." + ) if target_default != "": - target += " Defaults to " + target_default + target = target + " Defaults to " + target_default doc_params += docs[key].rstrip() + target elif key == "bounds" and bounds_default != "": - doc_params += docs[key].rstrip() + " Defaults to " + bounds_default + doc_params = ( + doc_params + docs[key].rstrip() + " Defaults to " + bounds_default + ) elif key == "loss_function": loss = "" if coil: From 633d081fc83c991177a1e477865594b6dff65855 Mon Sep 17 00:00:00 2001 From: Yigit Gunsur Elmacioglu <102380275+YigitElma@users.noreply.github.com> Date: Mon, 30 Sep 2024 13:54:34 -0400 Subject: [PATCH 20/31] Update desc/objectives/objective_funs.py Co-authored-by: Kaya Unalmis --- desc/objectives/objective_funs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/desc/objectives/objective_funs.py b/desc/objectives/objective_funs.py index 758efbb4d..9a0e61be3 100644 --- a/desc/objectives/objective_funs.py +++ b/desc/objectives/objective_funs.py @@ -44,7 +44,7 @@ doc_weight = """ weight : {float, ndarray}, optional Weighting to apply to the Objective, relative to other Objectives. - Must be broadcastable to to Objective.dim_f + Must be broadcastable to Objective.dim_f """ doc_normalize = """ normalize : bool, optional From bf5c539b9d9ccc6786106559b5cfb0491fbe05b9 Mon Sep 17 00:00:00 2001 From: Yigit Gunsur Elmacioglu <102380275+YigitElma@users.noreply.github.com> Date: Mon, 30 Sep 2024 13:54:42 -0400 Subject: [PATCH 21/31] Update desc/objectives/objective_funs.py Co-authored-by: Kaya Unalmis --- desc/objectives/objective_funs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/desc/objectives/objective_funs.py b/desc/objectives/objective_funs.py index 9a0e61be3..7cf55cd92 100644 --- a/desc/objectives/objective_funs.py +++ b/desc/objectives/objective_funs.py @@ -64,7 +64,7 @@ """ doc_deriv_mode = """ deriv_mode : {"auto", "fwd", "rev"} - Specify how to compute jacobian matrix, either forward mode or reverse mode AD. + Specify how to compute Jacobian matrix, either forward mode or reverse mode AD. "auto" selects forward or reverse mode based on the size of the input and output of the objective. Has no effect on self.grad or self.hess which always use reverse mode and forward over reverse mode respectively. From a1b45c8353057b28a4dfc4426ce3b3ead185c80e Mon Sep 17 00:00:00 2001 From: Yigit Gunsur Elmacioglu <102380275+YigitElma@users.noreply.github.com> Date: Mon, 30 Sep 2024 13:54:50 -0400 Subject: [PATCH 22/31] Update desc/objectives/objective_funs.py Co-authored-by: Kaya Unalmis --- desc/objectives/objective_funs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/desc/objectives/objective_funs.py b/desc/objectives/objective_funs.py index 7cf55cd92..4d859982d 100644 --- a/desc/objectives/objective_funs.py +++ b/desc/objectives/objective_funs.py @@ -39,7 +39,7 @@ doc_bounds = """ bounds : tuple of {float, ndarray}, optional Lower and upper bounds on the objective. Overrides target. - Both bounds must be broadcastable to to Objective.dim_f + Both bounds must be broadcastable to Objective.dim_f """ doc_weight = """ weight : {float, ndarray}, optional From 966938ffde3e78bb57db15b733e8047ee7734dd2 Mon Sep 17 00:00:00 2001 From: YigitElma Date: Mon, 30 Sep 2024 15:11:56 -0400 Subject: [PATCH 23/31] add missing info --- desc/objectives/_coils.py | 16 +++++++++++++--- desc/objectives/_geometry.py | 1 - desc/objectives/_power_balance.py | 8 ++++++-- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/desc/objectives/_coils.py b/desc/objectives/_coils.py index d63f0bee3..3961fbb81 100644 --- a/desc/objectives/_coils.py +++ b/desc/objectives/_coils.py @@ -617,7 +617,11 @@ class CoilSetMinDistance(_Objective): """ - __doc__ = __doc__.rstrip() + collect_docs(coil=True) + __doc__ = __doc__.rstrip() + collect_docs( + target_default="``bounds=(1,np.inf)``.", + bounds_default="``bounds=(1,np.inf)``.", + coil=True, + ) _scalar = False _units = "(m)" @@ -767,7 +771,11 @@ class PlasmaCoilSetMinDistance(_Objective): """ - __doc__ = __doc__.rstrip() + collect_docs(coil=True) + __doc__ = __doc__.rstrip() + collect_docs( + target_default="``bounds=(1,np.inf)``.", + bounds_default="``bounds=(1,np.inf)``.", + coil=True, + ) _scalar = False _units = "(m)" @@ -1176,7 +1184,9 @@ class ToroidalFlux(_Objective): """ __doc__ = __doc__.rstrip() + collect_docs( - loss_detail=" Note: has no effect for this objective." + target_default="``target=eq.Psi``.", + bounds_default="``target=eq.Psi``.", + loss_detail=" Note: has no effect for this objective.", ) _coordinates = "rtz" diff --git a/desc/objectives/_geometry.py b/desc/objectives/_geometry.py index ae6061395..65fa1cf82 100644 --- a/desc/objectives/_geometry.py +++ b/desc/objectives/_geometry.py @@ -177,7 +177,6 @@ class Elongation(_Objective): bounds_default="``target=1``.", normalize_detail=" Note: Has no effect for this objective.", normalize_target_detail=" Note: Has no effect for this objective.", - loss_detail=" Note: Has no effect for this objective.", ) _scalar = True diff --git a/desc/objectives/_power_balance.py b/desc/objectives/_power_balance.py index e72bcb5f1..bc291cb8a 100644 --- a/desc/objectives/_power_balance.py +++ b/desc/objectives/_power_balance.py @@ -33,7 +33,9 @@ class FusionPower(_Objective): """ __doc__ = __doc__.rstrip() + collect_docs( - target_default="``target=1e9``.", bounds_default="``target=1e9``." + target_default="``target=1e9``.", + bounds_default="``target=1e9``.", + loss_detail=" Note: Has no effect for this objective.", ) _scalar = True @@ -197,7 +199,9 @@ class HeatingPowerISS04(_Objective): """ __doc__ = __doc__.rstrip() + collect_docs( - target_default="``target=0``.", bounds_default="``target=0``." + target_default="``target=0``.", + bounds_default="``target=0``.", + loss_detail=" Note: Has no effect for this objective.", ) _scalar = True From 85d485a889a9fd9ed8fcab3f07b6cf075a2827b2 Mon Sep 17 00:00:00 2001 From: YigitElma Date: Mon, 30 Sep 2024 15:19:02 -0400 Subject: [PATCH 24/31] add missing info for profiles and stability --- desc/objectives/_profiles.py | 12 ++++++++++-- desc/objectives/_stability.py | 6 +++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/desc/objectives/_profiles.py b/desc/objectives/_profiles.py index 97885aebf..0d0a522e4 100644 --- a/desc/objectives/_profiles.py +++ b/desc/objectives/_profiles.py @@ -174,7 +174,11 @@ class RotationalTransform(_Objective): """ - __doc__ = __doc__.rstrip() + collect_docs(overwrite=profile_overwrite) + __doc__ = __doc__.rstrip() + collect_docs( + overwrite=profile_overwrite, + normalize_detail=" Note: Has no effect for this objective.", + normalize_target_detail=" Note: Has no effect for this objective.", + ) _coordinates = "r" _units = "(dimensionless)" @@ -318,7 +322,11 @@ class Shear(_Objective): """ - __doc__ = __doc__.rstrip() + collect_docs(overwrite=profile_overwrite) + __doc__ = __doc__.rstrip() + collect_docs( + overwrite=profile_overwrite, + normalize_detail=" Note: Has no effect for this objective.", + normalize_target_detail=" Note: Has no effect for this objective.", + ) _coordinates = "r" _units = "(dimensionless)" diff --git a/desc/objectives/_stability.py b/desc/objectives/_stability.py index 8f0b30e6b..02da27459 100644 --- a/desc/objectives/_stability.py +++ b/desc/objectives/_stability.py @@ -208,7 +208,11 @@ class MagneticWell(_Objective): """ - __doc__ = __doc__.rstrip() + collect_docs(overwrite=overwrite_stability) + __doc__ = __doc__.rstrip() + collect_docs( + overwrite=overwrite_stability, + normalize_detail=" Note: Has no effect for this objective.", + normalize_target_detail=" Note: Has no effect for this objective.", + ) _coordinates = "r" _units = "(dimensionless)" From 1e3141b9ef093eec2b0261f1a674aca0a85027c4 Mon Sep 17 00:00:00 2001 From: Rory Conlin Date: Mon, 30 Sep 2024 16:37:11 -0400 Subject: [PATCH 25/31] Update rules for chunking jacobian --- desc/objectives/objective_funs.py | 48 +++++++++++++++---------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/desc/objectives/objective_funs.py b/desc/objectives/objective_funs.py index 9cdfb61c2..88ae520e4 100644 --- a/desc/objectives/objective_funs.py +++ b/desc/objectives/objective_funs.py @@ -113,14 +113,6 @@ def __init__( self._compiled = False self._name = name - def _set_derivatives(self): - """Choose derivative mode based on mode of sub-objectives.""" - if self._deriv_mode == "auto": - if all((obj._deriv_mode == "fwd") for obj in self.objectives): - self._deriv_mode = "batched" - else: - self._deriv_mode = "blocked" - def _unjit(self): """Remove jit compiled methods.""" methods = [ @@ -178,12 +170,20 @@ def build(self, use_jit=None, verbose=1): else: self._scalar = False - self._set_derivatives() + self._set_things() + + # setting derivative mode and chunking. + errorif( + isposint(self._jac_chunk_size) and self._deriv_mode in ["auto", "blocked"], + ValueError, + "'jac_chunk_size' was passed into ObjectiveFunction, but the " + "ObjectiveFunction is not using 'batched' deriv_mode", + ) sub_obj_jac_chunk_sizes_are_ints = [ isposint(obj._jac_chunk_size) for obj in self.objectives ] errorif( - any(sub_obj_jac_chunk_sizes_are_ints) and self._deriv_mode != "blocked", + any(sub_obj_jac_chunk_sizes_are_ints) and self._deriv_mode == "batched", ValueError, "'jac_chunk_size' was passed into one or more sub-objectives, but the" " ObjectiveFunction is using 'batched' deriv_mode, so sub-objective " @@ -192,21 +192,12 @@ def build(self, use_jit=None, verbose=1): " Specify 'blocked' deriv_mode if each sub-objective is desired to have a " "different 'jac_chunk_size' for its Jacobian computation.", ) - errorif( - self._jac_chunk_size not in ["auto", None] - and self._deriv_mode == "blocked", - ValueError, - "'jac_chunk_size' was passed into ObjectiveFunction, but the " - "ObjectiveFunction is using 'blocked' deriv_mode, so sub-objective " - "'jac_chunk_size' are used to compute each sub-objective's Jacobian, " - "`ignoring the ObjectiveFunction's 'jac_chunk_size'.", - ) - - if not self.use_jit: - self._unjit() - self._set_things() - self._built = True + if self._deriv_mode == "auto": + if all((obj._deriv_mode == "fwd") for obj in self.objectives): + self._deriv_mode = "batched" + else: + self._deriv_mode = "blocked" if self._jac_chunk_size == "auto": # Heuristic estimates of fwd mode Jacobian memory usage, @@ -218,6 +209,15 @@ def build(self, use_jit=None, verbose=1): * self.dim_x ) self._jac_chunk_size = max([1, max_chunk_size]) + if self._deriv_mode == "blocked": + for obj in self.objectives: + if obj._jac_chunk_size is None: + obj._jac_chunk_size = self._jac_chunk_size + + if not self.use_jit: + self._unjit() + + self._built = True timer.stop("Objective build") if verbose > 1: From 04121b18905630a1b91bb9be206b1d04fd2793f9 Mon Sep 17 00:00:00 2001 From: Rory Conlin Date: Tue, 1 Oct 2024 15:27:11 -0400 Subject: [PATCH 26/31] Allow accessing dim_f during objective build --- desc/objectives/objective_funs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/desc/objectives/objective_funs.py b/desc/objectives/objective_funs.py index 88ae520e4..ae1e29420 100644 --- a/desc/objectives/objective_funs.py +++ b/desc/objectives/objective_funs.py @@ -799,7 +799,7 @@ def dim_x(self): @property def dim_f(self): """int: Number of objective equations.""" - if not self.built: + if not hasattr(self, "_dim_f"): raise RuntimeError("ObjectiveFunction must be built first.") return self._dim_f From 3e3a07086b61db366afc0ba184589e376fc21839 Mon Sep 17 00:00:00 2001 From: Rory Conlin Date: Tue, 1 Oct 2024 16:02:44 -0400 Subject: [PATCH 27/31] Use compatible deriv mode if jac_chunk_size is specified in getters --- desc/objectives/getters.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/desc/objectives/getters.py b/desc/objectives/getters.py index 727c6f183..7d4772a8b 100644 --- a/desc/objectives/getters.py +++ b/desc/objectives/getters.py @@ -1,6 +1,6 @@ """Utilities for getting standard groups of objectives and constraints.""" -from desc.utils import flatten_list, is_any_instance, unique_list +from desc.utils import flatten_list, is_any_instance, isposint, unique_list from ._equilibrium import Energy, ForceBalance, HelicalForceBalance, RadialForceBalance from .linear_objectives import ( @@ -86,7 +86,10 @@ def get_equilibrium_objective(eq, mode="force", normalize=True, jac_chunk_size=" objectives = (RadialForceBalance(**kwargs), HelicalForceBalance(**kwargs)) else: raise ValueError("got an unknown equilibrium objective type '{}'".format(mode)) - return ObjectiveFunction(objectives, jac_chunk_size=jac_chunk_size) + deriv_mode = "batched" if isposint(jac_chunk_size) else "auto" + return ObjectiveFunction( + objectives, jac_chunk_size=jac_chunk_size, deriv_mode=deriv_mode + ) def get_fixed_axis_constraints(eq, profiles=True, normalize=True): From 195753d8e79a30cce748bc645fd640b4eddbfe89 Mon Sep 17 00:00:00 2001 From: Rory Conlin Date: Tue, 1 Oct 2024 20:52:16 -0400 Subject: [PATCH 28/31] Update tests for new chunking rules --- tests/test_examples.py | 1 + tests/test_objective_funs.py | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/test_examples.py b/tests/test_examples.py index 53fb6479b..93c700b36 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -1043,6 +1043,7 @@ def test_freeb_vacuum(): objective = ObjectiveFunction( VacuumBoundaryError(eq=eq, field=ext_field, field_fixed=True), jac_chunk_size=1000, + deriv_mode="batched", ) eq, _ = eq.optimize( objective, diff --git a/tests/test_objective_funs.py b/tests/test_objective_funs.py index cfbf09090..0413a6492 100644 --- a/tests/test_objective_funs.py +++ b/tests/test_objective_funs.py @@ -1323,6 +1323,7 @@ def test_derivative_modes(): AspectRatio(eq), ], deriv_mode="batched", + jac_chunk_size="auto", use_jit=False, ) obj2 = ObjectiveFunction( @@ -1332,13 +1333,15 @@ def test_derivative_modes(): AspectRatio(eq, jac_chunk_size=None), ], deriv_mode="blocked", + jac_chunk_size="auto", use_jit=False, ) obj1.build() obj2.build() # check that default size works for blocked - assert obj2.objectives[1]._jac_chunk_size is None - assert obj2.objectives[2]._jac_chunk_size is None + assert obj2.objectives[0]._jac_chunk_size == 2 + assert obj2.objectives[1]._jac_chunk_size > 0 + assert obj2.objectives[2]._jac_chunk_size > 0 # hard to say what size auto will give, just check it is >0 assert obj1._jac_chunk_size > 0 obj3.build() From 5c2674362190bfda1099bdec0d83430d8ba2615b Mon Sep 17 00:00:00 2001 From: YigitElma Date: Wed, 2 Oct 2024 13:28:08 -0400 Subject: [PATCH 29/31] remove loss details for QuadraticFlux --- desc/objectives/_coils.py | 1 - 1 file changed, 1 deletion(-) diff --git a/desc/objectives/_coils.py b/desc/objectives/_coils.py index 3961fbb81..9d6267e53 100644 --- a/desc/objectives/_coils.py +++ b/desc/objectives/_coils.py @@ -994,7 +994,6 @@ class QuadraticFlux(_Objective): __doc__ = __doc__.rstrip() + collect_docs( target_default="``target=0``.", bounds_default="``target=0``.", - loss_detail=" Note: has no effect for this objective.", ) _scalar = False From b7a0558d5a8514a2ac9db008961159e47c925ed5 Mon Sep 17 00:00:00 2001 From: Rory Conlin Date: Wed, 2 Oct 2024 22:40:55 -0400 Subject: [PATCH 30/31] Update desc/objectives/objective_funs.py Co-authored-by: Yigit Gunsur Elmacioglu <102380275+YigitElma@users.noreply.github.com> --- desc/objectives/objective_funs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/desc/objectives/objective_funs.py b/desc/objectives/objective_funs.py index ae1e29420..e66bfdbde 100644 --- a/desc/objectives/objective_funs.py +++ b/desc/objectives/objective_funs.py @@ -186,7 +186,7 @@ def build(self, use_jit=None, verbose=1): any(sub_obj_jac_chunk_sizes_are_ints) and self._deriv_mode == "batched", ValueError, "'jac_chunk_size' was passed into one or more sub-objectives, but the" - " ObjectiveFunction is using 'batched' deriv_mode, so sub-objective " + " ObjectiveFunction is using 'batched' deriv_mode, so sub-objective " "'jac_chunk_size' will be ignored in favor of the ObjectiveFunction's " f"'jac_chunk_size' of {self._jac_chunk_size}." " Specify 'blocked' deriv_mode if each sub-objective is desired to have a " From ec60a82e3fb96a942799fbd81be7098bf3fc5536 Mon Sep 17 00:00:00 2001 From: YigitElma Date: Fri, 4 Oct 2024 15:52:34 -0400 Subject: [PATCH 31/31] update contributing.rst --- docs/adding_objectives.rst | 46 +++++++++----------------------------- 1 file changed, 10 insertions(+), 36 deletions(-) diff --git a/docs/adding_objectives.rst b/docs/adding_objectives.rst index 31192c991..2fa3028ba 100644 --- a/docs/adding_objectives.rst +++ b/docs/adding_objectives.rst @@ -47,42 +47,16 @@ A full example objective with comments describing the key points is given below: ---------- eq : Equilibrium Equilibrium that will be optimized to satisfy the Objective. - target : {float, ndarray}, optional - Target value(s) of the objective. Only used if bounds is None. - Must be broadcastable to Objective.dim_f. - bounds : tuple of {float, ndarray}, optional - Lower and upper bounds on the objective. Overrides target. - Both bounds must be broadcastable to to Objective.dim_f - weight : {float, ndarray}, optional - Weighting to apply to the Objective, relative to other Objectives. - Must be broadcastable to to Objective.dim_f - normalize : bool, optional - Whether to compute the error in physical units or non-dimensionalize. - normalize_target : bool, optional - Whether target and bounds should be normalized before comparing to computed - values. If `normalize` is `True` and the target is in physical units, - this should also be set to True. - loss_function : {None, 'mean', 'min', 'max'}, optional - Loss function to apply to the objective values once computed. This loss function - is called on the raw compute value, before any shifting, scaling, or - normalization. grid : Grid, optional Collocation grid containing the nodes to evaluate at. - name : str, optional - Name of the objective function. - jac_chunk_size : int or "auto", optional - Will calculate the Jacobian for this objective ``jac_chunk_size`` - columns at a time, instead of all at once. The memory usage of the - Jacobian calculation is roughly ``memory usage = m0 + m1*jac_chunk_size``: - the smaller the chunk size, the less memory the Jacobian calculation - will require (with some baseline memory usage). The time to compute the - Jacobian is roughly ``t=t0 +t1/jac_chunk_size``, so the larger the - ``jac_chunk_size``, the faster the calculation takes, at the cost of - requiring more memory. A ``jac_chunk_size`` of 1 corresponds to the least - memory intensive, but slowest method of calculating the Jacobian. - If None, it will use the largest possible size. """ + # Most of the documentation is shared among all objectives, so we just inherit + # the docstring from the base class and add a few details specific to this objective. + # See the documentation of `collect_docs` for more details. + __doc__ = __doc__.rstrip() + collect_docs( + target_default="``target=0``.", bounds_default="``target=0``." + ) _coordinates = "rtz" # What coordinates is this objective a function of, with r=rho, t=theta, z=zeta? # i.e. if only a profile, it is "r" , while if all 3 coordinates it is "rtz" @@ -229,12 +203,12 @@ you will have to manually convert these vectors using the geometry utility funct ``rpz2xyz`` and/or ``rpz2xyz_vec``. See the ``PlasmaVesselDistance`` objective for an example of this. -Adapting Existing Objectives with Different Loss Funtions ---------------------------------------------------------- +Adapting Existing Objectives with Different Loss Functions +---------------------------------------------------------- If your desired objective is already implemented in DESC, but not in the correct form, -a few different loss functions are available through the the ``loss_function`` kwarg -when instantiating an Objective objective to modify the objective cost in order to adapt +a few different loss functions are available through the ``loss_function`` kwarg +when instantiating an Objective, to modify the objective cost in order to adapt the objective to your desired purpose. For example, the DESC ``RotationalTransform`` objective with ``target=iota_target`` by default forms the residual by taking the target and subtracting it from the profile at the points in the grid, resulting in a residual