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

Debugging singular integrals #1440

Open
wants to merge 60 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 56 commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
d4515c9
Failing 3D shape for green's id
unalmis Dec 9, 2024
8fb0d7c
Merge branch 'master' into debug_integral
unalmis Dec 9, 2024
bc313a0
Merge branch 'master' into debug_integral
dpanici Dec 11, 2024
cc9862a
Merge branch 'master' into debug_integral
unalmis Dec 22, 2024
b5344c7
Merge branch 'master' into debug_integral
unalmis Jan 8, 2025
0c48769
Merge branch 'master' into debug_integral
unalmis Jan 14, 2025
cd229d9
Merge branch 'master' into debug_integral
dpanici Jan 15, 2025
b9fc895
Merge remote-tracking branch 'origin/debug_integral' into debug_integral
unalmis Jan 15, 2025
0dabf85
Commit failing test
unalmis Jan 16, 2025
3d45932
Merge branch 'master' into debug_integral
dpanici Jan 16, 2025
7bfa014
Merge branch 'master' into debug_integral
dpanici Jan 16, 2025
f78034b
Update FFT interpolator with restriction to avoid frequency truncation
unalmis Jan 17, 2025
9f3f62d
debugging DFTInterpolator
unalmis Jan 17, 2025
2ea5eaf
Merge remote-tracking branch 'origin/debug_integral' into debug_integral
unalmis Jan 17, 2025
e51ef97
Debugging NFP periodicity
unalmis Jan 18, 2025
faf14aa
Resolves #1524
unalmis Jan 18, 2025
e43690e
Bunt axissymetic case to later
unalmis Jan 18, 2025
8adff59
Allow different NFP only if there is no toroidal variation
unalmis Jan 18, 2025
8256621
Lower bound s by 1 for singular integral resolution...
unalmis Jan 18, 2025
f831611
Fixing DFTInterpolator
unalmis Jan 20, 2025
3d661ba
Cache vandermonde matrix
unalmis Jan 20, 2025
2d40524
Merge branch 'master' into debug_integral
unalmis Jan 20, 2025
c1d7066
Avoid constructing large matrix
unalmis Jan 20, 2025
371ec5d
Rename new public function for interpolator
unalmis Jan 21, 2025
6ca4ae7
Genearlize polar grid extent to non-square grids
unalmis Jan 22, 2025
e9e6f72
Resolves #1531
unalmis Jan 22, 2025
4513ee4
Fix comment in commit e9e6f72
unalmis Jan 22, 2025
42f3a6d
Merge branch 'master' into debug_integral
unalmis Jan 22, 2025
ec42c11
Remove now unused kwargs in DoubleFourierSeries
unalmis Jan 22, 2025
dc16ba3
Fix typos in docstrings
unalmis Jan 22, 2025
b7b96b1
Loop over data instead of index in _non_singular_part as this is more…
unalmis Jan 22, 2025
91b7aa1
Merge branch 'master' into debug_integral
unalmis Jan 22, 2025
6b06648
Add second hyperparameter to free boundary objective
unalmis Jan 23, 2025
67060ab
Merge branch 'master' into debug_integral
unalmis Jan 23, 2025
fc47523
Cache vander matrix in bounce integrals
unalmis Jan 23, 2025
1629bdf
.
unalmis Jan 23, 2025
51f5aaa
Update interpolator test
unalmis Jan 23, 2025
178d45c
Make docstrings more verbose as requested by user
unalmis Jan 24, 2025
3c70721
Reuse Vandermonde array to interpolate with JIT fusion
unalmis Jan 24, 2025
6a3ffd4
Comment hanging code
unalmis Jan 24, 2025
2bd67ce
Switch notebook to reverse mode
unalmis Jan 24, 2025
7c3720c
Update master compute data
unalmis Jan 24, 2025
2b3b287
Review request and document work to prove integration is symmetric fo…
unalmis Jan 26, 2025
b91bec1
Usually eval grid and source grid are same, so don't recompute stuff …
unalmis Jan 26, 2025
bd4143f
Add note to docstring for free boundary ob
unalmis Jan 27, 2025
04600a3
Throw error on axisymmetric devices with NFP 1 and explain why
unalmis Jan 27, 2025
a275e8f
Free boundary speed (#1536)
unalmis Jan 27, 2025
a0c5f2e
Apply suggestions from code review
unalmis Jan 27, 2025
d2657ef
Merge branch 'master' into debug_integral
unalmis Jan 27, 2025
6ef7c89
Merge branch 'master' into debug_integral
unalmis Jan 28, 2025
d0bb776
Merge branch 'master' into debug_integral
unalmis Jan 28, 2025
7c3dd35
Move free boundary changes to new pr
unalmis Jan 29, 2025
25624aa
Merge branch 'master' into debug_integral
unalmis Jan 30, 2025
70a3aab
Merge branch 'master' into debug_integral
dpanici Jan 31, 2025
4924f25
Review requests
unalmis Feb 2, 2025
7f57c9e
Merge branch 'master' into debug_integral
unalmis Feb 3, 2025
8e58244
PR requests and finish adding chunk_size to free boundary
unalmis Feb 4, 2025
6b589c4
Merge branch 'master' into debug_integral
unalmis Feb 4, 2025
04e91a7
Update free boundary docstring for chunking
unalmis Feb 4, 2025
382e64c
Merge branch 'master' into debug_integral
unalmis Feb 4, 2025
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ Bug Fixes
- Fixed I/O bug when saving/loading ``_Profile`` classes that do not have a ``_params`` attribute.
- Minor bugs described in [#1323](https://github.com/PlasmaControl/DESC/pull/1323).
- Corrects basis vectors computations made on surface objects [#1175](https://github.com/PlasmaControl/DESC/pull/1175).
- Fix issue with interpolator for singular integrals [#1522](https://github.com/PlasmaControl/DESC/issues/1522) and additional checks [1519](https://github.com/PlasmaControl/DESC/issues/1519).

v0.13.0
-------
Expand Down
71 changes: 38 additions & 33 deletions desc/basis.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,9 +261,9 @@ def _get_modes(self, L):
Each row is one basis function with modes (l,m,n).

"""
l = np.arange(L + 1).reshape((-1, 1))
z = np.zeros((L + 1, 2))
return np.hstack([l, z])
l = np.arange(L + 1)
z = np.zeros_like(l)
return np.array([l, z, z]).T
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I changed some of the mode number constructors. They are the same as before. I changed this while debugging github issue 1522 and decided to keep the modifications because it uses the simpler conventions we use elsewhere in the code.


def evaluate(
self, nodes, derivatives=np.array([0, 0, 0]), modes=None, unique=False
Expand Down Expand Up @@ -374,10 +374,9 @@ def _get_modes(self, N):
Each row is one basis function with modes (l,m,n).

"""
dim_tor = 2 * N + 1
n = np.arange(dim_tor).reshape((-1, 1)) - N
z = np.zeros((dim_tor, 2))
return np.hstack([z, n])
n = np.arange(-N, N + 1)
z = np.zeros_like(n)
return np.array([z, z, n]).T

def evaluate(
self, nodes, derivatives=np.array([0, 0, 0]), modes=None, unique=False
Expand All @@ -400,6 +399,9 @@ def evaluate(
-------
y : ndarray, shape(num_nodes,num_modes)
Basis functions evaluated at nodes.
The Vandermonde matrix when ``modes is None`` is
given by ``y.reshape(-1,2*N+1)`` and is ordered
[sin(N𝛇), ..., sin(𝛇), 1, cos(𝛇), ..., cos(N𝛇)].

"""
if modes is None:
Expand Down Expand Up @@ -477,9 +479,7 @@ def __init__(self, M, N, NFP=1, sym=False):
self._NFP = check_posint(NFP, "NFP", False)
self._sym = bool(sym) if not sym else str(sym)
self._spectral_indexing = "linear"

self._modes = self._get_modes(M=self.M, N=self.N)

super().__init__()

def _get_modes(self, M, N):
Expand All @@ -499,16 +499,13 @@ def _get_modes(self, M, N):
Each row is one basis function with modes (l,m,n).

"""
dim_pol = 2 * M + 1
dim_tor = 2 * N + 1
m = np.arange(dim_pol) - M
n = np.arange(dim_tor) - N
mm, nn = np.meshgrid(m, n)
mm = mm.reshape((-1, 1), order="F")
nn = nn.reshape((-1, 1), order="F")
z = np.zeros_like(mm)
y = np.hstack([z, mm, nn])
return y
m = np.arange(-M, M + 1)
n = np.arange(-N, N + 1)
m, n = np.meshgrid(m, n, indexing="ij")
m = m.ravel()
n = n.ravel()
z = np.zeros_like(m)
return np.array([z, m, n]).T

def evaluate(
self, nodes, derivatives=np.array([0, 0, 0]), modes=None, unique=False
Expand All @@ -531,6 +528,11 @@ def evaluate(
-------
y : ndarray, shape(num_nodes,num_modes)
Basis functions evaluated at nodes.
The Vandermonde matrix when ``modes is None`` is
given by ``y.reshape(-1,2*M+1,2*N+1)`` and
is an outer product of Fourier matrices with order
[sin(M𝛉), ..., sin(𝛉), 1, cos(𝛉), ..., cos(M𝛉)]
⊗ [sin(N𝛇), ..., sin(𝛇), 1, cos(𝛇), ..., cos(N𝛇)].

"""
if modes is None:
Expand Down Expand Up @@ -858,17 +860,14 @@ def _get_modes(self, L, M, N):
Each row is one basis function with modes (l,m,n).

"""
dim_pol = 2 * M + 1
dim_tor = 2 * N + 1
l = np.arange(L + 1)
m = np.arange(dim_pol) - M
n = np.arange(dim_tor) - N
ll, mm, nn = np.meshgrid(l, m, n)
ll = ll.reshape((-1, 1), order="F")
mm = mm.reshape((-1, 1), order="F")
nn = nn.reshape((-1, 1), order="F")
y = np.hstack([ll, mm, nn])
return y
m = np.arange(-M, M + 1)
n = np.arange(-N, N + 1)
l, m, n = np.meshgrid(l, m, n, indexing="ij")
l = l.ravel()
m = m.ravel()
n = n.ravel()
return np.array([l, m, n]).T

def evaluate(
self, nodes, derivatives=np.array([0, 0, 0]), modes=None, unique=False
Expand All @@ -891,6 +890,12 @@ def evaluate(
-------
y : ndarray, shape(num_nodes,num_modes)
Basis functions evaluated at nodes.
The Vandermonde matrix when ``modes is None`` is given by
``y.reshape(-1,L+1,2*M+1,2*N+1,3)`` and is
an outer product of Chebyshev and Fourier matrices with order
[T₀(𝛒), T₁(𝛒), ..., T_L(𝛒)]
⊗ [sin(M𝛉), ..., sin(𝛉), 1, cos(𝛉), ..., cos(M𝛉)]
⊗ [sin(N𝛇), ..., sin(𝛇), 1, cos(𝛇), ..., cos(N𝛇)].

"""
if modes is None:
Expand Down Expand Up @@ -1212,9 +1217,9 @@ def _get_modes(self, L):
Each row is one basis function with modes (l,m,n).

"""
l = np.arange(L + 1).reshape((-1, 1))
z = np.zeros((L + 1, 2))
return np.hstack([l, z])
l = np.arange(L + 1)
z = np.zeros_like(l)
return np.array([l, z, z]).T

def evaluate(
self, nodes, derivatives=np.array([0, 0, 0]), modes=None, unique=False
Expand Down Expand Up @@ -1627,7 +1632,7 @@ def chebyshev(r, l, dr=0):

Parameters
----------
rho : ndarray, shape(N,)
r : ndarray, shape(N,)
radial coordinates to evaluate basis
l : ndarray of int, shape(K,)
radial mode number(s)
Expand Down
3 changes: 1 addition & 2 deletions desc/compute/_deprecated.py
Original file line number Diff line number Diff line change
Expand Up @@ -351,13 +351,12 @@ def _Gamma_c_Velasco_1D(params, transforms, profiles, data, **kwargs):

def Gamma_c(data):
bounce = Bounce1D(grid, data, quad, is_reshaped=True)
points = bounce.points(data["pitch_inv"], num_well)
v_tau, radial_drift, poloidal_drift = bounce.integrate(
[_v_tau, _radial_drift, _poloidal_drift],
data["pitch_inv"],
data,
["cvdrift0", "gbdrift"],
points,
bounce.points(data["pitch_inv"], num_well),
)
# This is γ_c π/2.
gamma_c = jnp.arctan(safediv(radial_drift, poloidal_drift))
Expand Down
10 changes: 5 additions & 5 deletions desc/compute/_equil.py
Original file line number Diff line number Diff line change
Expand Up @@ -824,12 +824,12 @@ def _beta_voltor(params, transforms, profiles, data, **kwargs):
def _P_ISS04(params, transforms, profiles, data, **kwargs):
rho = transforms["grid"].compress(data["rho"], surface_label="rho")
iota = transforms["grid"].compress(data["iota"], surface_label="rho")
method = kwargs.get("method", "cubic")
fx = {}
if "iota_r" in data:
fx["fx"] = transforms["grid"].compress(
data["iota_r"]
) # noqa: unused dependency
iota_23 = interp1d(2 / 3, rho, iota, method=kwargs.get("method", "cubic"), **fx)
if "iota_r" in data and method == "cubic":
# noqa: unused dependency
fx["fx"] = transforms["grid"].compress(data["iota_r"])
iota_23 = interp1d(2 / 3, rho, iota, method=method, **fx)
data["P_ISS04"] = 1e6 * ( # MW -> W
jnp.abs(data["W_p"] / 1e6) # J -> MJ
/ (
Expand Down
2 changes: 1 addition & 1 deletion desc/compute/geom_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def xyz2rpz(pts):
"""
x, y, z = pts.T
r = jnp.sqrt(x**2 + y**2)
r = jnp.hypot(x, y)
p = jnp.arctan2(y, x)
return jnp.array([r, p, z]).T

Expand Down
6 changes: 6 additions & 0 deletions desc/grid.py
Original file line number Diff line number Diff line change
Expand Up @@ -990,6 +990,7 @@ def __init__(
self._node_pattern = "linear"
self._coordinates = "rtz"
self._is_meshgrid = True
self._can_fft2 = not sym and not endpoint
self._period = (np.inf, 2 * np.pi, 2 * np.pi / self._NFP)
self._nodes, self._spacing = self._create_nodes(
L=L,
Expand Down Expand Up @@ -1205,6 +1206,11 @@ def _create_nodes( # noqa: C901
self._endpoint = (self._poloidal_endpoint or (t.size == 1 and z.size > 1)) and (
self._toroidal_endpoint or (z.size == 1 and t.size > 1)
)
self._can_fft2 = (
self._can_fft2
and not self._poloidal_endpoint
and not self._toroidal_endpoint
)

r, t, z = map(np.ravel, np.meshgrid(r, t, z, indexing="ij"))
dr, dt, dz = map(np.ravel, np.meshgrid(dr, dt, dz, indexing="ij"))
Expand Down
Loading
Loading