Skip to content
Closed
Changes from all commits
Commits
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
76 changes: 76 additions & 0 deletions freegs4e/equilibrium.py
Original file line number Diff line number Diff line change
Expand Up @@ -2541,6 +2541,82 @@ def dr_sep(

return [dr_sep_in, dr_sep_out]

def jtor_1D(self, N):
"""

Calculate the flux surface averaged toroidal current density (as a function of normalised psi):

< j_tor > (ψ) = < j_tor/R > / < 1/R >

where the flux surface average is defined as:

< f > = d/d psi int_{psi' <= psi} f dV,

where dV = 2 pi R ds \ |∇ψ|.

Parameters
----------
N : int
Number of discretisation points.

Returns
-------
np.array
Flux surface averaged toroidal current density (as a function of normalised psi, length N).
"""

# compute the gradient of psi
dPsidR = self.psi_func(self.R, self.Z, dx=1, grid=False)
dPsidZ = self.psi_func(self.R, self.Z, dy=1, grid=False)
grad_psi = np.sqrt(dPsidR**2 + dPsidZ**2) # |∇ψ|

# define quantities to flux-average
F1 = self._profiles.jtor / self.R # J_phi / R
F2 = 1 / self.R # 1 / R

# compute normalised psi levels
psi_levels = self.psi_1D(N)
psi_norm_levels = self.psiN_1D(N)

# compute enclosed integral
F_Q1 = np.zeros(N)
F_Q2 = np.zeros(N)
dV = 2 * np.pi * self.R / grad_psi

for i, psi_k in enumerate(psi_levels):
mask = self.psi() <= psi_k # region inside the flux surface

# apply core plasma mask
try:
F_Q1[i] = np.sum(
(F1 * dV * mask) * self._profiles.limiter_core_mask
)
F_Q2[i] = np.sum(
(F2 * dV * mask) * self._profiles.limiter_core_mask
)
except AttributeError as e:
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this should be catching TypeError? Or maybe both TypeError and AttributeError?
Sometimes limiter_core_mask can be None, and then you get a type error from trying to multiply a float by a None.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Do you have an example of this? Typically, this error pops up because self._profiles is not an attribute of the equilibrium object unless the equilibrium has been solved. Not sure I've seen a case where self._profiles.limiter_core_mask = None

print(e)
warnings.warn(
"The core mask is not in place. You need to solve for the equilibrium first!"
)
raise e

# compute flux surface average ⟨Q⟩ = dF_Q/dψ_norm using UnivariateSpline
flux_avg_Q1_interp = interpolate.UnivariateSpline(
psi_norm_levels, F_Q1
)
flux_avg_Q2_interp = interpolate.UnivariateSpline(
psi_norm_levels, F_Q2
)

flux_avg_Q1 = flux_avg_Q1_interp.derivative()(psi_norm_levels)
flux_avg_Q2 = flux_avg_Q2_interp.derivative()(psi_norm_levels)

flux_surf_avg_jtor = flux_avg_Q1 / flux_avg_Q2
flux_surf_avg_jtor[-1] = 0

return flux_surf_avg_jtor

def solve(self, profiles, Jtor=None, psi=None, psi_bndry=None):
"""
This is a legacy function that can be used to solve for the plasma equilibrium. It
Expand Down