Skip to content
Merged
Show file tree
Hide file tree
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

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Temperature Profile | `ElectronTemperatureProfile(Profile)`
# Electron Temperature Profile | `ElectronTemperatureProfile(Profile)`

The temperature profile class is organised around a central runner function that is called each time the plasma is parameterised by the parent [`PlasmaProfile()`](plasma_profiles.md#plasma-profile-class-plasmaprofile) class. It is called by [`pedestal_parameterisation()`](plasma_profiles.md#pedestal_parameterisation) and [`parabolic parameterisation()`](plasma_profiles.md#parabolic_parameterisation). The sequence of the runner function can be seen below along with explanation of the following calculations.

Expand All @@ -21,8 +21,8 @@ A list of input parameters for calculating the core plasma temperature can be fo
| Profile parameter / Input | Temperature |
|----------------------------------|-----------|
| Pedestal radius (r/a) | `radius_plasma_pedestal_temp_norm`, $\rho_{\text{ped,T}}$ |
| Pedestal value | `temp_plasma_pedestal_kev`, $T_{\text{ped}}$ |
| Separatrix value | `temp_plasma_separatrix_kev`, $T_{\text{sep}}$ |
| Pedestal value | `temp_plasma_pedestal_electron_kev`, $T_{\text{ped}}$ |
| Separatrix value | `temp_plasma_separatrix_electron_kev`, $T_{\text{sep}}$ |
| Average temperature | `temp_vol_avg_kev`, $\langle T \rangle$ |
| Profile index/ peaking parameter | `alphat`, $\alpha_T$ |
| Profile index/ peaking parameter | `tbeta`, $\beta_T$ |
Expand Down Expand Up @@ -193,8 +193,8 @@ A table of the input variables can be found below
| Normalised plasma radii | `profile_x` |
| Pedestal radius (r/a) | `radius_plasma_pedestal_temp_norm`, $\rho_{\text{ped,T}}$ |
| Core temperature | `temp_plasma_electron_on_axis_kev`, $T_{\text{e0}}$ |
| Pedestal value | `temp_plasma_pedestal_kev`, $T_{\text{ped}}$ |
| Separatrix value | `temp_plasma_separatrix_kev`, $T_{\text{sep}}$ |
| Pedestal value | `temp_plasma_pedestal_electron_kev`, $T_{\text{ped}}$ |
| Separatrix value | `temp_plasma_separatrix_electron_kev`, $T_{\text{sep}}$ |
| Profile index/ peaking parameter | `alphat`, $\alpha_T$ |
| 2nd profile index/ peaking parameter | `tbeta`, $\beta_T$ |

Expand Down Expand Up @@ -222,6 +222,13 @@ $$\begin{aligned}

5. Profile is then integrated with `integrate_profile_y()` using Simpsons integration from the profile abstract base class

---------------------

# Ion Temperature Profile | `IonTemperatureProfile()`

The ion temperature profile matches the exact same shape as the electron density profile but its values are scaled linearly via the value of `f_temp_plasma_ion_electron`.


[^1]: Jean, J. (2011). *HELIOS: A Zero-Dimensional Tool for Next Step and Reactor Studies*. Fusion Science and Technology, 59(2), 308–349. <https://doi.org/10.13182/FST11-A11650>

[^iter_design_89]: N.A. Uckan and ITER Physics Group, 'ITER Physics Design Guidelines: 1989',
4 changes: 2 additions & 2 deletions examples/data/large_tokamak_IN.DAT
Original file line number Diff line number Diff line change
Expand Up @@ -376,10 +376,10 @@ radius_plasma_pedestal_temp_norm = 0.94
tbeta = 2.0

* Electron temperature of pedestal (kev) (i_plasma_pedestal=1)
temp_plasma_pedestal_kev = 5.5
temp_plasma_pedestal_electron_kev = 5.5

* Electron temperature at separatrix (kev) (i_plasma_pedestal=1)
temp_plasma_separatrix_kev = 0.1
temp_plasma_separatrix_electron_kev = 0.1

* Switch for energy confinement time scaling law
i_confinement_time = 34
Expand Down
4 changes: 2 additions & 2 deletions examples/data/large_tokamak_eval_IN.DAT
Original file line number Diff line number Diff line change
Expand Up @@ -294,8 +294,8 @@ plasma_res_factor = 0.7 * plasma resistivity pre-factor
radius_plasma_pedestal_density_norm = 0.94 * r/a of density pedestal (`i_plasma_pedestal==1`)
radius_plasma_pedestal_temp_norm = 0.94 * r/a of temperature pedestal (`i_plasma_pedestal==1`)
tbeta = 2.0 * temperature profile index beta (`i_plasma_pedestal==1)
temp_plasma_pedestal_kev = 5.5 * electron temperature of pedestal (keV) (`i_plasma_pedestal==1')
temp_plasma_separatrix_kev = 0.1 * electron temperature at separatrix (keV) (`i_plasma_pedestal==1`) calculated if reinke
temp_plasma_separatrix_electron_kev = 5.5 * electron temperature of pedestal (keV) (`i_plasma_pedestal==1')
temp_plasma_separatrix_electron_kev = 0.1 * electron temperature at separatrix (keV) (`i_plasma_pedestal==1`) calculated if reinke
i_confinement_time = 34 * switch for energy confinement time scaling law (see description in `tauscl`)
i_plasma_geometry = 0 * switch for plasma cross-sectional shape calculation;
kappa = 1.85 * plasma separatrix elongation (calculated if `i_plasma_geometry = 1-5; 7 or 9-10`)
Expand Down
4 changes: 2 additions & 2 deletions examples/data/large_tokamak_varied_min_net_electric_IN.DAT
Original file line number Diff line number Diff line change
Expand Up @@ -376,10 +376,10 @@ radius_plasma_pedestal_temp_norm = 0.94
tbeta = 2.0

* Electron temperature of pedestal (kev) (i_plasma_pedestal=1)
temp_plasma_pedestal_kev = 5.5
temp_plasma_separatrix_electron_kev = 5.5

* Electron temperature at separatrix (kev) (i_plasma_pedestal=1)
temp_plasma_separatrix_kev = 0.1
temp_plasma_separatrix_electron_kev = 0.1

* Switch for energy confinement time scaling law
i_confinement_time = 34
Expand Down
4 changes: 2 additions & 2 deletions examples/data/large_tokamak_varyrun_IN.DAT
Original file line number Diff line number Diff line change
Expand Up @@ -376,10 +376,10 @@ radius_plasma_pedestal_temp_norm = 0.94
tbeta = 2.0

* Electron temperature of pedestal (kev) (i_plasma_pedestal=1)
temp_plasma_pedestal_kev = 5.5
temp_plasma_separatrix_electron_kev = 5.5

* Electron temperature at separatrix (kev) (i_plasma_pedestal=1)
temp_plasma_separatrix_kev = 0.1
temp_plasma_separatrix_electron_kev = 0.1

* Switch for energy confinement time scaling law
i_confinement_time = 34
Expand Down
4 changes: 2 additions & 2 deletions examples/data/scan_example_file_IN.DAT
Original file line number Diff line number Diff line change
Expand Up @@ -386,10 +386,10 @@ radius_plasma_pedestal_temp_norm = 0.94
tbeta = 2.0

* Electron temperature of pedestal (kev) (i_plasma_pedestal=1)
temp_plasma_pedestal_kev = 5.5
temp_plasma_pedestal_electron_kev = 5.5

* Electron temperature at separatrix (kev) (i_plasma_pedestal=1)
temp_plasma_separatrix_kev = 0.1
temp_plasma_separatrix_electron_kev = 0.1

* Switch for energy confinement time scaling law
i_confinement_time = 34
Expand Down
6 changes: 4 additions & 2 deletions process/core/data_structure/obsolete_vars.py
Original file line number Diff line number Diff line change
Expand Up @@ -410,8 +410,8 @@
"rhopedt": "radius_plasma_pedestal_temp_norm",
"taumax": "t_plasma_energy_confinement_max",
"te": "temp_plasma_electron_vol_avg_kev",
"teped": "temp_plasma_pedestal_kev",
"tesep": "temp_plasma_separatrix_kev",
"teped": "temp_plasma_pedestal_electron_kev",
"tesep": "temp_plasma_separatrix_electron_kev",
"ti": "temp_plasma_ion_vol_avg_kev",
"tratio": "f_temp_plasma_ion_electron",
"ipedestal": "i_plasma_pedestal",
Expand Down Expand Up @@ -479,6 +479,8 @@
"neqns": "n_equality_constraints",
"nineqns": "n_inequality_constraints",
"f_p_div_lower": "f_p_div_lower_separatrix",
"temp_plasma_pedestal_kev": "temp_plasma_pedestal_electron_kev",
"temp_plasma_separatrix_kev": "temp_plasma_separatrix_electron_kev",
}

OBS_VARS_HELP = {
Expand Down
46 changes: 25 additions & 21 deletions process/core/init.py
Original file line number Diff line number Diff line change
Expand Up @@ -430,27 +430,28 @@ def check_process(inputs, data): # noqa: ARG001
if data.ife.ife != 1 and data.physics.i_plasma_pedestal == 1:
# Temperature checks
if (
data.physics.temp_plasma_pedestal_kev
< data.physics.temp_plasma_separatrix_kev
data.physics.temp_plasma_pedestal_electron_kev
< data.physics.temp_plasma_separatrix_electron_kev
):
raise ProcessValidationError(
"Pedestal temperature is lower than separatrix temperature",
temp_plasma_pedestal_kev=data.physics.temp_plasma_pedestal_kev,
temp_plasma_separatrix_kev=data.physics.temp_plasma_separatrix_kev,
temp_plasma_pedestal_electron_kev=data.physics.temp_plasma_pedestal_electron_kev,
temp_plasma_separatrix_electron_kev=data.physics.temp_plasma_separatrix_electron_kev,
)

if (abs(data.physics.radius_plasma_pedestal_temp_norm - 1.0) <= 1e-7) and (
(
data.physics.temp_plasma_pedestal_kev
- data.physics.temp_plasma_separatrix_kev
data.physics.temp_plasma_pedestal_electron_kev
- data.physics.temp_plasma_separatrix_electron_kev
)
>= 1e-7
):
logger.warning(
f"Temperature pedestal is at plasma edge, but temp_plasma_pedestal_kev "
f"({data.physics.temp_plasma_pedestal_kev}) differs from"
" temp_plasma_separatrix_kev"
f" ({data.physics.temp_plasma_separatrix_kev})",
f"Temperature pedestal is at plasma edge, "
"but temp_plasma_pedestal_electron_kev "
f"({data.physics.temp_plasma_pedestal_electron_kev}) differs from"
" temp_plasma_separatrix_electron_kev"
f" ({data.physics.temp_plasma_separatrix_electron_kev})",
stacklevel=2,
)

Expand All @@ -461,32 +462,35 @@ def check_process(inputs, data): # noqa: ARG001
# (which will only have an effect if this is an optimisation run)
if (
data.physics.temp_plasma_electron_vol_avg_kev
<= data.physics.temp_plasma_pedestal_kev
<= data.physics.temp_plasma_pedestal_electron_kev
):
logger.warning(
f"Volume-averaged temperature ({data.physics.te}) has been "
"forced to exceed input pedestal height"
f" ({data.physics.temp_plasma_pedestal_kev}). "
"Changing to te = temp_plasma_pedestal_kev*1.001",
f" ({data.physics.temp_plasma_pedestal_electron_kev}). "
"Changing to te = temp_plasma_pedestal_electron_kev*1.001",
stacklevel=2,
)
data.physics.temp_plasma_electron_vol_avg_kev = (
data.physics.temp_plasma_pedestal_kev * 1.001
data.physics.temp_plasma_pedestal_electron_kev * 1.001
)

if (
data.numerics.i_process_run_mode == PROCESSRunMode.OPTIMISATION
and (data.numerics.ixc[: data.numerics.n_iteration_variables] == 4).any()
and data.numerics.boundl[3] < data.physics.temp_plasma_pedestal_kev * 1.001
and data.numerics.boundl[3]
< data.physics.temp_plasma_pedestal_electron_kev * 1.001
):
logger.warning(
"Lower limit of volume averaged electron temperature"
" (temp_plasma_electron_vol_avg_kev)"
" has been raised to ensure"
" temp_plasma_electron_vol_avg_kev > temp_plasma_pedestal_kev",
" temp_plasma_electron_vol_avg_kev > temp_plasma_pedestal_electron_kev",
stacklevel=2,
)
data.numerics.boundl[3] = data.physics.temp_plasma_pedestal_kev * 1.001
data.numerics.boundl[3] = (
data.physics.temp_plasma_pedestal_electron_kev * 1.001
)
data.numerics.boundu[3] = max(
data.numerics.boundu[3], data.numerics.boundl[3]
)
Expand Down Expand Up @@ -612,12 +616,12 @@ def check_process(inputs, data): # noqa: ARG001
]
== 78
).any():
# If Reinke criterion is used temp_plasma_separatrix_kev is calculated and
# cannot be an iteration variable
# If Reinke criterion is used temp_plasma_separatrix_electron_kev is
# calculated and cannot be an iteration variable
if (data.numerics.ixc[: data.numerics.n_iteration_variables] == 119).any():
raise ProcessValidationError(
"REINKE IMPURITY MODEL: temp_plasma_separatrix_kev is calculated and "
"cannot be an iteration variable for the Reinke model"
"REINKE IMPURITY MODEL: temp_plasma_separatrix_electron_kev is "
"calculated and cannot be an iteration variable for the Reinke model"
)

# If Reinke criterion is used need to enforce LH-threshold
Expand Down
8 changes: 6 additions & 2 deletions process/core/input.py
Original file line number Diff line number Diff line change
Expand Up @@ -825,8 +825,12 @@ def bounds(self) -> tuple[NumberType | None, NumberType | None]:
"temp_fw_coolant_in": InputVariable("fwbs", float, range=(300.0, 1500.0)),
"temp_fw_coolant_out": InputVariable("fwbs", float, range=(300.0, 1500.0)),
"temp_fw_max": InputVariable("fwbs", float, range=(500.0, 2000.0)),
"temp_plasma_pedestal_kev": InputVariable("physics", float, range=(0.0, 20.0)),
"temp_plasma_separatrix_kev": InputVariable("physics", float, range=(0.0, 20.0)),
"temp_plasma_pedestal_electron_kev": InputVariable(
"physics", float, range=(0.0, 20.0)
),
"temp_plasma_separatrix_electron_kev": InputVariable(
"physics", float, range=(0.0, 20.0)
),
"tfcbv": InputVariable("buildings", float, range=(10000.0, 1000000.0)),
"dx_tf_wp_insertion_gap": InputVariable("tfcoil", float, range=(1e-10, 0.1)),
"f_dr_tf_outboard_inboard": InputVariable("build", float, range=(0.2, 5.0)),
Expand Down
4 changes: 2 additions & 2 deletions process/core/io/mfile/comparison.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,9 @@
"nd_plasma_electrons_vol_avg",
"nd_plasma_electron_on_axis",
"f_nd_plasma_greenwald",
"temp_plasma_separatrix_kev",
"temp_plasma_separatrix_electron_kev",
"nd_plasma_separatrix_electron",
"temp_plasma_pedestal_kev",
"temp_plasma_pedestal_electron_kev",
"nd_plasma_pedestal_electron",
"n_charge_plasma_effective_vol_avg",
"nd_plasma_impurities_vol_avg",
Expand Down
55 changes: 34 additions & 21 deletions process/core/io/plot/summary.py
Original file line number Diff line number Diff line change
Expand Up @@ -4278,23 +4278,27 @@ def plot_t_profiles(prof, demo_ranges: bool, mfile: MFile, scan: int):
n_plasma_profile_elements = int(mfile.get("n_plasma_profile_elements", scan=scan))
i_plasma_pedestal = mfile.get("i_plasma_pedestal", scan=scan)
rho = np.linspace(0, 1.0, n_plasma_profile_elements)
temp_plasma_pedestal_kev = mfile.get("temp_plasma_pedestal_kev", scan=scan)
temp_plasma_separatrix_kev = mfile.get("temp_plasma_separatrix_kev", scan=scan)
temp_plasma_pedestal_electron_kev = mfile.get(
"temp_plasma_pedestal_electron_kev", scan=scan
)
temp_plasma_separatrix_electron_kev = mfile.get(
"temp_plasma_separatrix_electron_kev", scan=scan
)
f_temp_plasma_ion_electron = mfile.get("f_temp_plasma_ion_electron", scan=scan)
tbeta = mfile.get("tbeta", scan=scan)
te0 = mfile.get("temp_plasma_electron_on_axis_kev", scan=scan)

if i_plasma_pedestal == 1:
rhocore = np.linspace(0.0, radius_plasma_pedestal_temp_norm)
tcore = (
temp_plasma_pedestal_kev
+ (te0 - temp_plasma_pedestal_kev)
temp_plasma_pedestal_electron_kev
+ (te0 - temp_plasma_pedestal_electron_kev)
* (1 - (rhocore / radius_plasma_pedestal_temp_norm) ** tbeta) ** alphat
)

rhosep = np.linspace(radius_plasma_pedestal_temp_norm, 1)
tsep = temp_plasma_separatrix_kev + (
temp_plasma_pedestal_kev - temp_plasma_separatrix_kev
tsep = temp_plasma_separatrix_electron_kev + (
temp_plasma_pedestal_electron_kev - temp_plasma_separatrix_electron_kev
) * (1 - rhosep) / (1 - min(0.9999, radius_plasma_pedestal_temp_norm))

rho = np.append(rhocore, rhosep)
Expand Down Expand Up @@ -4322,7 +4326,7 @@ def plot_t_profiles(prof, demo_ranges: bool, mfile: MFile, scan: int):
if i_plasma_pedestal != 0:
# Plot pedestal lines
prof.axhline(
y=temp_plasma_pedestal_kev,
y=temp_plasma_pedestal_electron_kev,
xmax=radius_plasma_pedestal_temp_norm,
color="r",
linestyle="-",
Expand All @@ -4332,7 +4336,7 @@ def plot_t_profiles(prof, demo_ranges: bool, mfile: MFile, scan: int):
prof.vlines(
x=radius_plasma_pedestal_temp_norm,
ymin=0.0,
ymax=temp_plasma_pedestal_kev,
ymax=temp_plasma_pedestal_electron_kev,
color="r",
linestyle="-",
linewidth=0.4,
Expand All @@ -4350,22 +4354,26 @@ def plot_t_profiles(prof, demo_ranges: bool, mfile: MFile, scan: int):
),
(
rf"$T_{{\text{{e,0}}}}$: {te0:.3f} keV"
rf"$\hspace{{2}} \alpha_{{\text{{T}}}}$: {alphat:.3f}"
rf"$\hspace{{3}} \alpha_{{\text{{T}}}}$: {alphat:.3f} "
rf"$\hspace{{3}} \langle T_{{\text{{i}}}} \rangle_\text{{V}}$: {mfile.get('temp_plasma_ion_vol_avg_kev', scan=scan):.3f} keV"
),
(
rf"$T_{{\text{{e,ped}}}}$: {temp_plasma_pedestal_kev:.3f} keV"
r"$ \hspace{3} \frac{\langle T_i \rangle}{\langle T_e \rangle}$: "
f"{f_temp_plasma_ion_electron:.3f}"
rf"$T_{{\text{{e,ped}}}}$: {temp_plasma_pedestal_electron_kev:.3f} keV"
r"$ \hspace{3} \frac{\langle T_i \rangle}{\langle T_e \rangle}$: "
f"{f_temp_plasma_ion_electron:.3f} "
f"$\\hspace{{4}} T_{{\\text{{i,0}}}}$: {mfile.get('temp_plasma_ion_on_axis_kev', scan=scan):.3f} keV"
),
(
rf"$\rho_{{\text{{ped,T}}}}$: {radius_plasma_pedestal_temp_norm:.3f}"
r"$ \hspace{5} \frac{T_{e,0}}{\langle T_e \rangle}$: "
f"{mfile.get('f_temp_plasma_electron_on_axis_vol_avg', scan=scan):.3f}"
f"{mfile.get('f_temp_plasma_electron_on_axis_vol_avg', scan=scan):.3f} "
f"$\\hspace{{4}} T_{{\\text{{i,ped}}}}$: {mfile.get('temp_plasma_pedestal_ion_kev', scan=scan):.3f} keV"
),
(
rf"$T_{{\text{{e,sep}}}}$: {temp_plasma_separatrix_kev:.3f} keV"
r"$ \hspace{3} \frac{{{\langle T_e \rangle_n}}}{{{\langle T_e \rangle_V}}}$: "
rf"$T_{{\text{{e,sep}}}}$: {temp_plasma_separatrix_electron_kev:.3f} keV"
r"$\hspace{3} \frac{{{\langle T_e \rangle_n}}}{{{\langle T_e \rangle_V}}}$: "
f"{mfile.get('f_temp_plasma_electron_density_vol_avg', scan=scan):.3f}"
f"$\\hspace{{4}} T_{{\\text{{i,sep}}}}$: {mfile.get('temp_plasma_separatrix_ion_kev', scan=scan):.3f} keV"
),
))

Expand Down Expand Up @@ -4530,8 +4538,12 @@ def profiles_with_pedestal(mfile, scan: int):
ne0 = mfile.get("nd_plasma_electron_on_axis", scan=scan)
rho = np.linspace(0, 1.0, n_plasma_profile_elements)
nd_plasma_separatrix_electron = mfile.get("nd_plasma_separatrix_electron", scan=scan)
temp_plasma_pedestal_kev = mfile.get("temp_plasma_pedestal_kev", scan=scan)
temp_plasma_separatrix_kev = mfile.get("temp_plasma_separatrix_kev", scan=scan)
temp_plasma_pedestal_electron_kev = mfile.get(
"temp_plasma_pedestal_electron_kev", scan=scan
)
temp_plasma_separatrix_electron_kev = mfile.get(
"temp_plasma_separatrix_electron_kev", scan=scan
)
tbeta = mfile.get("tbeta", scan=scan)
te0 = mfile.get("temp_plasma_electron_on_axis_kev", scan=scan)

Expand Down Expand Up @@ -4569,15 +4581,16 @@ def profiles_with_pedestal(mfile, scan: int):
# Core temperature region
if rho[q] <= radius_plasma_pedestal_temp_norm:
te[q] = (
temp_plasma_pedestal_kev
+ (te0 - temp_plasma_pedestal_kev)
temp_plasma_pedestal_electron_kev
+ (te0 - temp_plasma_pedestal_electron_kev)
* (1 - (rho[q] / radius_plasma_pedestal_temp_norm) ** tbeta)
** alphat
)
else:
# Pedestal temperature region
te[q] = temp_plasma_separatrix_kev + (
temp_plasma_pedestal_kev - temp_plasma_separatrix_kev
te[q] = temp_plasma_separatrix_electron_kev + (
temp_plasma_pedestal_electron_kev
- temp_plasma_separatrix_electron_kev
) * (1 - rho[q]) / (1 - radius_plasma_pedestal_temp_norm)

return rho, ne, te
Expand Down
2 changes: 1 addition & 1 deletion process/core/solver/iteration_variables.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ class IterationVariable:
108: IterationVariable("breeder_f", "fwbs", 0.060, 1.0),
109: IterationVariable("f_nd_alpha_thermal_electron", "physics", 0.05, 0.15),
114: IterationVariable("len_fw_channel", "fwbs", 0.001, 1.0e3),
119: IterationVariable("temp_plasma_separatrix_kev", "physics", 0.0, 1.0e1),
119: IterationVariable("temp_plasma_separatrix_electron_kev", "physics", 0.0, 1.0e1),
122: IterationVariable("f_a_cs_turn_steel", "pf_coil", 0.001, 0.950),
125: IterationVariable(
"f_nd_impurity_electrons(03)",
Expand Down
Loading
Loading