Skip to content

Commit

Permalink
Merge branch 'master' into integrate_on_boundary
Browse files Browse the repository at this point in the history
  • Loading branch information
unalmis committed Oct 6, 2024
2 parents 01e212f + 6c599b4 commit d7c6d26
Show file tree
Hide file tree
Showing 17 changed files with 158 additions and 30 deletions.
14 changes: 8 additions & 6 deletions desc/objectives/_free_boundary.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from desc.integrals import DFTInterpolator, FFTInterpolator, virtual_casing_biot_savart
from desc.nestor import Nestor
from desc.objectives.objective_funs import _Objective
from desc.utils import PRINT_WIDTH, Timer, errorif, warnif
from desc.utils import PRINT_WIDTH, Timer, errorif, parse_argname_change, warnif

from .normalization import compute_scaling_factors

Expand Down Expand Up @@ -63,7 +63,7 @@ class VacuumBoundaryError(_Objective):
"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
eval_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)``
field_grid : Grid, optional
Expand Down Expand Up @@ -104,15 +104,17 @@ def __init__(
normalize_target=True,
loss_function=None,
deriv_mode="auto",
grid=None,
eval_grid=None,
field_grid=None,
field_fixed=False,
name="Vacuum boundary error",
jac_chunk_size=None,
**kwargs,
):
eval_grid = parse_argname_change(eval_grid, kwargs, "grid", "eval_grid")
if target is None and bounds is None:
target = 0
self._grid = grid
self._eval_grid = eval_grid
self._eq = eq
self._field = field
self._field_grid = field_grid
Expand Down Expand Up @@ -146,12 +148,12 @@ def build(self, use_jit=True, verbose=1):
"""
eq = self.things[0]
if self._grid is None:
if self._eval_grid is None:
grid = LinearGrid(
rho=np.array([1.0]), M=eq.M_grid, N=eq.N_grid, NFP=eq.NFP, sym=False
)
else:
grid = self._grid
grid = self._eval_grid

pres = np.max(np.abs(eq.compute("p")["p"]))
curr = np.max(np.abs(eq.compute("current")["current"]))
Expand Down
4 changes: 2 additions & 2 deletions desc/objectives/_omnigenity.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ def build(self, use_jit=True, verbose=1):
M_booz=M_booz,
N_booz=N_booz,
)
matrix, modes, idx = ptolemy_linear_transform(
matrix, _, idx = ptolemy_linear_transform(
transforms["B"].basis.modes,
helicity=self.helicity,
NFP=transforms["B"].basis.NFP,
Expand All @@ -180,7 +180,7 @@ def build(self, use_jit=True, verbose=1):
if verbose > 1:
timer.disp("Precomputing transforms")

self._dim_f = idx.size
self._dim_f = idx.size * grid.num_rho

if self._normalize:
scales = compute_scaling_factors(eq)
Expand Down
2 changes: 1 addition & 1 deletion desc/objectives/linear_objectives.py
Original file line number Diff line number Diff line change
Expand Up @@ -3065,7 +3065,7 @@ def build(self, use_jit=True, verbose=1):
np.logical_and((basis.modes[:, 1] % 2 == 0), basis.modes[:, 1] > 0),
)
)[0]
mm = basis.modes[idx_m, 2]
mm = basis.modes[idx_m, 1]
self._A[i, idx_0] = 1
self._A[i, idx_m] = (mm % 2 - 1) * (mm % 4 - 1)

Expand Down
82 changes: 67 additions & 15 deletions desc/plotting.py
Original file line number Diff line number Diff line change
Expand Up @@ -860,7 +860,15 @@ def plot_3d(
* ``cmap``: string denoting colormap to use.
* ``levels``: array of data values where ticks on colorbar should be placed.
* ``alpha``: float in [0,1.0], the transparency of the plotted surface
* ``showscale``: Bool, whether or not to show the colorbar. True by default
* ``showscale``: Bool, whether or not to show the colorbar. True by default.
* ``showgrid``: Bool, whether or not to show the coordinate grid lines.
True by default.
* ``showticklabels``: Bool, whether or not to show the coordinate tick labels.
True by default.
* ``showaxislabels``: Bool, whether or not to show the coordinate axis labels.
True by default.
* ``zeroline``: Bool, whether or not to show the zero coordinate axis lines.
True by default.
* ``field``: MagneticField, a magnetic field with which to calculate Bn on
the surface, must be provided if Bn is entered as the variable to plot.
* ``field_grid``: MagneticField, a Grid to pass to the field as a source grid
Expand Down Expand Up @@ -950,6 +958,10 @@ def plot_3d(
data = data.reshape((grid.num_theta, grid.num_rho, grid.num_zeta), order="F")

label = r"$\mathbf{B} \cdot \hat{n} ~(\mathrm{T})$"
showgrid = kwargs.pop("showgrid", True)
zeroline = kwargs.pop("zeroline", True)
showticklabels = kwargs.pop("showticklabels", True)
showaxislabels = kwargs.pop("showaxislabels", True)
errorif(
len(kwargs) != 0,
msg=f"plot_3d got unexpected keyword argument: {kwargs.keys()}",
Expand Down Expand Up @@ -1017,30 +1029,48 @@ def plot_3d(
if fig is None:
fig = go.Figure()
fig.add_trace(meshdata)
xaxis_title = (
LatexNodes2Text().latex_to_text(_AXIS_LABELS_XYZ[0]) if showaxislabels else ""
)
yaxis_title = (
LatexNodes2Text().latex_to_text(_AXIS_LABELS_XYZ[1]) if showaxislabels else ""
)
zaxis_title = (
LatexNodes2Text().latex_to_text(_AXIS_LABELS_XYZ[2]) if showaxislabels else ""
)

fig.update_layout(
scene=dict(
xaxis_title=LatexNodes2Text().latex_to_text(_AXIS_LABELS_XYZ[0]),
yaxis_title=LatexNodes2Text().latex_to_text(_AXIS_LABELS_XYZ[1]),
zaxis_title=LatexNodes2Text().latex_to_text(_AXIS_LABELS_XYZ[2]),
xaxis_title=xaxis_title,
yaxis_title=yaxis_title,
zaxis_title=zaxis_title,
aspectmode="data",
xaxis=dict(
backgroundcolor="white",
gridcolor="darkgrey",
showbackground=False,
zerolinecolor="darkgrey",
showgrid=showgrid,
zeroline=zeroline,
showticklabels=showticklabels,
),
yaxis=dict(
backgroundcolor="white",
gridcolor="darkgrey",
showbackground=False,
zerolinecolor="darkgrey",
showgrid=showgrid,
zeroline=zeroline,
showticklabels=showticklabels,
),
zaxis=dict(
backgroundcolor="white",
gridcolor="darkgrey",
showbackground=False,
zerolinecolor="darkgrey",
showgrid=showgrid,
zeroline=zeroline,
showticklabels=showticklabels,
),
),
width=figsize[0] * dpi,
Expand Down Expand Up @@ -2009,7 +2039,7 @@ def plot_boundary(eq, phi=None, plot_axis=True, ax=None, return_data=False, **kw
ax.set_ylabel(_AXIS_LABELS_RPZ[2], fontsize=ylabel_fontsize)
ax.tick_params(labelbottom=True, labelleft=True)

fig.legend(**legend_kw)
ax.legend(**legend_kw)
_set_tight_layout(fig)

plot_data = {}
Expand Down Expand Up @@ -2113,9 +2143,7 @@ def plot_boundaries(

phi = (1 if eqs[-1].N == 0 else 4) if phi is None else phi
if isinstance(phi, numbers.Integral):
phi = np.linspace(
0, 2 * np.pi / eqs[-1].NFP, phi + 1
) # +1 to include pi and 2pi
phi = np.linspace(0, 2 * np.pi / eqs[-1].NFP, phi, endpoint=False)
phi = np.atleast_1d(phi)

neq = len(eqs)
Expand Down Expand Up @@ -2166,7 +2194,7 @@ def plot_boundaries(
plot_data["R"].append(R)
plot_data["Z"].append(Z)

for j in range(nz - 1):
for j in range(nz):
(line,) = ax.plot(
R[:, -1, j], Z[:, -1, j], color=colors[i], linestyle=ls[i], lw=lw[i]
)
Expand All @@ -2183,7 +2211,7 @@ def plot_boundaries(
ax.tick_params(labelbottom=True, labelleft=True)

if any(labels) and kwargs.pop("legend", True):
fig.legend(**kwargs.pop("legend_kw", {}))
ax.legend(**kwargs.pop("legend_kw", {}))
_set_tight_layout(fig)

assert (
Expand Down Expand Up @@ -2409,6 +2437,14 @@ def plot_coils(coils, grid=None, fig=None, return_data=False, **kwargs):
* ``lw``: float, linewidth of plotted coils
* ``ls``: str, linestyle of plotted coils
* ``color``: str, color of plotted coils
* ``showgrid``: Bool, whether or not to show the coordinate grid lines.
True by default.
* ``showticklabels``: Bool, whether or not to show the coordinate tick labels.
True by default.
* ``showaxislabels``: Bool, whether or not to show the coordinate axis labels.
True by default.
* ``zeroline``: Bool, whether or not to show the zero coordinate axis lines.
True by default.
Returns
-------
Expand All @@ -2423,6 +2459,10 @@ def plot_coils(coils, grid=None, fig=None, return_data=False, **kwargs):
figsize = kwargs.pop("figsize", (10, 10))
color = kwargs.pop("color", "black")
unique = kwargs.pop("unique", False)
showgrid = kwargs.pop("showgrid", True)
zeroline = kwargs.pop("zeroline", True)
showticklabels = kwargs.pop("showticklabels", True)
showaxislabels = kwargs.pop("showaxislabels", True)
errorif(
len(kwargs) != 0,
msg=f"plot_coils got unexpected keyword argument: {kwargs.keys()}",
Expand Down Expand Up @@ -2489,28 +2529,40 @@ def flatten_coils(coilset):
)

fig.add_trace(trace)
xaxis_title = "X (m)" if showaxislabels else ""
yaxis_title = "Y (m)" if showaxislabels else ""
zaxis_title = "Z (m)" if showaxislabels else ""
fig.update_layout(
scene=dict(
xaxis_title="X (m)",
yaxis_title="Y (m)",
zaxis_title="Z (m)",
xaxis_title=xaxis_title,
yaxis_title=yaxis_title,
zaxis_title=zaxis_title,
xaxis=dict(
backgroundcolor="white",
gridcolor="darkgrey",
showbackground=False,
zerolinecolor="darkgrey",
showgrid=showgrid,
zeroline=zeroline,
showticklabels=showticklabels,
),
yaxis=dict(
backgroundcolor="white",
gridcolor="darkgrey",
showbackground=False,
zerolinecolor="darkgrey",
showgrid=showgrid,
zeroline=zeroline,
showticklabels=showticklabels,
),
zaxis=dict(
backgroundcolor="white",
gridcolor="darkgrey",
showbackground=False,
zerolinecolor="darkgrey",
showgrid=showgrid,
zeroline=zeroline,
showticklabels=showticklabels,
),
aspectmode="data",
),
Expand Down Expand Up @@ -2698,7 +2750,7 @@ def plot_boozer_modes( # noqa: C901
ax.set_ylabel(ylabel, fontsize=ylabel_fontsize)

if kwargs.pop("legend", True):
fig.legend(**kwargs.pop("legend_kw", {"loc": "lower right"}))
ax.legend(**kwargs.pop("legend_kw", {"loc": "lower right"}))

assert (
len(kwargs) == 0
Expand Down Expand Up @@ -3111,7 +3163,7 @@ def plot_qs_error( # noqa: 16 fxn too complex
ax.set_ylabel(ylabel, fontsize=ylabel_fontsize)

if kwargs.pop("legend", True):
fig.legend(**kwargs.pop("legend_kw", {"loc": "center right"}))
ax.legend(**kwargs.pop("legend_kw", {"loc": "center right"}))

assert (
len(kwargs) == 0
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ colorama
diffrax >= 0.4.1
h5py >= 3.0.0, < 4.0
interpax >= 0.3.3
jax[cpu] >= 0.3.2, < 0.5.0
jax[cpu] >= 0.3.2, < 0.4.34
matplotlib >= 3.5.0, < 4.0.0
mpmath >= 1.0.0, < 2.0
netcdf4 >= 1.5.4, < 2.0
Expand Down
Binary file modified tests/baseline/test_bounce1d_checks.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/baseline/test_plot_b_mag.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/baseline/test_plot_boozer_modes.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/baseline/test_plot_boozer_modes_breaking_only.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/baseline/test_plot_boozer_modes_max.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/baseline/test_plot_boozer_modes_no_norm.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/baseline/test_plot_boundaries.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/baseline/test_plot_boundary.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/baseline/test_plot_boundary_surface.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/baseline/test_plot_qs_error.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 21 additions & 0 deletions tests/test_linear_objectives.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
FixNearAxisLambda,
FixNearAxisR,
FixNearAxisZ,
FixOmniBmax,
FixOmniMap,
FixOmniWell,
FixParameters,
Expand Down Expand Up @@ -915,6 +916,26 @@ def test_fix_omni_indices():
assert constraint.dim_f == indices.size


@pytest.mark.unit
def test_fix_omni_Bmax():
"""Test that omnigenity parameters are constrained for B_max to be a straight line.
Test for GH issue #1266.
"""

def _test(M_x, N_x, NFP, sum):
field = OmnigenousField(L_x=2, M_x=M_x, N_x=N_x, NFP=NFP, helicity=(1, NFP))
constraint = FixOmniBmax(field=field)
constraint.build()
assert constraint.dim_f == (2 * field.N_x + 1) * (field.L_x + 1)
# 0 - 2 + 4 - 6 + 8 ...
np.testing.assert_allclose(constraint._A @ field.x_basis.modes[:, 1], sum)

_test(M_x=6, N_x=3, NFP=1, sum=-4)
_test(M_x=9, N_x=4, NFP=2, sum=4)
_test(M_x=12, N_x=5, NFP=3, sum=6)


@pytest.mark.unit
def test_fix_parameters_input_order(DummyStellarator):
"""Test that FixParameters preserves the input indices and target ordering."""
Expand Down
Loading

0 comments on commit d7c6d26

Please sign in to comment.