Add PlasmaDensityLimit class and integrate into physics and stellarat…#4093
Add PlasmaDensityLimit class and integrate into physics and stellarat…#4093chris-ashe wants to merge 16 commits intomainfrom
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #4093 +/- ##
==========================================
+ Coverage 46.86% 46.94% +0.07%
==========================================
Files 136 137 +1
Lines 29228 29319 +91
==========================================
+ Hits 13698 13764 +66
- Misses 15530 15555 +25 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
e2784ec to
aa1518c
Compare
timothy-nunn
left a comment
There was a problem hiding this comment.
Please fix conflicts before a review can be provided
d46b934 to
f9d01b2
Compare
98854e8 to
a4f2d2d
Compare
There was a problem hiding this comment.
Several density limit models are available in PROCESS. These are
calculated in routinecalculate_density_limit(), which is called byphysics.
Needs to be updated to reflect the new class
process/models/physics/physics.py
Outdated
| def calculate_density_limit( | ||
| self, | ||
| b_plasma_toroidal_on_axis: float, | ||
| i_density_limit: int, | ||
| p_plasma_separatrix_mw: float, | ||
| p_hcd_injected_total_mw: float, | ||
| plasma_current: float, | ||
| prn1: float, | ||
| qcyl: float, | ||
| q95: float, | ||
| rmajor: float, | ||
| rminor: float, | ||
| a_plasma_surface: float, | ||
| zeff: float, | ||
| ) -> tuple[np.ndarray, float]: | ||
| """ | ||
| Calculate the density limit using various models. | ||
|
|
||
| Args: | ||
| b_plasma_toroidal_on_axis (float): Toroidal field on axis (T). | ||
| i_density_limit (int): Switch denoting which formula to enforce. | ||
| p_plasma_separatrix_mw (float): Power flowing to the edge plasma via charged particles (MW). | ||
| p_hcd_injected_total_mw (float): Power injected into the plasma (MW). | ||
| plasma_current (float): Plasma current (A). | ||
| prn1 (float): Edge density / average plasma density. | ||
| qcyl (float): Equivalent cylindrical safety factor (qstar). | ||
| q95 (float): Safety factor at 95% surface. | ||
| rmajor (float): Plasma major radius (m). | ||
| rminor (float): Plasma minor radius (m). | ||
| a_plasma_surface (float): Plasma surface area (m^2). | ||
| zeff (float): Plasma effective charge. | ||
|
|
||
| Returns: | ||
| Tuple[np.ndarray, float]: A tuple containing: | ||
| - nd_plasma_electron_max_array (np.ndarray): Average plasma density limit using seven different models (m^-3). | ||
| - nd_plasma_electrons_max (float): Enforced average plasma density limit (m^-3). | ||
|
|
||
| Raises: | ||
| ValueError: If i_density_limit is not between 1 and 7. | ||
|
|
||
| Notes: | ||
| This routine calculates several different formulae for the density limit and enforces the one chosen by the user. | ||
| For i_density_limit = 1-5, 8, we scale the sepatrix density limit output by the ratio of the separatrix to volume averaged density | ||
|
|
||
| References: | ||
| - AEA FUS 172: Physics Assessment for the European Reactor Study | ||
|
|
||
| - N.A. Uckan and ITER Physics Group, 'ITER Physics Design Guidelines: 1989 | ||
|
|
||
| - M. Bernert et al., “The H-mode density limit in the full tungsten ASDEX Upgrade tokamak,” | ||
| vol. 57, no. 1, pp. 014038-014038, Nov. 2014, doi: https://doi.org/10.1088/0741-3335/57/1/014038. | ||
| """ | ||
|
|
||
| if i_density_limit < 1 or i_density_limit > 7: | ||
| raise ProcessValueError( | ||
| "Illegal value for i_density_limit", i_density_limit=i_density_limit | ||
| ) | ||
|
|
||
| nd_plasma_electron_max_array = np.empty((8,)) | ||
|
|
||
| # Power per unit area crossing the plasma edge | ||
| # (excludes radiation and neutrons) | ||
|
|
||
| p_perp = p_plasma_separatrix_mw / a_plasma_surface | ||
|
|
||
| # Old ASDEX density limit formula | ||
| # This applies to the density at the plasma edge, so must be scaled | ||
| # to give the density limit applying to the average plasma density. | ||
|
|
||
| nd_plasma_electron_max_array[0] = self.calculate_asdex_density_limit( | ||
| p_perp=p_perp, | ||
| b_plasma_toroidal_on_axis=b_plasma_toroidal_on_axis, | ||
| q95=q95, | ||
| rmajor=rmajor, | ||
| prn1=prn1, | ||
| ) | ||
|
|
||
| # Borrass density limit model for ITER (I) | ||
| # This applies to the density at the plasma edge, so must be scaled | ||
| # to give the density limit applying to the average plasma density. | ||
| # Borrass et al, ITER-TN-PH-9-6 (1989) | ||
|
|
||
| nd_plasma_electron_max_array[1] = self.calculate_borrass_iter_i_density_limit( | ||
| p_perp=p_perp, | ||
| b_plasma_toroidal_on_axis=b_plasma_toroidal_on_axis, | ||
| q95=q95, | ||
| rmajor=rmajor, | ||
| prn1=prn1, | ||
| ) | ||
|
|
||
| # Borrass density limit model for ITER (II) | ||
| # This applies to the density at the plasma edge, so must be scaled | ||
| # to give the density limit applying to the average plasma density. | ||
| # This formula is (almost) identical to that in the original routine | ||
| # denlim (now deleted). | ||
|
|
||
| nd_plasma_electron_max_array[2] = self.calculate_borrass_iter_ii_density_limit( | ||
| p_perp=p_perp, | ||
| b_plasma_toroidal_on_axis=b_plasma_toroidal_on_axis, | ||
| q95=q95, | ||
| rmajor=rmajor, | ||
| prn1=prn1, | ||
| ) | ||
|
|
||
| # JET edge radiation density limit model | ||
| # This applies to the density at the plasma edge, so must be scaled | ||
| # to give the density limit applying to the average plasma density. | ||
| # qcyl=qstar here, but literature is not clear. | ||
|
|
||
| nd_plasma_electron_max_array[3] = ( | ||
| self.calculate_jet_edge_radiation_density_limit( | ||
| zeff=zeff, | ||
| p_hcd_injected_total_mw=p_hcd_injected_total_mw, | ||
| prn1=prn1, | ||
| qcyl=qcyl, | ||
| ) | ||
| ) | ||
|
|
||
| # JET simplified density limit model | ||
| # This applies to the density at the plasma edge, so must be scaled | ||
| # to give the density limit applying to the average plasma density. | ||
|
|
||
| nd_plasma_electron_max_array[4] = self.calculate_jet_simple_density_limit( | ||
| b_plasma_toroidal_on_axis=b_plasma_toroidal_on_axis, | ||
| p_plasma_separatrix_mw=p_plasma_separatrix_mw, | ||
| rmajor=rmajor, | ||
| prn1=prn1, | ||
| ) | ||
|
|
||
| # Hugill-Murakami M.q limit | ||
| # qcyl=qstar here, which is okay according to the literature | ||
|
|
||
| nd_plasma_electron_max_array[5] = self.calculate_hugill_murakami_density_limit( | ||
| b_plasma_toroidal_on_axis=b_plasma_toroidal_on_axis, rmajor=rmajor, qcyl=qcyl | ||
| ) | ||
|
|
||
| # Greenwald limit | ||
|
|
||
| nd_plasma_electron_max_array[6] = self.calculate_greenwald_density_limit( | ||
| c_plasma=plasma_current, rminor=rminor | ||
| ) | ||
|
|
||
| nd_plasma_electron_max_array[7] = self.calculate_asdex_new_density_limit( | ||
| p_hcd_injected_total_mw=p_hcd_injected_total_mw, | ||
| c_plasma=plasma_current, | ||
| q95=q95, | ||
| prn1=prn1, | ||
| ) | ||
|
|
||
| # Enforce the chosen density limit | ||
|
|
||
| return nd_plasma_electron_max_array, nd_plasma_electron_max_array[ | ||
| i_density_limit - 1 | ||
| ] |
There was a problem hiding this comment.
Is this ever called by the code?
There was a problem hiding this comment.
Its ran from self.density_limit.run() on line 2462
|
|
||
| nd_plasma_electron_max_array, nd_plasma_electrons_max = ( | ||
| physics.calculate_density_limit( | ||
| PlasmaDensityLimit().calculate_density_limit( |
There was a problem hiding this comment.
| PlasmaDensityLimit().calculate_density_limit( | |
| physics.density_limit.calculate_density_limit( |
There was a problem hiding this comment.
The documentation style for this file is out of date, please use the numpy style
There was a problem hiding this comment.
Changed to numpy
…or models
Description
Checklist
I confirm that I have completed the following checks: