Skip to content

Commit 0a816d5

Browse files
committed
Add computation of <1/R>
1 parent f88c6de commit 0a816d5

File tree

3 files changed

+33
-3
lines changed

3 files changed

+33
-3
lines changed

torax/_src/geometry/imas.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# limitations under the License.
1414

1515
"""Useful functions for handling of IMAS IDSs."""
16+
import logging
1617
import os
1718
from typing import Any
1819

@@ -123,6 +124,14 @@ def geometry_from_IMAS(
123124
int_dl_over_Bp = dvoldpsi # C1
124125
flux_surf_avg_1_over_R2 = IMAS_data.profiles_1d.gm1 # C2/C1
125126

127+
if IMAS_data.profiles_1d.gm9:
128+
flux_surf_avg_1_over_R = IMAS_data.profiles_1d.gm9
129+
else:
130+
logging.warning(
131+
"<1/R> profile (gm9) not found; assuming <1/R> ≈ 1/R_major (constant)"
132+
)
133+
flux_surf_avg_1_over_R = 1 / R_major
134+
126135
# jtor = dI/drhon / (drho/dS) = dI/drhon / spr
127136
# spr = vpr / ( 2 * np.pi * R_major)
128137
# -> Ip_profile = integrate(y = spr * jtor, x= rhon, initial = 0.0)
@@ -164,6 +173,7 @@ def geometry_from_IMAS(
164173
"R_out": R_out,
165174
"F": F,
166175
"int_dl_over_Bp": int_dl_over_Bp,
176+
"flux_surf_avg_1_over_R": flux_surf_avg_1_over_R,
167177
"flux_surf_avg_1_over_R2": flux_surf_avg_1_over_R2,
168178
"flux_surf_avg_RBp": flux_surf_avg_RBp,
169179
"flux_surf_avg_R2Bp2": flux_surf_avg_R2Bp2,

torax/_src/geometry/standard_geometry.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,8 @@ class StandardGeometryIntermediates:
142142
int_dl_over_Bp: :math:`\oint dl/B_p` (field-line contour integral on the
143143
flux surface) [:math:`\mathrm{m / T}`], where :math:`B_p` is the poloidal
144144
magnetic field.
145+
flux_surf_avg_1_over_R: Flux surface average of :math:`1/R`
146+
[:math:`\mathrm{m^{-1}}`].
145147
flux_surf_avg_1_over_R2: Flux surface average of :math:`1/R^2`
146148
[:math:`\mathrm{m^{-2}}`].
147149
flux_surf_avg_Bp2: Flux surface average of :math:`B_p^2`
@@ -177,6 +179,7 @@ class StandardGeometryIntermediates:
177179
R_out: chex.Array
178180
F: chex.Array
179181
int_dl_over_Bp: chex.Array
182+
flux_surf_avg_1_over_R: chex.Array
180183
flux_surf_avg_1_over_R2: chex.Array
181184
flux_surf_avg_Bp2: chex.Array
182185
flux_surf_avg_RBp: chex.Array
@@ -317,6 +320,7 @@ def from_chease(
317320
int_dl_over_Bp = (
318321
chease_data['Int(Rdlp/|grad(psi)|)=Int(Jdchi)'] * R_major / B_0
319322
)
323+
flux_surf_avg_1_over_R = chease_data['<1/R>profile'] / R_major
320324
flux_surf_avg_1_over_R2 = chease_data['<1/R**2>'] / R_major**2
321325
flux_surf_avg_Bp2 = chease_data['<Bp**2>'] * B_0**2
322326
flux_surf_avg_RBp = chease_data['<|grad(psi)|>'] * psiunnormfactor / R_major
@@ -340,6 +344,7 @@ def from_chease(
340344
R_out=R_out_chease,
341345
F=F,
342346
int_dl_over_Bp=int_dl_over_Bp,
347+
flux_surf_avg_1_over_R=flux_surf_avg_1_over_R,
343348
flux_surf_avg_1_over_R2=flux_surf_avg_1_over_R2,
344349
flux_surf_avg_Bp2=flux_surf_avg_Bp2,
345350
flux_surf_avg_RBp=flux_surf_avg_RBp,
@@ -523,6 +528,7 @@ def _get_LY_single_slice_from_bundle(
523528
'TQ',
524529
'FB',
525530
'FA',
531+
'Q0Q',
526532
'Q1Q',
527533
'Q2Q',
528534
'Q3Q',
@@ -596,6 +602,7 @@ def _from_fbt(
596602
# replaces the zero does not matter, since it will be replaced by a spline
597603
# extrapolation in the post_init.
598604
LY_Q1Q = np.where(LY['Q1Q'] != 0, LY['Q1Q'], constants.CONSTANTS.eps)
605+
599606
return cls(
600607
geometry_type=geometry.GeometryType.FBT,
601608
Ip_from_parameters=Ip_from_parameters,
@@ -609,6 +616,7 @@ def _from_fbt(
609616
R_out=LY['rgeom'] + LY['aminor'],
610617
F=np.abs(LY['TQ']),
611618
int_dl_over_Bp=1 / LY_Q1Q,
619+
flux_surf_avg_1_over_R=LY['Q0Q'],
612620
flux_surf_avg_1_over_R2=LY['Q2Q'],
613621
flux_surf_avg_Bp2=np.abs(LY['Q3Q']) / (4 * np.pi**2),
614622
flux_surf_avg_RBp=np.abs(LY['Q5Q']) / (2 * np.pi),
@@ -765,6 +773,7 @@ def calculate_area(x, z):
765773
R_inboard, R_outboard = np.empty(len(surfaces) + 1), np.empty(
766774
len(surfaces) + 1
767775
)
776+
flux_surf_avg_1_over_R_eqdsk = np.empty(len(surfaces) + 1) # <1/R>
768777
flux_surf_avg_1_over_R2_eqdsk = np.empty(len(surfaces) + 1) # <1/R**2>
769778
flux_surf_avg_Bp2_eqdsk = np.empty(len(surfaces) + 1) # <Bp**2>
770779
flux_surf_avg_RBp_eqdsk = np.empty(len(surfaces) + 1) # <|grad(psi)|>
@@ -799,8 +808,13 @@ def calculate_area(x, z):
799808
# plasma current
800809
surface_int_bpol_dl = np.sum(surface_Bpol * surface_dl)
801810

802-
# 4 FSA, < 1/ R^2>, < | grad psi | >, < B_pol^2>, < | grad psi |^2 >
811+
# Flux surface averaged equilibrium terms
812+
# <1/R>, < 1/ R^2>, < | grad psi | >, < B_pol^2>, < | grad psi |^2 >
803813
# where FSA(G) = int (G dl / Bpol) / (int (dl / Bpol))
814+
surface_FSA_int_one_over_r = (
815+
np.sum(1 / x_surface * surface_dl / surface_Bpol)
816+
/ surface_int_dl_over_bpol
817+
)
804818
surface_FSA_int_one_over_r2 = (
805819
np.sum(1 / x_surface**2 * surface_dl / surface_Bpol)
806820
/ surface_int_dl_over_bpol
@@ -845,6 +859,7 @@ def calculate_area(x, z):
845859
R_inboard[n + 1] = x_surface.min()
846860
R_outboard[n + 1] = x_surface.max()
847861
int_dl_over_Bp_eqdsk[n + 1] = surface_int_dl_over_bpol
862+
flux_surf_avg_1_over_R_eqdsk[n + 1] = surface_FSA_int_one_over_r
848863
flux_surf_avg_1_over_R2_eqdsk[n + 1] = surface_FSA_int_one_over_r2
849864
flux_surf_avg_RBp_eqdsk[n + 1] = surface_FSA_abs_grad_psi
850865
flux_surf_avg_R2Bp2_eqdsk[n + 1] = surface_FSA_abs_grad_psi2
@@ -863,6 +878,7 @@ def calculate_area(x, z):
863878
R_inboard[0] = Raxis
864879
R_outboard[0] = Raxis
865880
int_dl_over_Bp_eqdsk[0] = 0
881+
flux_surf_avg_1_over_R_eqdsk[0] = 1 / Raxis
866882
flux_surf_avg_1_over_R2_eqdsk[0] = 1 / Raxis**2
867883
flux_surf_avg_RBp_eqdsk[0] = 0
868884
flux_surf_avg_R2Bp2_eqdsk[0] = 0
@@ -922,6 +938,7 @@ def calculate_area(x, z):
922938
R_out=R_outboard,
923939
F=F_eqdsk,
924940
int_dl_over_Bp=int_dl_over_Bp_eqdsk,
941+
flux_surf_avg_1_over_R=flux_surf_avg_1_over_R_eqdsk,
925942
flux_surf_avg_1_over_R2=flux_surf_avg_1_over_R2_eqdsk,
926943
flux_surf_avg_RBp=flux_surf_avg_RBp_eqdsk,
927944
flux_surf_avg_R2Bp2=flux_surf_avg_R2Bp2_eqdsk,
@@ -1037,13 +1054,15 @@ def build_standard_geometry(
10371054

10381055
# dV/drhon, dS/drhon
10391056
vpr = intermediate.vpr
1040-
spr = vpr / (2 * np.pi * intermediate.R_major)
1057+
spr = vpr * intermediate.flux_surf_avg_1_over_R / (2 * np.pi)
10411058

10421059
# Volume and area
10431060
volume_intermediate = scipy.integrate.cumulative_trapezoid(
10441061
y=vpr, x=rho_norm_intermediate, initial=0.0
10451062
)
1046-
area_intermediate = volume_intermediate / (2 * np.pi * intermediate.R_major)
1063+
area_intermediate = scipy.integrate.cumulative_trapezoid(
1064+
y=spr, x=rho_norm_intermediate, initial=0.0
1065+
)
10471066

10481067
# plasma current density
10491068
dI_tot_drhon = np.gradient(intermediate.Ip_profile, rho_norm_intermediate)

torax/_src/geometry/tests/standard_geometry_test.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ def foo(geo: geometry.Geometry):
5252
R_out=np.arange(1, 2, 0.01),
5353
F=np.arange(0, 1.0, 0.01),
5454
int_dl_over_Bp=np.arange(0, 1.0, 0.01),
55+
flux_surf_avg_1_over_R=np.arange(0, 1.0, 0.01),
5556
flux_surf_avg_1_over_R2=np.arange(0, 1.0, 0.01),
5657
flux_surf_avg_Bp2=np.arange(0, 1.0, 0.01),
5758
flux_surf_avg_RBp=np.arange(0, 1.0, 0.01),

0 commit comments

Comments
 (0)