Skip to content
Open
28 changes: 26 additions & 2 deletions process/core/io/plot/summary.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
PlasmaGeometryModelType,
PlasmaShapeModelType,
)
from process.models.physics.profiles import PlasmaProfileShapeType
from process.models.superconductors import SuperconductorModel
from process.models.tfcoil.base import (
TFCoilShapeModel,
Expand Down Expand Up @@ -4348,7 +4349,7 @@ def plot_t_profiles(prof, demo_ranges: bool, mfile: MFile, scan: int):
(
rf"$\rho_{{\text{{ped,T}}}}$: {radius_plasma_pedestal_temp_norm:.3f}"
r"$ \hspace{5} \frac{T_{e,0}}{\langle T_e \rangle}$: "
f"{te0 / te:.3f}"
f"{mfile.get('f_temp_plasma_electron_on_axis_vol_avg', scan=scan):.3f}"
),
(
rf"$T_{{\text{{e,sep}}}}$: {temp_plasma_separatrix_kev:.3f} keV"
Expand Down Expand Up @@ -12117,7 +12118,10 @@ def plot_plasma_pressure_profiles(axis: plt.Axes, mfile: MFile, scan: int):
axis.legend()

textstr_pressure = "\n".join((
rf"$p_0$: {mfile.get('pres_plasma_thermal_on_axis', scan=scan) / 1000:,.3f} kPa",
(
rf"$p_0$: {mfile.get('pres_plasma_thermal_on_axis', scan=scan) / 1000:,.3f} kPa"
rf"$\hspace{{2}} \frac{{p_0}}{{\langle p_{{\text{{total}}}} \rangle_\text{{V}}}}$: {mfile.get('f_pres_plasma_thermal_on_axis_vol_avg', scan=scan):,.3f}"
),
rf"$\langle p_{{\text{{total}}}} \rangle_\text{{V}}$: {mfile.get('pres_plasma_thermal_vol_avg', scan=scan) / 1000:,.3f} kPa",
))

Expand All @@ -12132,6 +12136,26 @@ def plot_plasma_pressure_profiles(axis: plt.Axes, mfile: MFile, scan: int):
bbox={"boxstyle": "round", "facecolor": "wheat", "alpha": 0.5},
)

if (
int(mfile.get("i_plasma_pedestal", scan=scan))
== PlasmaProfileShapeType.PEDESTAL_PROFILE
):
textstr_pressure_pedestal = "\n".join((
rf"$p_{{\text{{ped}}}}$: {mfile.get('pres_plasma_pedestal_thermal', scan=scan) / 1000:,.3f} kPa",
rf"$p_{{\text{{sep}}}}$: {mfile.get('pres_plasma_separatrix_thermal', scan=scan) / 1000:,.3f} kPa",
))

axis.text(
0.9,
1.2,
textstr_pressure_pedestal,
transform=axis.transAxes,
fontsize=9,
verticalalignment="top",
horizontalalignment="center",
bbox={"boxstyle": "round", "facecolor": "wheat", "alpha": 0.5},
)


def plot_plasma_current_comparison(axis: plt.Axes, mfile: MFile, scan: int):
"""Function to plot a scatter box plot of different plasma current comparisons.
Expand Down
12 changes: 12 additions & 0 deletions process/data_structure/physics_variables.py
Original file line number Diff line number Diff line change
Expand Up @@ -992,6 +992,9 @@ class PhysicsData:
pres_plasma_thermal_on_axis: float = 0.0
"""Plasma central thermal pressure (p₀) (no fast ions or beam pressure) [Pa]"""

f_pres_plasma_thermal_on_axis_vol_avg: float = 0.0

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Maybe this is a real nit-pick but if it's a ratio should we use the "fraction" prefix for the variable name?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

We dont really have anything else in the style guide that fits the bill. f_ still represents a dimensionless unit that is the portion of something else

"""Ratio of central plasma thermal pressure to volume averaged (p₀/⟨p⟩)"""

pres_plasma_thermal_total_profile: list[float] = field(default_factory=list)
"""Profile of total pressure in plasma [Pa]"""

Expand All @@ -1004,6 +1007,12 @@ class PhysicsData:
pres_plasma_fuel_profile: list[float] = field(default_factory=list)
"""Profile of fuel pressure in plasma [Pa]"""

pres_plasma_pedestal_thermal: float = 0.0
"""Plasma pedestal thermal pressure (p_ped) (no fast ions or beam pressure) [Pa]"""

pres_plasma_separatrix_thermal: float = 0.0
"""Plasma separatrix thermal pressure (pₛₑₚ) (no fast ions or beam pressure) [Pa]"""

j_plasma_on_axis: float = 0.0
"""Central plasma current density (j₀) [A/m²]"""

Expand Down Expand Up @@ -1355,6 +1364,9 @@ class PhysicsData:
temp_plasma_electron_on_axis_kev: float = 0.0
"""Plasma central electron temperature (Tₑ₀) [keV]"""

f_temp_plasma_electron_on_axis_vol_avg: float = 0.0
"""Ratio of plasma central electron temperature to volume averaged (Tₑ₀/⟨Tₑ⟩)"""

temp_plasma_electron_density_weighted_kev: float = 0.0
"""Density weighted average electron temperature (⟨Tₑ⟩_n) [keV]"""

Expand Down
38 changes: 35 additions & 3 deletions process/models/physics/physics.py
Original file line number Diff line number Diff line change
Expand Up @@ -2534,6 +2534,13 @@ def output_temperature_density_profile_info(self) -> None:
self.data.physics.temp_plasma_electron_on_axis_kev,
"OP ",
)
po.ovarre(
self.outfile,
"Ratio of electron temperature on axis to volume averaged (Tₑ₀/⟨Tₑ⟩)",
"(f_temp_plasma_electron_on_axis_vol_avg)",
self.data.physics.f_temp_plasma_electron_on_axis_vol_avg,
"OP ",
)
po.ovarre(
self.outfile,
"Line averaged electron temperature (keV)",
Expand Down Expand Up @@ -2792,6 +2799,31 @@ def output_temperature_density_profile_info(self) -> None:
self.data.physics.pres_plasma_thermal_vol_avg,
"OP ",
)
po.ovarre(
self.outfile,
"Central to volume averaged plasma thermal pressure ratio (p₀/⟨p⟩)",
"(f_pres_plasma_thermal_on_axis_vol_avg)",
self.data.physics.f_pres_plasma_thermal_on_axis_vol_avg,
"OP ",
)
if (
self.data.physics.i_plasma_pedestal
== PlasmaProfileShapeType.PEDESTAL_PROFILE
):
po.oblnkl(self.outfile)
po.ovarre(
self.outfile,
"Plasma thermal pressure at pedestal (p_ped) [Pa]",
"(pres_plasma_pedestal_thermal)",
self.data.physics.pres_plasma_pedestal_thermal,
)
po.ovarre(
self.outfile,
"Plasma thermal pressure at separatrix (pₛₑₚ) [Pa]",
"(pres_plasma_separatrix_thermal)",
self.data.physics.pres_plasma_separatrix_thermal,
)

# As array output is not currently supported, each element is output as a float
# instance
# Output plasma pressure profiles to mfile
Expand Down Expand Up @@ -2831,21 +2863,21 @@ def output_temperature_density_profile_info(self) -> None:

po.ovarre(
self.outfile,
"Total plasma thermal energy [W]",
"Total plasma thermal energy [J]",
"(e_plasma_thermal_total)",
self.data.physics.e_plasma_thermal_total,
"OP ",
)
po.ovarre(
self.outfile,
"Plasma thermal energy in electrons [W]",
"Plasma thermal energy in electrons [J]",
"(e_plasma_electrons_thermal)",
self.data.physics.e_plasma_electrons_thermal,
"OP ",
)
po.ovarre(
self.outfile,
"Plasma thermal energy in ions [W]",
"Plasma thermal energy in ions [J]",
"(e_plasma_ions_thermal)",
self.data.physics.e_plasma_ions_thermal,
"OP ",
Expand Down
42 changes: 42 additions & 0 deletions process/models/physics/plasma_profiles.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,11 @@ def parabolic_parameterisation(self):
* (1.0 + self.data.physics.alphat)
)

self.data.physics.f_temp_plasma_electron_on_axis_vol_avg = (
self.data.physics.temp_plasma_electron_on_axis_kev
/ self.data.physics.temp_plasma_electron_vol_avg_kev
)

self.data.physics.nd_plasma_electron_on_axis = (
self.data.physics.nd_plasma_electrons_vol_avg
* (1.0 + self.data.physics.alphan)
Expand Down Expand Up @@ -237,6 +242,11 @@ def pedestal_parameterisation(self):
self.teprofile.profile_integ
)

self.data.physics.f_temp_plasma_electron_on_axis_vol_avg = (
self.data.physics.temp_plasma_electron_on_axis_kev
/ self.data.physics.temp_plasma_electron_vol_avg_kev
)

# Scrape-off density / volume averaged density
# (Input value is used if i_plasma_pedestal = 0)

Expand Down Expand Up @@ -284,6 +294,33 @@ def calculate_profile_factors(self):
+ self.data.physics.pres_plasma_ion_total_profile
)

# Calculate pedestal and separatrix pressures for pedestal profile case
if (
PlasmaProfileShapeType(self.data.physics.i_plasma_pedestal)
== PlasmaProfileShapeType.PEDESTAL_PROFILE
):
# Pedestal pressure is the profile value where gradient is maximum
# (i.e the smallest negative value)
rho = self.neprofile.profile_x
pres_profile = self.data.physics.pres_plasma_thermal_total_profile
dpres_drho = np.gradient(pres_profile, rho)
# Find rho index closest to the normalized pedestal positions
pedestal_rho = np.min([
self.data.physics.radius_plasma_pedestal_temp_norm,
self.data.physics.radius_plasma_pedestal_density_norm,
])
closest_idx = np.argmin(np.abs(rho - pedestal_rho))
mask = np.zeros_like(rho, dtype=bool)
mask[closest_idx:] = True
dpres_drho_pedestal = dpres_drho[mask]
max_grad_idx_pedestal = np.argmax(dpres_drho_pedestal)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Should this use np.argmin? Since the pressure decreases with increasing radius, the steepest pedestal gradient should be the most negative value

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I found that using np.argmin gets you closer to the pedestal in the large tokamak case as it plateus very quickly before the pedestal point. If you go for the max at the pedestal drop their is about a 10kPa difference. I do worry that this will break if a very flat profile is used so the pressure profile is practically vertical before the pedestal point

image

max_grad_idx = np.where(mask)[0][max_grad_idx_pedestal]
self.data.physics.pres_plasma_pedestal_thermal = pres_profile[max_grad_idx]

self.data.physics.pres_plasma_separatrix_thermal = (
self.data.physics.pres_plasma_thermal_total_profile[-1]
)

# Fuel ion pressure profile (Pa)
self.data.physics.pres_plasma_fuel_profile = (
self.data.physics.nd_plasma_fuel_ions_vol_avg
Expand Down Expand Up @@ -312,6 +349,11 @@ def calculate_profile_factors(self):
* self.data.physics.temp_plasma_ion_density_weighted_kev
) * constants.KILOELECTRON_VOLT

self.data.physics.f_pres_plasma_thermal_on_axis_vol_avg = (
self.data.physics.pres_plasma_thermal_on_axis
/ self.data.physics.pres_plasma_thermal_vol_avg
)

# Central plasma current density (A/m²)
# Assumes a parabolic profile for the current density
self.data.physics.j_plasma_on_axis = (
Expand Down
Loading