diff --git a/process/core/io/plot/summary.py b/process/core/io/plot/summary.py index e8b2fea071..e0af7b6a56 100644 --- a/process/core/io/plot/summary.py +++ b/process/core/io/plot/summary.py @@ -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, @@ -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" @@ -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", )) @@ -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. diff --git a/process/data_structure/physics_variables.py b/process/data_structure/physics_variables.py index 28e37dee79..deaf4331d9 100644 --- a/process/data_structure/physics_variables.py +++ b/process/data_structure/physics_variables.py @@ -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 + """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]""" @@ -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²]""" @@ -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]""" diff --git a/process/models/physics/physics.py b/process/models/physics/physics.py index 413e545d4c..a2fdbef65b 100644 --- a/process/models/physics/physics.py +++ b/process/models/physics/physics.py @@ -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)", @@ -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 @@ -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 ", diff --git a/process/models/physics/plasma_profiles.py b/process/models/physics/plasma_profiles.py index f54f6167f2..a259a11330 100644 --- a/process/models/physics/plasma_profiles.py +++ b/process/models/physics/plasma_profiles.py @@ -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) @@ -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) @@ -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) + 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 @@ -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 = (