Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow for optimizing multiple objects #604

Merged
merged 113 commits into from
Oct 28, 2023
Merged
Show file tree
Hide file tree
Changes from 104 commits
Commits
Show all changes
113 commits
Select commit Hold shift + click to select a range
bdf1dee
Remove arg order in favor of alphabetic ordering
f0uriest Dec 21, 2022
abfafb4
Add Optimizeable base class
f0uriest Jul 18, 2023
56d7913
Make Equilibrium Optimizeable
f0uriest Jul 18, 2023
709e1a5
Merge branch 'rc/arg_order' into rc/optimizeable
f0uriest Jul 18, 2023
f9017fb
Move optimizeable_parameters to method, add docs
f0uriest Jul 19, 2023
16fa782
Remove more instances of arg_order
f0uriest Jul 19, 2023
2fce2b2
Remove double setting of objective args
f0uriest Jul 19, 2023
1b20d82
Merge branch 'master' into rc/optimizeable
f0uriest Jul 19, 2023
f50cccf
Merge branch 'rc/equilibrium' into rc/optimizeable
f0uriest Jul 20, 2023
b12f67a
Merge branch 'master' into rc/optimizeable
f0uriest Jul 20, 2023
da35e2e
Sort args in reverse alphabetical order
f0uriest Jul 20, 2023
e175fa9
Adjust tolerance on QIC test
f0uriest Jul 20, 2023
50733d4
Remove arg_order from constraint wrappers
f0uriest Jul 20, 2023
582550a
Merge branch 'rc/compute_geometry' into rc/optimizeable
f0uriest Jul 20, 2023
78bf82b
Make curves, surfaces, coils Optimizeable
f0uriest Jul 20, 2023
501af24
Remove blocked jacobian option for now
f0uriest Jul 21, 2023
f557814
Merge branch 'rc/geometry' into rc/optimizeable
f0uriest Jul 21, 2023
f217405
Merge branch 'rc/compute_geometry' into rc/optimizeable
f0uriest Jul 21, 2023
70d89cf
Remove argwise derivatives from objectives
f0uriest Jul 24, 2023
c3ea183
Make all objective compute methods take consistent inputs
f0uriest Jul 24, 2023
4b078d0
Remove args attribute from objectives
f0uriest Jul 24, 2023
d3b3517
Allow flatten_list to also flatten tuples
f0uriest Jul 24, 2023
476522f
Make get_instance return None if no valid items are present
f0uriest Jul 24, 2023
10b7bd7
Remove references to eq from LinearConstraintProjection
f0uriest Jul 24, 2023
7c6e275
Fix indexing bug
f0uriest Jul 24, 2023
76ee779
Refactor constraint projection in vmec load
f0uriest Jul 25, 2023
107e754
Add things attribute to objectives
f0uriest Jul 25, 2023
e8513b5
Break objective get_* utils to their own file
f0uriest Jul 25, 2023
443b965
Copy arrays into params_dict, add dim_x attribute to optimizeables
f0uriest Jul 26, 2023
4141331
Remove x_idx and dimensions from objectives
f0uriest Jul 26, 2023
69d38d6
Refactor modes/target tests - need FixPressure since all args are now…
f0uriest Jul 26, 2023
c76085e
Relabel unit/regression tests for speed/efficiency
f0uriest Jul 26, 2023
bcf1c8f
Remove args and dimensions from objective class
f0uriest Jul 26, 2023
d1b3b58
Merge branch 'master' into rc/optimizeable
f0uriest Jul 31, 2023
1b248de
Merge branch 'rc/compute_geometry' into rc/optimizeable
f0uriest Jul 31, 2023
9f6839c
Simplify wrapped attributes in constraint wrappers
f0uriest Jul 31, 2023
b7c195f
Make PlasmaVesselDistance be a function of both equilibrium and surface
f0uriest Jul 31, 2023
704d335
Add attributes and methods for dealing with multi-object optimization
f0uriest Jul 31, 2023
68d0027
Merge branch 'rc/compute_geometry' into rc/optimizeable
f0uriest Jul 31, 2023
c5f2f40
Merge branch 'master' into rc/optimizeable
f0uriest Aug 7, 2023
f8c77ca
Merge branch 'master' into rc/optimizeable
f0uriest Aug 9, 2023
2e4d136
Merge branch 'master' into rc/optimizeable
f0uriest Aug 14, 2023
818548d
Update baseline images
f0uriest Aug 14, 2023
57309c0
Update notebooks with new API changes
f0uriest Aug 14, 2023
e308bc1
Merge branch 'master' into rc/optimizeable
f0uriest Aug 15, 2023
49d96a7
Merge branch 'rc/tests' into rc/optimizeable
f0uriest Aug 15, 2023
af99067
Merge branch 'master' into rc/optimizeable
f0uriest Aug 15, 2023
a740cf4
Merge branch 'rc/optimizeable' of github.com:PlasmaControl/DESC into …
f0uriest Aug 15, 2023
fbedf63
Update baseline images, mpl==3.5.0
f0uriest Aug 15, 2023
7b51eb6
Merge branch 'master' into rc/optimizeable
f0uriest Aug 18, 2023
93e459d
Merge branch 'master' into rc/optimizeable
f0uriest Aug 23, 2023
993a66a
Fix spelling
f0uriest Aug 23, 2023
342192e
Update baseline images
f0uriest Aug 23, 2023
d273f67
Merge branch 'master' into rc/optimizeable
f0uriest Aug 24, 2023
e36d695
Merge branch 'master' into rc/optimizeable
f0uriest Aug 26, 2023
42fcdee
Merge branch 'rc/hotfix' into rc/optimizeable
f0uriest Aug 26, 2023
ccdf1ae
Merge branch 'master' into rc/optimizeable
f0uriest Aug 28, 2023
1a74915
Merge branch 'rc/optimizeable' of github.com:PlasmaControl/DESC into …
f0uriest Aug 28, 2023
7507040
Massage test data
f0uriest Aug 28, 2023
c4e29b2
Revert "Massage test data"
f0uriest Aug 29, 2023
36c7f58
Merge branch 'master' into rc/optimizeable
f0uriest Aug 29, 2023
08a995d
Revert baseline images
f0uriest Aug 29, 2023
f8e67db
Add back arg_order for Equilibrium
f0uriest Aug 29, 2023
73cf57c
Ensure correct equilibrium is passed to optimize
f0uriest Aug 30, 2023
5056ab4
Reorder parsing of constraints in Optimizer.optimize
f0uriest Aug 30, 2023
df48cba
Add methods to flatten/unflatten trees of things or params
f0uriest Aug 30, 2023
102c3fa
Add extra guards for setting things attributes
f0uriest Aug 30, 2023
4425291
Have Optimizer.optimize return optimized things
f0uriest Aug 30, 2023
0dfac5f
Merge branch 'master' into rc/optimizeable
f0uriest Sep 1, 2023
965feb6
Fix failing tests
f0uriest Sep 1, 2023
dd857c2
Merge branch 'master' into rc/optimizeable
f0uriest Sep 3, 2023
5522e4e
Merge branch 'master' into rc/optimizeable
f0uriest Sep 10, 2023
70679e5
Merge branch 'master' into rc/optimizeable
f0uriest Sep 13, 2023
d27b7ce
Merge branch 'master' into rc/optimizeable
f0uriest Sep 19, 2023
de62622
Add constraints for fixing arbitrary degrees of freedom
f0uriest Sep 19, 2023
c2cb3c8
Fix leftover from merge
f0uriest Sep 19, 2023
be26659
Merge branch 'master' into rc/optimizeable
dpanici Sep 26, 2023
16460d0
Merge branch 'master' into rc/optimizeable
dpanici Oct 3, 2023
6bf436e
Address some reviewer comments
f0uriest Oct 4, 2023
067c9a4
Add test for fixing arbitrary parameter
f0uriest Oct 4, 2023
bf8dd1f
Merge branch 'master' into rc/optimizeable
f0uriest Oct 5, 2023
d07833a
fix order of if statement ensure constraints are tuple in optimize, a…
dpanici Oct 6, 2023
26a73f7
Update anisotropic stuff to work with optimizable
f0uriest Oct 6, 2023
a4320da
Make equilibrium a required argument for objectives, remove eq from b…
f0uriest Oct 6, 2023
be07251
Merge branch 'rc/optimizeable' of github.com:PlasmaControl/DESC into …
dpanici Oct 6, 2023
eb6ad4b
Merge branch 'master' into rc/optimizeable
f0uriest Oct 6, 2023
1e58218
Update notebook to pass in eq when getting constraints
f0uriest Oct 6, 2023
b67b2e4
Merge branch 'master' into rc/optimizeable
f0uriest Oct 7, 2023
ba7fcba
Merge branch 'master' into rc/optimizeable
f0uriest Oct 7, 2023
ba3d471
Merge branch 'master' into rc/optimizeable
f0uriest Oct 10, 2023
f9b0eee
Merge branch 'master' into rc/optimizeable
f0uriest Oct 11, 2023
4af00f0
Merge branch 'master' into rc/optimizeable
f0uriest Oct 12, 2023
dbe194b
Merge branch 'master' into rc/optimizeable
f0uriest Oct 12, 2023
43a0fd0
Merge branch 'master' into rc/optimizeable
f0uriest Oct 13, 2023
22c885b
Merge branch 'master' into rc/optimizeable
f0uriest Oct 13, 2023
ca57fab
Merge branch 'master' into rc/optimizeable
f0uriest Oct 16, 2023
ceb4e84
add test for changing things of an obj
dpanici Oct 16, 2023
145962a
Merge branch 'rc/optimizeable' of github.com:PlasmaControl/DESC into …
dpanici Oct 16, 2023
ce950e5
expand test for PlasmaVEsselDistance, have that objective change its …
dpanici Oct 16, 2023
6828436
Merge branch 'master' into rc/optimizeable
f0uriest Oct 17, 2023
0178e09
Ensure objectives are rebuilt after changing things
f0uriest Oct 17, 2023
d243898
fix tests
dpanici Oct 17, 2023
646a138
Merge branch 'master' into rc/optimizeable
dpanici Oct 19, 2023
13c3a59
Merge branch 'master' into rc/optimizeable
dpanici Oct 20, 2023
624df5d
fix small error in notebooks where comparison of constraints from man…
dpanici Oct 20, 2023
2e3c187
Merge branch 'rc/optimizeable' of github.com:PlasmaControl/DESC into …
dpanici Oct 20, 2023
1d7f2da
fix some incorrect text in notebook
dpanici Oct 20, 2023
548e0a0
Merge branch 'master' into rc/optimizeable
dpanici Oct 20, 2023
a6d56c7
Merge branch 'master' into rc/optimizeable
f0uriest Oct 24, 2023
daaabdc
Fix typos
f0uriest Oct 24, 2023
1bd1581
Merge branch 'master' into rc/optimizeable
f0uriest Oct 24, 2023
8360881
Merge branch 'master' into rc/optimizeable
f0uriest Oct 25, 2023
5767948
Merge branch 'master' into rc/optimizeable
f0uriest Oct 27, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion desc/coils.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
)
from desc.grid import LinearGrid
from desc.magnetic_fields import _MagneticField
from desc.optimizable import Optimizable, optimizable_parameter
from desc.utils import equals, errorif, flatten_list


Expand Down Expand Up @@ -110,7 +111,7 @@ def biot_savart_quad(eval_pts, coil_pts, tangents, current):
return B


class _Coil(_MagneticField, ABC):
class _Coil(_MagneticField, Optimizable, ABC):
"""Base class representing a magnetic field coil.

Represents coils as a combination of a Curve and current
Expand All @@ -134,6 +135,7 @@ def __init__(self, current, *args, **kwargs):
self._current = float(current)
super().__init__(*args, **kwargs)

@optimizable_parameter
@property
def current(self):
"""float: Current passing through the coil, in Amperes."""
Expand Down
1 change: 0 additions & 1 deletion desc/compute/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@
from .data_index import data_index
from .geom_utils import rpz2xyz, rpz2xyz_vec, xyz2rpz, xyz2rpz_vec
from .utils import (
arg_order,
compute,
get_data_deps,
get_derivs,
Expand Down
19 changes: 11 additions & 8 deletions desc/compute/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,17 @@

from .data_index import data_index

# map from profile name to equilibrium parameter name
profile_names = {
"pressure": "p_l",
"iota": "i_l",
"current": "c_l",
"electron_temperature": "Te_l",
"electron_density": "ne_l",
"ion_temperature": "Ti_l",
"atomic_number": "Zeff_l",
}


def _parse_parameterization(p):
if isinstance(p, str):
Expand All @@ -23,10 +34,6 @@ def _parse_parameterization(p):
return module + "." + klass.__qualname__


def _sort_args(args):
return [arg for arg in arg_order if arg in args]


def compute(parameterization, names, params, transforms, profiles, data=None, **kwargs):
"""Compute the quantity given by name on grid.

Expand Down Expand Up @@ -283,10 +290,6 @@ def get_params(keys, obj, has_axis=False, **kwargs):
params = []
for key in deps:
params += data_index[p][key]["dependencies"]["params"]
if p == "desc.equilibrium.equilibrium.Equilibrium":
# probably need some way to distinguish between params from different instances
# of the same class?
params = _sort_args(list(set(params)))
if isinstance(obj, str) or inspect.isclass(obj):
return params
temp_params = {}
Expand Down
84 changes: 38 additions & 46 deletions desc/continuation.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import numpy as np
from termcolor import colored

from desc.compute import arg_order
from desc.equilibrium import EquilibriaFamily, Equilibrium
from desc.objectives import get_equilibrium_objective, get_fixed_boundary_constraints
from desc.optimize import Optimizer
Expand Down Expand Up @@ -75,12 +74,6 @@ def _solve_axisym(

if not isinstance(optimizer, Optimizer):
optimizer = Optimizer(optimizer)
constraints_i = get_fixed_boundary_constraints(
eq=eqi,
iota=objective != "vacuum" and eq.iota is not None,
kinetic=eq.electron_temperature is not None,
)
objective_i = get_equilibrium_objective(eq=eqi, mode=objective)

eqfam = EquilibriaFamily()

Expand All @@ -105,6 +98,13 @@ def _solve_axisym(
deltas = get_deltas({"surface": surf_i}, {"surface": surf_i2})
surf_i = surf_i2

constraints_i = get_fixed_boundary_constraints(
f0uriest marked this conversation as resolved.
Show resolved Hide resolved
eq=eqi,
iota=eqi.iota,
kinetic=eqi.electron_temperature,
)
objective_i = get_equilibrium_objective(eq=eqi, mode=objective)

if verbose:
_print_iteration_summary(
ii,
Expand All @@ -118,12 +118,6 @@ def _solve_axisym(
optimizer,
)

constraints_i = get_fixed_boundary_constraints(
eq=eqi,
iota=objective != "vacuum" and eq.iota is not None,
kinetic=eq.electron_temperature is not None,
)
objective_i = get_equilibrium_objective(eq=eqi, mode=objective)
if len(deltas) > 0:
if verbose > 0:
print("Perturbing equilibrium")
Expand Down Expand Up @@ -215,13 +209,6 @@ def _add_pressure(
# make sure its at full radial/poloidal resolution
eqi.change_resolution(L=eq.L, M=eq.M, L_grid=eq.L_grid, M_grid=eq.M_grid)

constraints_i = get_fixed_boundary_constraints(
eq=eqi,
iota=objective != "vacuum" and eq.iota is not None,
kinetic=eq.electron_temperature is not None,
)
objective_i = get_equilibrium_objective(eq=eqi, mode=objective)

pres_steps = (
0
if (abs(eq.pressure(np.linspace(0, 1, 20))) < 1e-14).all() or pres_step == 0
Expand All @@ -240,6 +227,13 @@ def _add_pressure(
deltas["p_l"] *= pres_step
pres_ratio += pres_step

constraints_i = get_fixed_boundary_constraints(
eq=eqi,
iota=eqi.iota,
kinetic=eqi.electron_temperature,
)
objective_i = get_equilibrium_objective(eq=eqi, mode=objective)

if verbose:
_print_iteration_summary(
ii,
Expand Down Expand Up @@ -347,13 +341,6 @@ def _add_shaping(
# make sure its at full resolution
eqi.change_resolution(eq.L, eq.M, eq.N, eq.L_grid, eq.M_grid, eq.N_grid)

constraints_i = get_fixed_boundary_constraints(
eq=eqi,
iota=objective != "vacuum" and eq.iota is not None,
kinetic=eq.electron_temperature is not None,
)
objective_i = get_equilibrium_objective(eq=eqi, mode=objective)

bdry_steps = 0 if eq.N == 0 or bdry_step == 0 else int(np.ceil(1 / bdry_step))
bdry_ratio = 0 if eq.N else 1

Expand All @@ -373,6 +360,13 @@ def _add_shaping(
deltas["Zb_lmn"] *= bdry_step
bdry_ratio += bdry_step

constraints_i = get_fixed_boundary_constraints(
eq=eqi,
iota=eqi.iota,
kinetic=eqi.electron_temperature,
)
objective_i = get_equilibrium_objective(eq=eqi, mode=objective)

if verbose:
_print_iteration_summary(
ii,
Expand Down Expand Up @@ -578,10 +572,7 @@ def solve_continuation_automatic( # noqa: C901
verbose,
checkpoint_path,
)
for arg in arg_order:
val = np.asarray(getattr(eqfam[-1], arg))
if val.size:
setattr(eq, arg, val)
eq.params_dict = eqfam[-1].params_dict
eqfam[-1] = eq
timer.stop("Total time")
if verbose > 0:
Expand Down Expand Up @@ -670,9 +661,9 @@ def solve_continuation( # noqa: C901

if not isinstance(optimizer, Optimizer):
optimizer = Optimizer(optimizer)
objective_i = get_equilibrium_objective(eq=eqfam[-1], mode=objective)
objective_i = get_equilibrium_objective(eq=eqfam[0], mode=objective)
constraints_i = get_fixed_boundary_constraints(
eq=eqfam[-1],
eq=eqfam[0],
iota=objective != "vacuum" and eqfam[0].iota is not None,
kinetic=eqfam[0].electron_temperature is not None,
)
Expand Down Expand Up @@ -716,20 +707,17 @@ def solve_continuation( # noqa: C901
}
deltas = get_deltas(things1, things2)

# maybe rebuild objective if resolution changed.
if eqfam[ii - 1].resolution != eqi.resolution:
objective_i = get_equilibrium_objective(eq=eqfam[ii], mode=objective)
constraints_i = get_fixed_boundary_constraints(
eq=eqfam[ii],
iota=objective != "vacuum" and eqfam[ii].iota is not None,
kinetic=eqfam[ii].electron_temperature is not None,
)

if len(deltas) > 0:
if verbose > 0:
print("Perturbing equilibrium")
# TODO: pass Jx if available
eqp = eqfam[ii - 1].copy()
objective_i = get_equilibrium_objective(eq=eqp, mode=objective)
constraints_i = get_fixed_boundary_constraints(
eq=eqp,
iota=eqp.iota,
kinetic=eqp.electron_temperature,
)
eqp.change_resolution(**eqi.resolution)
eqp.perturb(
objective=objective_i,
Expand All @@ -739,17 +727,21 @@ def solve_continuation( # noqa: C901
verbose=verbose,
copy=False,
)
for arg in arg_order:
val = np.asarray(getattr(eqp, arg))
if val.size:
setattr(eqi, arg, val)
eqi.params_dict = eqp.params_dict
deltas = {}
del eqp

if not eqi.is_nested(msg="manual"):
stop = True

if not stop:
# TODO: add ability to rebind objectives
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what prevents this currently? does binding an objective not just say which eq to build with?

objective_i = get_equilibrium_objective(eq=eqi, mode=objective)
constraints_i = get_fixed_boundary_constraints(
eq=eqi,
iota=eqi.iota,
kinetic=eqi.electron_temperature,
)
eqi.solve(
optimizer=optimizer,
objective=objective_i,
Expand Down
Loading