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

from_values method for FourierRZCoil and FourierPlanarCoil #1116

Merged
merged 34 commits into from
Jul 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
5274d22
add from_values to FourierRZCoil
dpanici Jul 9, 2024
4a870a4
add missing attrs
dpanici Jul 9, 2024
daf8ec4
Merge branch 'master' into dp/hotfix-fourierrzcoil-from-values
dpanici Jul 9, 2024
0189243
fix docstring and reorder args to match init
dpanici Jul 9, 2024
9094c1a
Merge branch 'dp/hotfix-fourierrzcoil-from-values' of github.com:Plas…
dpanici Jul 9, 2024
1217503
Merge branch 'master' into dp/hotfix-fourierrzcoil-from-values
ddudt Jul 15, 2024
ae2997e
Merge branch 'master' into dp/hotfix-fourierrzcoil-from-values
dpanici Jul 17, 2024
4ecae78
add from_values for FourierPlanarCurve
daniel-dudt Jul 17, 2024
638baf3
Merge branch 'master' into dp/hotfix-fourierrzcoil-from-values
dpanici Jul 18, 2024
fa98655
more robus planar curve fitting
daniel-dudt Jul 18, 2024
bf30b82
undo debugging change
daniel-dudt Jul 18, 2024
9c849de
be explicit about class
daniel-dudt Jul 19, 2024
14f5793
Merge branch 'master' into dp/hotfix-fourierrzcoil-from-values
ddudt Jul 19, 2024
35beb2c
Merge branch 'master' into dp/hotfix-fourierrzcoil-from-values
ddudt Jul 19, 2024
2b6b41b
use SVD to compute normal vector
daniel-dudt Jul 22, 2024
21dba61
Merge branch 'master' into dp/hotfix-fourierrzcoil-from-values
ddudt Jul 22, 2024
2fdf509
Merge branch 'master' into dp/hotfix-fourierrzcoil-from-values
dpanici Jul 22, 2024
efff9d1
add tests, allow normals that are parallel to Zaxis
dpanici Jul 23, 2024
0037d50
avoid error if no resolution is passed to to_XXX methods
dpanici Jul 23, 2024
29b35aa
undo unneeded changes in _curve compute
dpanici Jul 23, 2024
7ba36b7
remove white space
dpanici Jul 23, 2024
801832d
modify test to test a non-centered coil
dpanici Jul 23, 2024
f354986
modify test to test a non-centered coil
dpanici Jul 23, 2024
2a1ba00
Merge branch 'dp/hotfix-fourierrzcoil-from-values' of github.com:Plas…
dpanici Jul 23, 2024
6f6ea23
update changelog
dpanici Jul 24, 2024
cbb6543
remove NFP from grid of to_FourierRZ calls
dpanici Jul 24, 2024
d0eb4e0
add basis option for to_FourierPlanar
daniel-dudt Jul 24, 2024
448d239
ocd formatting
daniel-dudt Jul 24, 2024
9614631
Merge branch 'master' into dp/hotfix-fourierrzcoil-from-values
dpanici Jul 24, 2024
57688ef
add basis to coil to_planar method, make sure input coordinates match…
dpanici Jul 24, 2024
6147e7f
Merge branch 'master' into dp/hotfix-fourierrzcoil-from-values
dpanici Jul 24, 2024
7d2eeae
Merge branch 'master' into dp/hotfix-fourierrzcoil-from-values
f0uriest Jul 25, 2024
663894b
Merge branch 'master' into dp/hotfix-fourierrzcoil-from-values
f0uriest Jul 25, 2024
40f355a
Merge branch 'master' into dp/hotfix-fourierrzcoil-from-values
dpanici Jul 25, 2024
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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
Changelog
=========

New Features

- adds ``from_values`` method that was present in ``FourierRZCurve`` but missing in ``FourierRZCoil``
- also adds new ``from_values`` method for ``FourierPlanarCurve`` and ``FourierPlanarCoil``


v0.12.0
-------
Expand Down
173 changes: 162 additions & 11 deletions desc/coils.py
Original file line number Diff line number Diff line change
Expand Up @@ -346,14 +346,83 @@ def to_SplineXYZ(self, knots=None, grid=None, method="cubic", name=""):
self.current, coords, knots=knots, method=method, name=name, basis="xyz"
)

def to_FourierRZ(self, N=10, grid=None, NFP=None, sym=False, name=""):
"""Convert Coil to FourierRZCoil representation.

Note that some types of coils may not be representable in this basis.

Parameters
----------
N : int
Fourier resolution of the new R,Z representation.
grid : Grid, int or None
Grid used to evaluate curve coordinates on to fit with FourierRZCoil.
If an integer, uses that many equally spaced points.
NFP : int
Number of field periods, the coil will have a discrete toroidal symmetry
according to NFP.
sym : bool, optional
whether the curve is stellarator-symmetric or not. Default
is False.
name : str
name for this coil

Returns
-------
curve : FourierRZCoil
New representation of the coil parameterized by Fourier series for R,Z.

"""
NFP = 1 or NFP
if grid is None:
grid = LinearGrid(N=2 * N + 1)
coords = self.compute("x", grid=grid, basis="xyz")["x"]
return FourierRZCoil.from_values(
self.current, coords, N=N, NFP=NFP, basis="xyz", sym=sym, name=name
)

def to_FourierPlanar(self, N=10, grid=None, basis="xyz", name=""):
"""Convert Coil to FourierPlanarCoil representation.

Note that some types of coils may not be representable in this basis.
In this case, a least-squares fit will be done to find the
planar coil that best represents the coil.

Parameters
----------
N : int
Fourier resolution of the new FourierPlanarCoil representation.
grid : Grid, int or None
Grid used to evaluate curve coordinates on to fit with FourierPlanarCoil.
If an integer, uses that many equally spaced points.
basis : {'xyz', 'rpz'}
Coordinate system for center and normal vectors. Default = 'xyz'.
name : str
name for this coil

Returns
-------
coil : FourierPlanarCoil
New representation of the coil parameterized by Fourier series for
minor radius r in a plane specified by a center position and normal
vector.

"""
if grid is None:
grid = LinearGrid(N=2 * N + 1)
coords = self.compute("x", grid=grid, basis=basis)["x"]
return FourierPlanarCoil.from_values(
self.current, coords, N=N, basis=basis, name=name
)


class FourierRZCoil(_Coil, FourierRZCurve):
"""Coil parameterized by fourier series for R,Z in terms of toroidal angle phi.

Parameters
----------
current : float
current through coil, in Amperes
Current through the coil, in Amperes.
R_n, Z_n: array-like
fourier coefficients for R, Z
modes_R : array-like
Expand Down Expand Up @@ -414,14 +483,58 @@ def __init__(
):
super().__init__(current, R_n, Z_n, modes_R, modes_Z, NFP, sym, name)

@classmethod
def from_values(cls, current, coords, N=10, NFP=1, basis="rpz", sym=False, name=""):
"""Fit coordinates to FourierRZCoil representation.

Parameters
----------
current : float
Current through the coil, in Amperes.
coords: ndarray, shape (num_coords,3)
coordinates to fit a FourierRZCurve object with each column
corresponding to xyz or rpz depending on the basis argument.
N : int
Fourier resolution of the new R,Z representation.
NFP : int
Number of field periods, the curve will have a discrete toroidal symmetry
according to NFP.
basis : {"rpz", "xyz"}
basis for input coordinates. Defaults to "rpz"
sym : bool
Whether to enforce stellarator symmetry.
name : str
name for this coil


Returns
-------
coil : FourierRZCoil
New representation of the coil parameterized by Fourier series for R,Z.

"""
curve = super().from_values(
coords=coords, N=N, NFP=NFP, basis=basis, sym=sym, name=name
)
return FourierRZCoil(
current=current,
R_n=curve.R_n,
Z_n=curve.Z_n,
modes_R=curve.R_basis.modes[:, 2],
modes_Z=curve.Z_basis.modes[:, 2],
NFP=NFP,
sym=curve.sym,
name=name,
)


class FourierXYZCoil(_Coil, FourierXYZCurve):
"""Coil parameterized by fourier series for X,Y,Z in terms of arbitrary angle s.

Parameters
----------
current : float
current through coil, in Amperes
Current through the coil, in Amperes.
X_n, Y_n, Z_n: array-like
fourier coefficients for X, Y, Z
modes : array-like
Expand Down Expand Up @@ -484,7 +597,7 @@ def from_values(cls, current, coords, N=10, s=None, basis="xyz", name=""):
Parameters
----------
current : float
Current through the coil, in Amps.
Current through the coil, in Amperes.
coords: ndarray
Coordinates to fit a FourierXYZCoil object with.
N : int
Expand All @@ -503,12 +616,13 @@ def from_values(cls, current, coords, N=10, s=None, basis="xyz", name=""):
New representation of the coil parameterized by Fourier series for X,Y,Z.

"""
curve = super().from_values(coords, N, s, basis)
return cls(
current,
curve = super().from_values(coords=coords, N=N, s=s, basis=basis, name=name)
return FourierXYZCoil(
current=current,
X_n=curve.X_n,
Y_n=curve.Y_n,
Z_n=curve.Z_n,
modes=curve.X_basis.modes[:, 2],
name=name,
)

Expand Down Expand Up @@ -586,14 +700,49 @@ def __init__(
):
super().__init__(current, center, normal, r_n, modes, basis, name)

@classmethod
def from_values(cls, current, coords, N=10, basis="xyz", name=""):
"""Fit coordinates to FourierPlanarCoil representation.

Parameters
----------
current : float
Current through the coil, in Amperes.
coords: ndarray, shape (num_coords,3)
Coordinates to fit a FourierPlanarCurve object with each column
corresponding to xyz or rpz depending on the basis argument.
N : int
Fourier resolution of the new r representation.
basis : {"rpz", "xyz"}
Basis for input coordinates. Defaults to "xyz".
name : str
Name for this curve.

Returns
-------
curve : FourierPlanarCoil
New representation of the coil parameterized by a Fourier series for r.

"""
curve = super().from_values(coords=coords, N=N, basis=basis, name=name)
return FourierPlanarCoil(
current=current,
center=curve.center,
normal=curve.normal,
r_n=curve.r_n,
modes=curve.r_basis.modes[:, 2],
basis="xyz",
name=name,
)


class SplineXYZCoil(_Coil, SplineXYZCurve):
"""Coil parameterized by spline points in X,Y,Z.

Parameters
----------
current : float
current through coil, in Amperes
Current through the coil, in Amperes.
X, Y, Z: array-like
Points for X, Y, Z describing the curve. If the endpoint is included
(ie, X[0] == X[-1]), then the final point will be dropped.
Expand Down Expand Up @@ -705,7 +854,7 @@ def from_values(
Parameters
----------
current : float
Current through the coil, in Amps.
Current through the coil, in Amperes.
coords: ndarray
Points for X, Y, Z describing the curve. If the endpoint is included
(ie, X[0] == X[-1]), then the final point will be dropped.
Expand Down Expand Up @@ -737,9 +886,11 @@ def from_values(
New representation of the coil parameterized by splines in X,Y,Z.

"""
curve = super().from_values(coords, knots, method, basis=basis)
return cls(
current,
curve = super().from_values(
coords=coords, knots=knots, method=method, basis=basis, name=name
)
return SplineXYZCoil(
current=current,
X=curve.X,
Y=curve.Y,
Z=curve.Z,
Expand Down
46 changes: 42 additions & 4 deletions desc/geometry/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@
+ " (name={})".format(self.name)
)

def to_FourierXYZ(self, N=None, grid=None, s=None, name=""):
def to_FourierXYZ(self, N=10, grid=None, s=None, name=""):
"""Convert Curve to FourierXYZCurve representation.

Parameters
Expand Down Expand Up @@ -284,7 +284,7 @@
coords, knots=knots, method=method, name=name, basis="xyz"
)

def to_FourierRZ(self, N=None, grid=None, NFP=None, name=""):
def to_FourierRZ(self, N=10, grid=None, NFP=None, sym=False, name=""):
"""Convert Curve to FourierRZCurve representation.

Note that some types of curves may not be representable in this basis.
Expand All @@ -299,6 +299,8 @@
NFP : int
Number of field periods, the curve will have a discrete toroidal symmetry
according to NFP.
sym : bool, optional
Whether the curve is stellarator-symmetric or not. Default is False.
name : str
name for this curve

Expand All @@ -312,9 +314,45 @@

NFP = 1 or NFP
if grid is None:
grid = LinearGrid(N=2 * N + 1, NFP=NFP)
grid = LinearGrid(N=2 * N + 1)

Check warning on line 317 in desc/geometry/core.py

View check run for this annotation

Codecov / codecov/patch

desc/geometry/core.py#L317

Added line #L317 was not covered by tests
coords = self.compute("x", grid=grid, basis="xyz")["x"]
return FourierRZCurve.from_values(coords, N=N, NFP=NFP, basis="xyz", name=name)
return FourierRZCurve.from_values(

Check warning on line 319 in desc/geometry/core.py

View check run for this annotation

Codecov / codecov/patch

desc/geometry/core.py#L319

Added line #L319 was not covered by tests
coords, N=N, NFP=NFP, basis="xyz", name=name, sym=sym
)

def to_FourierPlanar(self, N=10, grid=None, basis="xyz", name=""):
"""Convert Curve to FourierPlanarCurve representation.

Note that some types of curves may not be representable in this basis.
In this case, a least-squares fit will be done to find the
planar curve that best represents the curve.

Parameters
----------
N : int
Fourier resolution of the new FourierPlanarCurve representation.
grid : Grid, int or None
Grid used to evaluate curve coordinates on to fit with FourierPlanarCurve.
If an integer, uses that many equally spaced points.
basis : {'xyz', 'rpz'}
Coordinate system for center and normal vectors. Default = 'xyz'.
name : str
name for this curve

Returns
-------
curve : FourierPlanarCurve
New representation of the curve parameterized by Fourier series for
minor radius r in a plane specified by a center position and normal
vector.

"""
from .curve import FourierPlanarCurve

Check warning on line 350 in desc/geometry/core.py

View check run for this annotation

Codecov / codecov/patch

desc/geometry/core.py#L350

Added line #L350 was not covered by tests

if grid is None:
grid = LinearGrid(N=2 * N + 1)
coords = self.compute("x", grid=grid, basis=basis)["x"]
return FourierPlanarCurve.from_values(coords, N=N, basis=basis, name=name)

Check warning on line 355 in desc/geometry/core.py

View check run for this annotation

Codecov / codecov/patch

desc/geometry/core.py#L352-L355

Added lines #L352 - L355 were not covered by tests


class Surface(IOAble, Optimizable, ABC):
Expand Down
Loading
Loading