diff --git a/documentation/scripts/plotting_scripts/fast_alpha_pressure.py b/documentation/scripts/plotting_scripts/fast_alpha_pressure.py
index 5a3470c899..cf23bbe7bd 100644
--- a/documentation/scripts/plotting_scripts/fast_alpha_pressure.py
+++ b/documentation/scripts/plotting_scripts/fast_alpha_pressure.py
@@ -52,7 +52,7 @@
const y1 = Array.from(x, (x) => 0.29 * (A/20 - 0.37) * (x)**2) // Example transformation for the first line
const y2 = Array.from(x, (x) => 0.26 * (A/20 - 0.65)**0.5 * (x)**2) // Example transformation for the second line
source.data = { x, y1, y2 }
-""",
+""", # noqa: E501
)
te.js_on_change("value", callback)
diff --git a/documentation/scripts/plotting_scripts/plasma_cross_section_plot.py b/documentation/scripts/plotting_scripts/plasma_cross_section_plot.py
index 37c33ce4c1..fc2f0aa524 100644
--- a/documentation/scripts/plotting_scripts/plasma_cross_section_plot.py
+++ b/documentation/scripts/plotting_scripts/plasma_cross_section_plot.py
@@ -157,7 +157,7 @@
ys2_mirror[i] = ys2[i];
}
source.change.emit();
-""",
+""", # noqa: E501
)
r0.js_on_change("value", callback)
diff --git a/documentation/scripts/plotting_scripts/profile_hastie_current.py b/documentation/scripts/plotting_scripts/profile_hastie_current.py
index a7c08ac3d2..7c3d2a0c5f 100644
--- a/documentation/scripts/plotting_scripts/profile_hastie_current.py
+++ b/documentation/scripts/plotting_scripts/profile_hastie_current.py
@@ -51,7 +51,7 @@
const y1 = Array.from(x, (x) => A * (1 - x**2)**B)
const y2 = Array.from(x, (x) => A / (1+B*x**2)**2) // Example transformation for the second line
source.data = { x, y1, y2 }
-""",
+""", # noqa: E501
)
n0.js_on_change("value", callback)
diff --git a/documentation/scripts/plotting_scripts/profile_peng_qbar.py b/documentation/scripts/plotting_scripts/profile_peng_qbar.py
index d731683713..3a7cc9654b 100644
--- a/documentation/scripts/plotting_scripts/profile_peng_qbar.py
+++ b/documentation/scripts/plotting_scripts/profile_peng_qbar.py
@@ -54,7 +54,7 @@
source.data['y1'] = y1;
source.data['y2'] = y2;
source.change.emit();
-""",
+""", # noqa: E501
)
q95.js_on_change("value", callback)
diff --git a/documentation/scripts/plotting_scripts/western_nb3sn_critical_surface.py b/documentation/scripts/plotting_scripts/western_nb3sn_critical_surface.py
index f9448d33b9..117336fad6 100644
--- a/documentation/scripts/plotting_scripts/western_nb3sn_critical_surface.py
+++ b/documentation/scripts/plotting_scripts/western_nb3sn_critical_surface.py
@@ -36,7 +36,8 @@
ax.set_ylabel("Magnetic field at superconductor (T)")
ax.set_zlabel("$J_{\\text{crit}}$ (kA/mm²)")
ax.set_title(
- "Western Superconducting Ltd. Nb\u2083Sn Critical Current Density Surface at Zero Strain"
+ "Western Superconducting Ltd. Nb\u2083Sn"
+ " Critical Current Density Surface at Zero Strain"
)
ax.view_init(elev=30, azim=45) # Rotate the plot around the z-axis by 45 degrees
fig.colorbar(surf, shrink=0.5, aspect=10)
@@ -52,7 +53,8 @@
# Update layout for better visualization
fig_plotly.update_layout(
- title="Western Superconducting Ltd. Nb\u2083Sn Critical Current Density Surface at Zero Strain",
+ title="Western Superconducting Ltd. Nb\u2083Sn"
+ " Critical Current Density Surface at Zero Strain",
scene={
"xaxis_title": "Temperature of superconductor (K)",
"yaxis_title": "Magnetic field strength at superconductor (T)",
diff --git a/examples/introduction.ex.py b/examples/introduction.ex.py
index e180c56648..db216070b4 100644
--- a/examples/introduction.ex.py
+++ b/examples/introduction.ex.py
@@ -23,19 +23,27 @@
# %% [markdown]
#
-# NOTE We run the examples in a temporary directory so all the inputs are copied there and the outputs contained there before the directory is removed when the example has finished running. This keeps the examples directory tidy and does not permanently modify any data files. The use of temporary directories is not needed for regular use of PROCESS.
+# NOTE We run the examples in a temporary directory so all the inputs are copied
+# there and the outputs contained there before the directory is removed when the example
+# has finished running.
+# This keeps the examples directory tidy and does not permanently modify any data files.
+# The use of temporary directories is not needed for regular use of PROCESS.
#
# %% [markdown]
-# Process can be run from the command line with the `process` command or as a standard python package.
-# Using process as a package allows for more complex scripting of a process run for different tasks.
+# Process can be run from the command line with the `process` command or as a standard
+# python package.
+# Using process as a package allows for more complex scripting of a process run for
+# different tasks.
# %% [markdown]
# ## Basic run of Process
-# Run Process on an input file using the `SingleRun` class. This outputs an `MFILE.DAT` and an `OUT.DAT`.
+# Run Process on an input file using the `SingleRun` class.
+# This outputs an `MFILE.DAT` and an `OUT.DAT`.
#
-# This is equivalent to running `process -i data/large_tokamak_IN.DAT` in the examples folder.
+# This is equivalent to running `process -i data/large_tokamak_IN.DAT`
+# in the examples folder.
# %%
# %load_ext autoreload
diff --git a/examples/optimum_solutions_comparison.ex.py b/examples/optimum_solutions_comparison.ex.py
index becbe80259..540783db03 100644
--- a/examples/optimum_solutions_comparison.ex.py
+++ b/examples/optimum_solutions_comparison.ex.py
@@ -18,25 +18,43 @@
# # Optimum solutions comparison notebook
#
# %% [markdown]
-# A Jupyter notebook to demonstrate how changing input parameters changes the optimum solution found by PROCESS.
+# A Jupyter notebook to demonstrate how changing input parameters changes the optimum
+# solution found by PROCESS.
#
# %% [markdown]
#
-# NOTE We run the examples in a temporary directory so all the inputs are copied there and the outputs contained there before the directory is removed when the example has finished running. This keeps the examples directory tidy and does not permanently modify any data files. The use of temporary directories is not needed for regular use of PROCESS.
+# NOTE We run the examples in a temporary directory so all the inputs are copied
+# there and the outputs contained there before the directory is removed when the example
+# has finished running.
+# This keeps the examples directory tidy and does not permanently modify any data files.
+# The use of temporary directories is not needed for regular use of PROCESS.
#
# %% [markdown]
-# This notebook demonstrates how the optimum solution found by `PROCESS` changes as we vary input parameters. We will use the large tokamak example input file to do this. The figure of merit for this example is to minimise the major radius, `rmajor`.
+# This notebook demonstrates how the optimum solution found by `PROCESS` changes
+# as we vary input parameters.
+# We will use the large tokamak example input file to do this.
+# The figure of merit for this example is to minimise the major radius, `rmajor`.
#
-# We use the functionality from `plot.solutions` and from `plot.summary` to demonstrate this.
+# We use the functionality from `plot.solutions` and from `plot.summary`
+# to demonstrate this.
#
-# These tools plot the solution vectors (i.e. final values of optimisation parameters) for different runs of `PROCESS`. This allows visual comparisons of different solution points.
+# These tools plot the solution vectors (i.e. final values of optimisation parameters)
+# for different runs of `PROCESS`.
+# This allows visual comparisons of different solution points.
#
-# It can use different intra-solution optimisation parameter normalisations (e.g. initial value, parameter range) and inter-solution normalisations (e.g. normalise to a certain solution).
+# It can use different intra-solution optimisation parameter normalisations
+# (e.g. initial value, parameter range)
+# and inter-solution normalisations (e.g. normalise to a certain solution).
#
# ### Known Limitations
#
-# - The solution vectors (optimisation parameter values at the solution) currently plotted are normalised to the initial point (from the `IN.DAT`) of each solution: each element of the vector is the $x_{final}/x_{initial}$, the `xcmxxx` values in the `MFILE.DAT`. This allows all optimisation parameters to be plotted on the same axis, showing the relative changes from their initial values across multiple solutions.
+# - The solution vectors (optimisation parameter values at the solution) currently
+# plotted are normalised to the initial point (from the `IN.DAT`) of each solution:
+# each element of the vector is the $x_{final}/x_{initial}$,
+# the `xcmxxx` values in the `MFILE.DAT`.
+# This allows all optimisation parameters to be plotted on the same axis,
+# showing the relative changes from their initial values across multiple solutions.
# - Solutions being plotted together must also have the same optimisation parameters.
# - The solutions plotted in this example are fictitious.
@@ -90,7 +108,9 @@
# %% [markdown]
# # Plot single solution
#
-# First we will look at the original large tokamak optimum solution. We will plot its solution, showing optimisation parameters normalised to their initial values.
+# First we will look at the original large tokamak optimum solution.
+# We will plot its solution, showing optimisation parameters normalised
+# to their initial values.
# %%
large_tokamak_mfile = working_dir / "large_tokamak_MFILE.DAT"
@@ -109,11 +129,15 @@
# %% [markdown]
# # Comparing optimum solutions
#
-# Now we will see the effect that varying an input parameter in the large tokamak input file has on the optimum solution found.
+# Now we will see the effect that varying an input parameter in the large tokamak input
+# file has on the optimum solution found.
#
-# Here, the minimum allowable value for net electric power, `p_plant_electric_net_required_mw`, has been changed from 400MW to 200MW, and PROCESS has found a different optimum solution.
+# Here, the minimum allowable value for net electric power,
+# `p_plant_electric_net_required_mw`, has been changed from 400MW to 200MW,
+# and PROCESS has found a different optimum solution.
#
-# We can plot the two MFILEs together, showing normalised values of the optimisation parameters at the solution points, as well as the objective function values.
+# We can plot the two MFILEs together, showing normalised values of the optimisation
+# parameters at the solution points, as well as the objective function values.
# %%
large_tokamak_varied_min_net_electric_mfile = (
@@ -157,14 +181,19 @@
# %% [markdown]
# To have lower net electric, `PROCESS` has found a solution where:
# - the fusion power has dropped, therefore the neutron wall load has gone down
-# - the toroidal field required has slightly dropped, therefore the case stress limits are lower as less current in the coils is needed
+# - the toroidal field required has slightly dropped, therefore the case stress limits
+# are lower as less current in the coils is needed
# %% [markdown]
# # Other solution comparison plots
#
-# There are some other ways that you can compare solutions in `PROCESS`. We will demonstrate these for the same two MFILEs as above, but you can add in more MFILEs if you want.
+# There are some other ways that you can compare solutions in `PROCESS`.
+# We will demonstrate these for the same two MFILEs as above, but you can add in
+# more MFILEs if you want.
#
-# Here we refer to the original large tokamak file as `Large tokamak 1`, and the new solution obtained by varying `p_plant_electric_net_required_mw` as `Large tokamak 2`.
+# Here we refer to the original large tokamak file as `Large tokamak 1`,
+# and the new solution obtained by varying `p_plant_electric_net_required_mw`
+# as `Large tokamak 2`.
# %% [markdown]
# ## Plot one solution normalised to another
@@ -204,7 +233,8 @@
# %% [markdown]
# ## Solutions normalised by range
#
-# Use `nitvar` values instead; the solution optimisation parameters are normalised to the range of their upper and lower bounds.
+# Use `nitvar` values instead; the solution optimisation parameters are normalised
+# to the range of their upper and lower bounds.
# %%
fig6, df6 = plot_mfile_solutions(
diff --git a/examples/scan.ex.py b/examples/scan.ex.py
index 05c8829292..267a1d6f63 100644
--- a/examples/scan.ex.py
+++ b/examples/scan.ex.py
@@ -21,16 +21,21 @@
#
# ## Scan details
#
-# The input file is a scan-enabled version of the large tokamak `IN.DAT`, as found in the `tests` directory. The scan-relevant values are:
+# The input file is a scan-enabled version of the large tokamak `IN.DAT`,
+# as found in the `tests` directory. The scan-relevant values are:
# ```
-# nsweep = 17 * b_tf_inboard_max, maximum peak toroidal field (T) (constraint equation 25)
+# nsweep = 17 * b_tf_inboard_max, maximum peak toroidal field (T)
# isweep = 6
# sweep = 10.5, 10.4, 10.3, 10.2, 10.1, 10.0
# ```
#
-# - `nsweep`: integer denoting the variable to scan (see `scan_module` for options). Here `17` corresponds to `b_tf_inboard_max` being scanned
+# - `nsweep`:
+# integer denoting the variable to scan (see `scan_module` for options).
+# Here `17` corresponds to `b_tf_inboard_max` being scanned
# - `isweep`: the number of scan points to run
-# - `sweep`: array of values for the scanned variable to take; one for each run. Should be of length `isweep`
+# - `sweep`:
+# array of values for the scanned variable to take; one for each run.
+# Should be of length `isweep`
# %% slideshow={"slide_type": "subslide"}
from process.core.repository import get_process_root
diff --git a/examples/single_model_evaluation.ex.py b/examples/single_model_evaluation.ex.py
index 9e08629c2b..873ed41ba4 100644
--- a/examples/single_model_evaluation.ex.py
+++ b/examples/single_model_evaluation.ex.py
@@ -16,7 +16,10 @@
# %% [markdown]
# # Evaluating a single PROCESS model
-# When understanding or investigating an individual model within Process, it can be useful to run the model in isolation and plot some responses. This is done here to investigate the effect of tungsten impurity concentration on radiated power and power incident on the divertor.
+# When understanding or investigating an individual model within Process,
+# it can be useful to run the model in isolation and plot some responses.
+# This is done here to investigate the effect of tungsten impurity concentration
+# on radiated power and power incident on the divertor.
# %%
import matplotlib.pyplot as plt
@@ -33,7 +36,10 @@
print(f"p_plasma_separatrix_mw = {PhysicsData.p_plasma_separatrix_mw}")
# %% [markdown]
-# In order to initialise all variables in Process with their values at a given point (design parameter vector), run an evaluation input file (one with no optimisation) to initialise values in all models. The "large tokamak" regression test solution is used here.
+# In order to initialise all variables in Process with their values at a given point
+# (design parameter vector), run an evaluation input file (one with no optimisation)
+# to initialise values in all models.
+# The "large tokamak" regression test solution is used here.
# %%
from process.core.repository import get_process_root
@@ -49,7 +55,8 @@
# Print initial values of interest
def print_values():
print(
- f"W frac = {single_run.data.impurity_radiation.f_nd_impurity_electron_array[13]:.3e}"
+ "W frac = "
+ f"{single_run.data.impurity_radiation.f_nd_impurity_electron_array[13]:.3e}"
)
print(f"p_plasma_rad_mw = {single_run.data.physics.p_plasma_rad_mw:.3e}")
print(
@@ -60,7 +67,8 @@ def print_values():
print_values()
# %% [markdown]
-# Now try increasing the tungsten impurity fraction to see if there's a change in the divertor power.
+# Now try increasing the tungsten impurity fraction to see if there's a change in
+# the divertor power.
# %%
single_run.data.impurity_radiation.f_nd_impurity_electron_array[13] = 5.0e-5
@@ -68,10 +76,12 @@ def print_values():
print_values()
# %% [markdown]
-# With a higher W impurity fraction, the radiated power has increased and the power incident on the divertor has decreased.
+# With a higher W impurity fraction, the radiated power has increased and
+# the power incident on the divertor has decreased.
#
# ## Parameter study of W impurity
-# Now investigate effect of varying W impurity on impurity radiation power, divertor power and constraint 15 (L-H threshold constraint).
+# Now investigate effect of varying W impurity on impurity radiation power,
+# divertor power and constraint 15 (L-H threshold constraint).
# %%
from process.core.solver.constraints import ConstraintManager
@@ -142,4 +152,5 @@ def run_impurities(w_imp_fracs):
# %% [markdown]
# The constraint becomes violated for W fraction values $> 6\times10^{-5}$.
#
-# This can easily be modified to investigate behaviour of any model in Process in isolation, without running other models or optimising.
+# This can easily be modified to investigate behaviour of
+# any model in Process in isolation, without running other models or optimising.
diff --git a/examples/vary_run_example.ex.py b/examples/vary_run_example.ex.py
index 2bd597d7f4..3bb663421c 100644
--- a/examples/vary_run_example.ex.py
+++ b/examples/vary_run_example.ex.py
@@ -23,29 +23,46 @@
# %% [markdown]
#
-# NOTE We run the examples in a temporary directory so all the inputs are copied there and the outputs contained there before the directory is removed when the example has finished running. This keeps the examples directory tidy and does not permanently modify any data files. The use of temporary directories is not needed for regular use of PROCESS.
+# NOTE We run the examples in a temporary directory so all the inputs are copied
+# there and the outputs contained there before the directory is removed when the example
+# has finished running.
+# This keeps the examples directory tidy and does not permanently modify any data files.
+# The use of temporary directories is not needed for regular use of PROCESS.
#
# %% [markdown]
-# `VaryRun` is a tool which takes an input file that does not converge and varies the initial values of the
-# iteration variables, within a tolerance, to find an initial point that converges, and creates
-# a new input file using these values.
+# `VaryRun` is a tool which takes an input file that does not converge and varies the
+# initial values of the iteration variables, within a tolerance,
+# to find an initial point that converges,
+# and creates a new input file using these values.
#
-# `VaryRun` requires a `.conf` file which specifies certain parameters needed for `VaryRun`.
-# In this file, you specify the original input file, the maximum number of iterations to be performed, and a factor within which the iteration variables are changed.
+# `VaryRun` requires a `.conf` file which specifies certain parameters needed for
+# `VaryRun`.
+# In this file, you specify the original input file,
+# the maximum number of iterations to be performed,
+# and a factor within which the iteration variables are changed.
#
-# If `VaryRun` is able to find a new initial point within the maximum number of iterations, you can find this file in the same directory as your initial input file. This new file will now converge when you run `PROCESS`.
+# If `VaryRun` is able to find a new initial point within the maximum number of
+# iterations,
+# you can find this file in the same directory as your initial input file.
+# This new file will now converge when you run `PROCESS`.
# `VaryRun` will produce new, numbered sets of files for each iteration it performs.
# %% [markdown]
# # VaryRun setup
#
-# VaryRun requires a `.conf` file in order to run. An example `.conf` file is displayed below.
+# VaryRun requires a `.conf` file in order to run. An example `.conf` file is
+# displayed below.
#
-# - `WDIR` specifies the path to the working directory where `PROCESS` is being run, here is is `.` to run in the directory of the `.conf` file, which is in `examples/data`
+# - `WDIR` specifies the path to the working directory where `PROCESS` is being run,
+# here is is `.` to run in the directory of the `.conf` file,
+# which is in `examples/data`
# - `ORIGINAL_IN_DAT` is providing the name of the original input file
# - `NITER` is specifying the maximum number of iterations to perform
-# - `SEED` is specifying a random number generator. Here it is set to 5 so the results of running `VaryRun` on the original input file will always be the same
-# - `FACTOR` is specifying a factor within which the iteration variables will change. Here it is set to 1.5, so this means the iteration variables can be varied within 50% of their initial values in the original input file
+# - `SEED` is specifying a random number generator. Here it is set to 5 so the results of
+# running `VaryRun` on the original input file will always be the same
+# - `FACTOR` is specifying a factor within which the iteration variables will change.
+# Here it is set to 1.5, so this means the iteration variables can be varied within
+# 50% of their initial values in the original input file
# %% [markdown]
# ```ini
@@ -71,7 +88,10 @@
# %% [markdown]
# ## Run `VaryRun`
#
-# Run `PROCESS` on an input file using the `VaryRun` class. The initial input file, `large_tokamak_varyrun_IN.DAT` does not converge. `VaryRun` will vary the initial values of the iteration variables to find an initial point that converges, and will create a new input file with these new values.
+# Run `PROCESS` on an input file using the `VaryRun` class. The initial input file,
+# `large_tokamak_varyrun_IN.DAT` does not converge. `VaryRun` will vary the
+# initial values of the iteration variables to find an initial point that converges,
+# and will create a new input file with these new values.
# %%
# %load_ext autoreload
@@ -131,7 +151,8 @@
# %%
import pandas as pd
-# Use pandas to display the values of the iteration variables before and after running VaryRun
+# Use pandas to display the values of the iteration variables before and after running
+# VaryRun
df = pd.DataFrame({
"Iteration variable names": iteration_variable_names,
"Original values": original_iteration_variable_values,
diff --git a/process/core/coolprop_interface.py b/process/core/coolprop_interface.py
index 4c78620b9b..ea431a1571 100644
--- a/process/core/coolprop_interface.py
+++ b/process/core/coolprop_interface.py
@@ -69,13 +69,13 @@ def of(
fluid_name :
the name of the fluid to calculate properties for, e.g. 'Helium' or 'Water'.
temperature :
- the current temperature [K] of the fluid to calculate the properties with respect to.
+ the current temperature [K] of the fluid to calculate the properties.
pressure :
- the current pressure [Pa] of the fluid to calculate the properties with respect to.
+ the current pressure [Pa] of the fluid to calculate the properties.
entropy :
- the current entropy [J/kg/K] of the fluid to calculate the properties with respect to.
+ the current entropy [J/kg/K] of the fluid to calculate the properties.
vapor_quality :
- the molar vapor quality [mol/mol] of the fluid to calculate the properties with respect to.
+ the molar vapor quality [mol/mol] of the fluid to calculate the properties.
`[0, 1]`, where `0` is a saturated liquid and `1` is a saturated vapor.
"""
coolprop_inputs = []
diff --git a/process/core/init.py b/process/core/init.py
index c94d08fac9..04c0ed7f20 100644
--- a/process/core/init.py
+++ b/process/core/init.py
@@ -438,13 +438,19 @@ def check_process(inputs, data): # noqa: ARG001
"Density pedestal is lower than separatrix density",
**(
{
- "nd_plasma_pedestal_electron": data.physics.nd_plasma_pedestal_electron,
- "nd_plasma_separatrix_electron": data.physics.nd_plasma_separatrix_electron,
+ k: getattr(data.physics, k)
+ for k in (
+ "nd_plasma_pedestal_electron",
+ "nd_plasma_separatrix_electron",
+ )
}
if pedestal_type == DensityProfilePedestalType.USER_INPUT
else {
- "f_nd_plasma_pedestal_greenwald": data.physics.f_nd_plasma_pedestal_greenwald,
- "f_nd_plasma_separatrix_greenwald": data.physics.f_nd_plasma_separatrix_greenwald,
+ k: getattr(data.physics, k)
+ for k in (
+ "f_nd_plasma_pedestal_greenwald",
+ "f_nd_plasma_separatrix_greenwald",
+ )
}
),
)
diff --git a/process/core/input.py b/process/core/input.py
index ca17ab6566..946132889e 100644
--- a/process/core/input.py
+++ b/process/core/input.py
@@ -66,8 +66,8 @@ class InputVariable:
Callable[[str, ValidInputTypes, int | None, InputVariable], ValidInputTypes]
| None
) = None
- """A function that takes the input variable: name, value, array index, and config (this dataclass)
- as input and returns a cleaned version of the input value. May raise
+ """A function that takes the input variable: name, value, array index, and config
+ (this dataclass) as input and returns a cleaned version of the input value. May raise
a ProcessValidationError.
NOTE: The value passed in has already been cleaned in the default way and has
@@ -77,19 +77,22 @@ class InputVariable:
Callable[[str, ValidInputTypes, int | None, InputVariable, DataStructure], None]
| None
) = None
- """A function that takes the input variable: name, value, array index, config (this dataclass), and
- the data structure object as input and performs some additional action in addition to the default
+ """A function that takes the input variable: name, value, array index, config
+ (this dataclass), and the data structure object as input and performs some additional
+ action in addition to the default
actions prescribed by the variables config. May raise a ProcessValidationError.
NOTE: The value passed in has already been cleaned in the default
way and has been cast to the specified `type`.
- NOTE: the input name is the cleaned name as in the input file NOT the `target_variable`.
+ NOTE:
+ the input name is the cleaned name as in the input file NOT the `target_variable`.
"""
target_name: str | None = None
"""Indicates the parsed variable name is different to its target on the `module`."""
set_variable: bool = True
- """Do not attempt to set the variable on the module. Instead only do any `additional_actions`."""
+ """Do not attempt to set the variable on the module.
+ Instead only do any `additional_actions`."""
def __post_init__(self):
if self.type not in DataTypes:
@@ -104,7 +107,8 @@ def __post_init__(self):
if not self.set_variable and self.additional_actions is None:
logger.warning(
- "Not setting variable or performing an additional action. Why are you parsing this variable?",
+ "Not setting variable or performing an additional action. "
+ "Why are you parsing this variable?",
stacklevel=2,
)
@@ -708,9 +712,12 @@ def bounds(self) -> tuple[NumberType | None, NumberType | None]:
rt <= 1e-6
or logger.warning(
(
- "the relationship between REBCO layer thickness and current density is not linear."
- "REBCO layer thicknesses > 1um should be considered an aggressive extrapolation of"
- "current HTS technology and any results must be considered speculative."
+ "the relationship between REBCO layer thickness "
+ "and current density is not linear."
+ "REBCO layer thicknesses > 1um should be considered "
+ "an aggressive extrapolation of"
+ "current HTS technology and any results "
+ "must be considered speculative."
),
stacklevel=1,
)
@@ -1300,7 +1307,8 @@ def parse_input_file(data_structure_obj: DataStructure):
data_structure_obj,
)
- # add the variable to a dictionary indexed by the variable name (in the input file)
+ # add the variable to a dictionary indexed by the variable name
+ # (in the input file)
variables[variable_name] = {
"value": clean_variable_value,
"index": array_index_clean,
@@ -1354,7 +1362,10 @@ def validate_variable(
try:
clean_value = config.type(value)
except ValueError as e:
- error_msg = f"Cannot cast variable name '{name}' at line {line_number} to a {config.type} (value = {value})"
+ error_msg = (
+ f"Cannot cast variable name '{name}' at line {line_number}"
+ f" to a {config.type} (value = {value})"
+ )
raise ProcessValidationError(error_msg) from e
if (
@@ -1368,7 +1379,10 @@ def validate_variable(
raise ProcessValidationError(error_msg)
if config.choices is not None and clean_value not in config.choices:
- error_msg = f"Variable '{name}' at line {line_number} is not one of {config.choices} (value = {value})"
+ error_msg = (
+ f"Variable '{name}' at line {line_number} is not one of {config.choices}"
+ f" (value = {value})"
+ )
raise ProcessValidationError(error_msg)
if config.additional_validation is not None:
@@ -1407,8 +1421,10 @@ def set_scalar_variable(name: str, value: ValidInputTypes, config: InputVariable
def set_array_variable(name: str, value: str, array_index: int, config: InputVariable):
"""Set an array variable in the `config.module`.
- The way PROCESS input files are structured, each element of the array is provided on one line
- so this function just needs to set the `value` at `array_index` (-1) because of Fortran-based indexing.
+ The way PROCESS input files are structured, each element of the array is provided on
+ one line
+ so this function just needs to set the `value` at `array_index` (-1)
+ because of Fortran-based indexing.
Parameters
----------
diff --git a/process/core/io/data_structure_dicts.py b/process/core/io/data_structure_dicts.py
index d74f28b03b..04da862a7d 100644
--- a/process/core/io/data_structure_dicts.py
+++ b/process/core/io/data_structure_dicts.py
@@ -129,9 +129,11 @@ def dict_ixc_bounds():
# process run.
@cache
def get_dicts():
- """Constructs the dictionaries which contain information about every PROCESS variable.
+ """Constructs the dictionaries which contain information about every
+ PROCESS variable.
- WARNING: this function must be used carefully because it re-initialises the PROCESS state
+ WARNING: this function must be used carefully because it
+ re-initialises the PROCESS state
"""
dict_objects = []
# Different dict objects, e.g. variable descriptions
@@ -181,7 +183,8 @@ def get_dicts():
# for each variable in the file, get the initial value
# (either is None, or value initialised in init_variables fn)
# set default to be None if variable is not being initialised eg if you
- # just have `example_double: float` instead of `example_double: float = None`
+ # just have `example_double: float`
+ # instead of `example_double: float = None`
initial_value = getattr(object_containing_initial_values, node.target.id)
# JSON doesn't like np arrays
if type(initial_value) is np.ndarray:
@@ -204,9 +207,10 @@ def get_dicts():
else:
raise TypeError(
f"The type annotation of variable {node.target.id} is "
- f"{node.annotation.value.id}[{node.annotation.slice.id}], and "
- "this is not recognised. Please change your type annotation for "
- "this variable. PROCESS recognises the following type annotations: "
+ f"{node.annotation.value.id}[{node.annotation.slice.id}],"
+ " and this is not recognised. "
+ "Please change your type annotation for this variable. "
+ "PROCESS recognises the following type annotations: "
"list[float], list[int], list[str], list[bool]."
)
elif node.annotation.id == "float":
@@ -220,8 +224,9 @@ def get_dicts():
else:
raise TypeError(
f"The type annotation of variable {node.target.id} is "
- f"{node.annotation.id}, and this is not recognised. Please change your "
- "type annotation for this variable. PROCESS recognises the following "
+ f"{node.annotation.id}, and this is not recognised. "
+ "Please change your type annotation for this variable. "
+ "PROCESS recognises the following "
"type annotations: float, int, str, bool."
)
diff --git a/process/core/io/in_dat/base.py b/process/core/io/in_dat/base.py
index aebcfaec64..8a581473b1 100644
--- a/process/core/io/in_dat/base.py
+++ b/process/core/io/in_dat/base.py
@@ -237,10 +237,12 @@ def get_constraint_equations(data):
if constraint is None:
raise ProcessValidationError(
- f"Constraint equation {constraint_number} requested but has not been registered"
+ f"Constraint equation {constraint_number} requested "
+ "but has not been registered"
)
- # TODO: we should store a short description of each constraint that we can use here.
+ # TODO: we should store a short description of each constraint
+ # that we can use here.
# Currently, no such information exists.
constraints[constraint_number] = ""
@@ -857,7 +859,8 @@ def variable_constraint_type_check(item_number, var_type):
# rounded float number with warning
print(
- f"Value {item_number} for {var_type} not an integer. Value rounded to {int(item_number)}."
+ f"Value {item_number} for {var_type} not an integer. "
+ f"Value rounded to {int(item_number)}."
" Check!"
)
return int(item_number)
@@ -876,7 +879,8 @@ def variable_constraint_type_check(item_number, var_type):
# If not an integer warn of rounding and return rounded integer
print(
- f"Value {item_number} for {var_type} not an integer. Value rounded to {int(item_number)}. Check!"
+ f"Value {item_number} for {var_type} not an integer. "
+ f"Value rounded to {int(item_number)}. Check!"
)
return int(item_number)
@@ -940,7 +944,8 @@ def variable_bound_check(bound_number, bound_type):
return int(bound_number), bound_type
bound_number = int(bound_number)
print(
- f"Bound number {bound_number} not an integer. Value rounded to {int(bound_number)}"
+ f"Bound number {bound_number} not an integer. "
+ f"Value rounded to {int(bound_number)}"
)
return bound_number, bound_type
@@ -970,7 +975,8 @@ def __init__(self, name, value, v_type, comment):
self.comment = comment
def __eq__(self, value):
- # intentionally missing .comment, this is not necessary for the variables to be equal
+ # intentionally missing .comment,
+ # this is not necessary for the variables to be equal
return (
self.name == value.name
and self.value == value.value
@@ -982,7 +988,8 @@ def __hash__(self):
def __repr__(self):
return (
- f"{type(self).__name__}(name={self.name!r}, value={self.value!r}, v_type={self.v_type!r}, "
+ f"{type(self).__name__}(name={self.name!r}, value={self.value!r}, "
+ f"v_type={self.v_type!r}, "
f"comment={self.comment!r})"
)
diff --git a/process/core/io/in_dat/create.py b/process/core/io/in_dat/create.py
index 0e7354adaa..8e43ad1f77 100644
--- a/process/core/io/in_dat/create.py
+++ b/process/core/io/in_dat/create.py
@@ -12,7 +12,8 @@
def feasible_point(filename, position: int):
- """Function to check for feasible solution before creating new IN.DAT, or to determine the first or last feasible point in a scan
+ """Function to check for feasible solution before creating new IN.DAT,
+ or to determine the first or last feasible point in a scan
Parameters
----------
diff --git a/process/core/io/obsolete_vars.py b/process/core/io/obsolete_vars.py
index bce1b7c86d..82aa8ed33f 100644
--- a/process/core/io/obsolete_vars.py
+++ b/process/core/io/obsolete_vars.py
@@ -1,4 +1,5 @@
-"""Dict of obsolete vars and their new names for the input validator, and dict of help messages for certain obsolete vars.
+"""Dict of obsolete vars and their new names for the input validator,
+and dict of help messages for certain obsolete vars.
This is used by the input_validator module to find any obsolete variables in the
input file (which have since been renamed in the current version of the source).
@@ -475,11 +476,19 @@
OBS_VARS_HELP = {
"iculdl": "(use IDENSL=3 for equivalent model to ICULDL=0). ",
- "dz_blkt_upper": "WARNING. BLNKTTH is now always calculated rather than input - please remove it from the input file. ",
- "iprofile": "Use i_beta_norm_max, i_alphaj and i_ind_plasma_internal_norm instead. See docs for setup. ",
+ "dz_blkt_upper": (
+ "WARNING. "
+ "BLNKTTH is now always calculated rather than input - "
+ "please remove it from the input file. "
+ ),
+ "iprofile": (
+ "Use i_beta_norm_max, i_alphaj and i_ind_plasma_internal_norm instead. "
+ "See docs for setup. "
+ ),
"fl_h_threshold": (
"fl_h_threshold has been replaced by f_h_mode_margin/f_l_mode_margin"
- " please check the docstring for constraint 15/22 to find the appropriate variable"
+ " please check the docstring for constraint 15/22 to "
+ "find the appropriate variable"
),
}
@@ -506,7 +515,10 @@
"mach0",
"neratio",
]
-kallenbach_message = "The Kallenbach model is currently not included in PROCESS. See issue #1886 for more information on the use of the Kallenbach model. "
+kallenbach_message = (
+ "The Kallenbach model is currently not included in PROCESS. "
+ "See issue #1886 for more information on the use of the Kallenbach model. "
+)
OBS_VARS.update(dict.fromkeys(kallenbach_list, None))
OBS_VARS_HELP.update(dict.fromkeys(kallenbach_list, kallenbach_message))
diff --git a/process/core/io/plot/cli.py b/process/core/io/plot/cli.py
index 9820a6b967..2179a794a4 100644
--- a/process/core/io/plot/cli.py
+++ b/process/core/io/plot/cli.py
@@ -134,7 +134,8 @@ def sankey(mfile, format_):
"y_axis_percent2",
is_flag=True,
help=(
- "Used to set the y axis ticks to percentages in place of absolute \nvalues. For the twinned axis if present."
+ "Used to set the y axis ticks to percentages in place of absolute \nvalues. "
+ "For the twinned axis if present."
),
)
@click.option(
@@ -143,7 +144,8 @@ def sankey(mfile, format_):
callback=split_callback,
default="",
help=(
- "Used to set the y value corresponding to 100 percent when \nconverting from absolute to percent values."
+ "Used to set the y value corresponding to 100 percent when \n"
+ "converting from absolute to percent values."
),
)
@click.option(
@@ -152,7 +154,8 @@ def sankey(mfile, format_):
callback=split_callback,
default="",
help=(
- "Used to set the y value corresponding to 100 percent when \nconverting from absolute to percent values."
+ "Used to set the y value corresponding to 100 percent when \n"
+ "converting from absolute to percent values."
"For the twinned axis if present."
),
)
@@ -321,7 +324,8 @@ def plot_tf_stress(plot_selec, save_format, axis_font_size, term_output, input_f
"-o",
"--output-format",
help=(
- "Output file format\npdf: pdf output (default)\npng: png output\nnone: no output file written"
+ "Output file format\npdf: pdf output (default)\npng: png output\n"
+ "none: no output file written"
),
default="pdf",
type=click.Choice(["pdf", "png", "none"]),
diff --git a/process/core/io/plot/costs/costs_bar.py b/process/core/io/plot/costs/costs_bar.py
index 3ca764dbf5..3408811d82 100644
--- a/process/core/io/plot/costs/costs_bar.py
+++ b/process/core/io/plot/costs/costs_bar.py
@@ -96,7 +96,8 @@ def cost_comp_1990(
# Explain why moneyint is missing
if "moneyint" not in item.data:
print(
- "Interest during construction (moneyint) is only calculated for ireactor = 1"
+ "Interest during construction (moneyint) "
+ "is only calculated for ireactor = 1"
)
if inflate: # Inflate costs using value parsed if specified
diff --git a/process/core/io/plot/sankey.py b/process/core/io/plot/sankey.py
index 026b22f4b3..4f2d68b46a 100644
--- a/process/core/io/plot/sankey.py
+++ b/process/core/io/plot/sankey.py
@@ -134,8 +134,11 @@ def power_balance_sankey(m_file: Path):
30, # 44: TF nuclear heat to secondary heat
15, # 45: HCD electric losses to secondary heat
24, # 46: Coolant pumps electric to secondary heat
- 6, # 47: FW pump to primary heat, Should only show if FW and Bkt pumps are separate
- 7, # 48: Blkt pump to primary heat, Should only show if FW and Blkt pumps are separate
+ # 47: FW pump to primary heat, Should only show if FW and Bkt pumps are separate
+ 6,
+ # 48: Blkt pump to primary heat,
+ # Should only show if FW and Blkt pumps are separate
+ 7,
2, # 49 Should show in beams are present
2, # 50: Should show in beams are present
4, # 51 Neutrons to CP shield, should only show if CP shield is present
@@ -199,8 +202,11 @@ def power_balance_sankey(m_file: Path):
29, # 44: TF nuclear heat to secondary heat
29, # 45: HCD electric losses to secondary heat
29, # 46: Coolant pumps electric to secondary heat
- 9, # 47: FW pump to primary heat, Should only show if FW and Bkt pumps are separate
- 9, # 48: Blkt pump to primary heat, Should only show if FW and Blkt pumps are separate
+ # 47: FW pump to primary heat, Should only show if FW and Bkt pumps are separate
+ 9,
+ # 48: Blkt pump to primary heat,
+ # Should only show if FW and Blkt pumps are separate
+ 9,
6, # 49 Should show in beams are present
6, # 50: Should show in beams are present
28, # 51 Neutrons to CP shield, should only show if CP shield is present
@@ -561,7 +567,7 @@ def minimise_dxdy(x_opt):
def plot_sankey(
mfilename=Path("MFILE.DAT"), format_: str = "pdf"
): # Plot simplified power flow Sankey Diagram
- # ------------------------------- Pulling values from the MFILE -------------------------------
+ # Pulling values from the MFILE
mfilename = Path(mfilename)
m_file = MFile(mfilename)
@@ -600,7 +606,8 @@ def plot_sankey(
"vachtmw", # vacuum pump power (MW)
"p_pf_electric_supplies_mw", # Total mean wall plug power for PFC & CS (MW)
"p_hcd_electric_total_mw", # injector wall plug power (MW)
- "p_coolant_pump_elec_total_mw", # heat transport system electrical pump power (MW)
+ # heat transport system electrical pump power (MW)
+ "p_coolant_pump_elec_total_mw",
"p_cp_coolant_pump_elec", # pumping power
]
(
@@ -691,7 +698,7 @@ def plot_sankey(
+ p_cp_coolant_pump_elec_mw
)
- # -------------------------------- Visual Settings ------------------------------------
+ # Visual Settings
plt.rcParams.update({"font.size": 9}) # Setting font size to 9
fig = plt.figure()
@@ -702,7 +709,7 @@ def plot_sankey(
trunk = 0.7
len1 = 0.5
len2 = 0.8
- # --------------------------------------- PLASMA - 0 --------------------------------------
+ # --- PLASMA - 0 --
# Fusion power, Injected power + ohmic power, - total plasma power
plasma = [
@@ -722,7 +729,7 @@ def plot_sankey(
labels=["Fusion Power", None, "Plasma"],
)
- # --------------------------------- ENERGY DEPOSITION - 1 ---------------------------------
+ # ------------ ENERGY DEPOSITION - 1 ------------
# Plasma power, - divertor deposited power, - blanket deposited power
deposition = [totalplasma, -totalblktetc - totaldivetc - totalcpetc]
@@ -742,7 +749,7 @@ def plot_sankey(
labels=[None, "Blanket/etc."],
)
- # -------------------------------------- BLANKET - 2 --------------------------------------
+ # -- BLANKET - 2 --
# Blanket deposited power, blanket energy multiplication, - primary heat
blanketsetc = [
@@ -767,7 +774,7 @@ def plot_sankey(
labels=[None, "Energy Mult.", "Primary Heat"],
)
- # ------------------------------------- HEAT LOSS - 3 -------------------------------------
+ # - HEAT LOSS - 3 -
# Primary heat, -Gross electric power, -difference (loss)
primary = [
@@ -789,7 +796,7 @@ def plot_sankey(
labels=[None, "Gross electric", "Losses"],
)
- # ------------------------------------ ELECTRICITY - 4 ------------------------------------
+ # ELECTRICITY - 4
# If net electric is +ve or -ve changes the flow organisation
if p_plant_electric_net_mw >= 0: # net electric is +ve
@@ -825,7 +832,7 @@ def plot_sankey(
labels=["Net elec.", None, "Recirc. Power"],
)
- # -------------------------------- RECIRCULATING POWER - 5 --------------------------------
+ # ----------- RECIRCULATING POWER - 5 -----------
# Recirculated power, -Core Systems, -Heating System
recirc = [
@@ -853,7 +860,7 @@ def plot_sankey(
labels=[None, "Core Systems", "Heating System"],
)
- # --------------------------------------- LOSSES - 6 --------------------------------------
+ # --- LOSSES - 6 --
# HCD: Heating system, -Plasma heating, -losses
hcd = [
@@ -876,7 +883,7 @@ def plot_sankey(
diagrams = sankey.finish()
fig.tight_layout()
- # --------------------------------------- Label Positioning ---------------------------------------
+ # --- Label Positioning ---
# Manipulating the positioning of the branch labels
# -ve to left and down; +ve to right and up
diff --git a/process/core/io/plot/scans.py b/process/core/io/plot/scans.py
index 08010849b7..53fc9d9ea0 100644
--- a/process/core/io/plot/scans.py
+++ b/process/core/io/plot/scans.py
@@ -93,7 +93,8 @@ def plot_scan(
13: "boundu(10)",
14: "f_j_tf_wp_critical_max",
16: "rmajor",
- 17: "b_tf_inboard_peak_symmetric", # b_tf_inboard_max the maximum T field upper limit is the scan variable
+ # b_tf_inboard_max the maximum T field upper limit is the scan variable
+ 17: "b_tf_inboard_peak_symmetric",
18: "eta_cd_norm_hcd_primary_max",
19: "boundl(16)",
20: "cnstv.t_burn_min",
@@ -133,7 +134,8 @@ def plot_scan(
54: "b_crit_upper_nbti",
55: "dr_shld_inboard",
56: "p_cryo_plant_electric_max_mw",
- 57: "b_plasma_toroidal_on_axis", # Genuinly b_plasma_toroidal_on_axis lower bound
+ # Genuinly b_plasma_toroidal_on_axis lower bound
+ 57: "b_plasma_toroidal_on_axis",
58: "dr_fw_plasma_gap_inboard",
59: "dr_fw_plasma_gap_outboard",
60: "sig_tf_wp_max",
@@ -248,7 +250,6 @@ def _format_lists(inp, output_names):
# -------------
# Case of a set of 1D scans
- # ----------------------------------------------------------------------------------------------
if not is_2D_scan:
# Loop over the MFILEs
output_arrays = {}
@@ -289,7 +290,8 @@ def _format_lists(inp, output_names):
else:
failed_value = m_file.data[scan_var_name].get_scan(ii + 1)
print(
- f"Warning : Non-convergent scan point : {scan_var_name} = {failed_value}\n"
+ "Warning : Non-convergent scan point : "
+ f"{scan_var_name} = {failed_value}\n"
"Warning : This point will not be shown."
)
@@ -351,7 +353,8 @@ def _format_lists(inp, output_names):
print()
if len(output_names2) > 0:
print(
- f"Y2-Axis\n {output_name2} : {output_arrays2[input_file][output_name2]}\n"
+ f"Y2-Axis\n {output_name2} : "
+ f"{output_arrays2[input_file][output_name2]}\n"
)
# Plot section
# -----------
@@ -689,8 +692,8 @@ def _format_lists(inp, output_names):
plt.rc("xtick", labelsize=axis_tick_size)
plt.rc("ytick", labelsize=axis_tick_size)
plt.title(
- f"{meta[output_name].latex if output_name in meta else {output_name}} vs "
- f"{meta[scan_var_name].latex if scan_var_name in meta else {scan_var_name}}",
+ f"{meta[output_name].latex if output_name in meta else {output_name}} vs " # noqa: E501
+ f"{meta[scan_var_name].latex if scan_var_name in meta else {scan_var_name}}", # noqa: E501
fontsize=axis_font_size,
)
plt.tight_layout()
@@ -700,11 +703,11 @@ def _format_lists(inp, output_names):
# Output file naming
if output_name == "plasma_current_MA":
- extra_str = f"plasma_current{f'_vs_{output_name2}' if len(output_names2) > 0 else ''}"
+ extra_str = f"plasma_current{f'_vs_{output_name2}' if len(output_names2) > 0 else ''}" # noqa: E501
elif stack_plots and output_names[-1] == output_name:
- extra_str = f"{output_name}{f'_vs_{output_name2}' if len(output_names2) > 0 else '_vs_'.join(output_names)}"
+ extra_str = f"{output_name}{f'_vs_{output_name2}' if len(output_names2) > 0 else '_vs_'.join(output_names)}" # noqa: E501
else:
- extra_str = f"{output_name}{f'_vs_{output_name2}' if len(output_names2) > 0 else ''}"
+ extra_str = f"{output_name}{f'_vs_{output_name2}' if len(output_names2) > 0 else ''}" # noqa: E501
if (not stack_plots) or (stack_plots and output_names[-1] == output_name):
plt.savefig(
@@ -717,7 +720,6 @@ def _format_lists(inp, output_names):
# ------------
# In case of a 2D scan
- # ----------------------------------------------------------------------------------------------
else:
# Opening the MFILE.DAT
m_file = MFile(filename=input_files[0])
@@ -727,7 +729,8 @@ def _format_lists(inp, output_names):
n_scan_2 = int(m_file.data["isweep_2"].get_scan(-1))
# Selecting the converged runs only
contour_conv_ij = [] # List of non-converged scan point numbers
- conv_ij = [] # 2D array of converged scan point numbers (sweep = rows, sweep_2 = columns)
+ # 2D array of converged scan point numbers (sweep = rows, sweep_2 = columns)
+ conv_ij = []
ii_jj = 0
for ii in range(n_scan_1):
conv_ij.append([])
@@ -743,7 +746,8 @@ def _format_lists(inp, output_names):
failed_value_1 = m_file.data[scan_var_name].get_scan(ii_jj)
failed_value_2 = m_file.data[scan_2_var_name].get_scan(ii_jj)
print(
- f"Warning : Non-convergent scan point : ({scan_var_name},{scan_2_var_name}) "
+ "Warning : Non-convergent scan point : "
+ f"({scan_var_name},{scan_2_var_name}) "
f"= ({failed_value_1},{failed_value_2})\n"
"Warning : This point will not be shown."
)
@@ -859,7 +863,7 @@ def _format_lists(inp, output_names):
plt.tight_layout()
plt.savefig(
outputdir
- / f"scan_{output_name}_vs_{scan_var_name}_{scan_2_var_name}.{save_format}"
+ / f"scan_{output_name}_vs_{scan_var_name}_{scan_2_var_name}.{save_format}" # noqa: E501
)
plt.grid(True)
plt.show()
@@ -885,7 +889,7 @@ def _format_lists(inp, output_names):
output_array[jj] = m_file.data[output_name].get_scan(conv_j[jj])
# Label formating
- labl = f"{meta[scan_var_name].latex if scan_var_name in meta else {scan_var_name}} = {scan_1_var_array[0]}"
+ labl = f"{meta[scan_var_name].latex if scan_var_name in meta else {scan_var_name}} = {scan_1_var_array[0]}" # noqa: E501
# Plot the graph
ax.plot(scan_2_var_array, output_array, "--o", label=labl)
@@ -955,7 +959,7 @@ def _format_lists(inp, output_names):
plt.tight_layout()
plt.savefig(
outputdir
- / f"scan_{output_name}_vs_{scan_var_name}_{scan_2_var_name}.{save_format}"
+ / f"scan_{output_name}_vs_{scan_var_name}_{scan_2_var_name}.{save_format}" # noqa: E501
)
# Display plot (used in Jupyter notebooks)
diff --git a/process/core/io/plot/stress_tf.py b/process/core/io/plot/stress_tf.py
index cc0823ee0a..c0e6712b11 100644
--- a/process/core/io/plot/stress_tf.py
+++ b/process/core/io/plot/stress_tf.py
@@ -51,7 +51,7 @@ def plot_stress(
plot_sm_sig = ("sm_sig" in plot_selection) or ("all" in plot_selection)
# Step 1 : Data extraction
- # ----------------------------------------------------------------------------------------------
+
# Number of physical quantity value per coil layer
n_radial_array_layer = 0
diff --git a/process/core/io/vary_run/config.py b/process/core/io/vary_run/config.py
index 64dba84a74..3f8c3560e8 100644
--- a/process/core/io/vary_run/config.py
+++ b/process/core/io/vary_run/config.py
@@ -136,7 +136,8 @@ def __post_init__(self):
if not isinstance(self.or_in_dat, Path) or not self.or_in_dat.is_file():
raise FileNotFoundError(
- f"Error: {self.or_in_dat} does not exist! Create file or modify config file!",
+ f"Error: {self.or_in_dat} does not exist! "
+ "Create file or modify config file!",
)
def __iter__(self):
@@ -161,7 +162,8 @@ def __next__(self):
print(f"VaryRun iteration {self._current_iteration} did not converge.\n")
else:
print(
- f"PROCESS found a converged solution using VaryRun. The converging input file is {self._current_iteration}_IN.DAT\n"
+ "PROCESS found a converged solution using VaryRun. "
+ f"The converging input file is {self._current_iteration}_IN.DAT\n"
)
self._current_iteration += 1
@@ -245,9 +247,19 @@ def error_status2readme(self, mfile):
ifail = m_file.data["ifail"].get_scan(-1)
if ifail != 1:
- ifail_msg = f"PROCESS has been unable to find a converging input file within the chosen maximum number of iterations.\nYou could try increasing the maximum number of iterations (which is currently set to {self.niter}),\nchanging the factor within which the iteration variables are changed,\nor by changing the initial values of the iteration variables."
+ ifail_msg = (
+ "PROCESS has been unable to find a converging input file "
+ "within the chosen maximum number of iterations.\n"
+ "You could try increasing the maximum number of iterations "
+ f"(which is currently set to {self.niter}),\n"
+ "changing the factor within which the iteration variables are changed,\n"
+ "or by changing the initial values of the iteration variables."
+ )
else:
- ifail_msg = f"PROCESS found a converged solution using VaryRun. The converging input file is {self._current_iteration - 1}_IN.DAT"
+ ifail_msg = (
+ "PROCESS found a converged solution using VaryRun. "
+ f"The converging input file is {self._current_iteration - 1}_IN.DAT"
+ )
if self.comment:
with open(Path(self.wdir, "README.txt"), "a") as readme:
@@ -327,7 +339,8 @@ class RunProcessConfig(ProcessConfig):
no_allowed_unfeasible: int = 0
"""the number of allowed unfeasible points in a sweep"""
create_itervar_diff: bool = False
- """boolean to indicate the creation of a summary file of the iteration variable values at each stage"""
+ """boolean to indicate the creation of a summary file of the iteration variable
+ values at each stage"""
dictvar: dict[str, str] = field(default_factory=dict)
"""Dictionary mapping variable name to new value"""
del_var: list[str] = field(default_factory=list)
diff --git a/process/core/log.py b/process/core/log.py
index 891da1f94c..af8358b1b0 100644
--- a/process/core/log.py
+++ b/process/core/log.py
@@ -72,7 +72,7 @@ def show_errors(file_unit: int):
"""
warning_string = (
- "******************************************** Errors and Warnings *********************************************"
+ "******************************************** Errors and Warnings *********************************************" # noqa: E501
f"\n{logging_model_handler.render_warnings()}"
)
print(warning_string)
diff --git a/process/core/model.py b/process/core/model.py
index 3ddc7bd3ac..265df636e1 100644
--- a/process/core/model.py
+++ b/process/core/model.py
@@ -95,14 +95,14 @@ class Model(abc.ABC):
def run(self) -> None:
"""Run the model.
- The run method is responsible for 'running' the model, ensuring it updates the data
- structure with variables that subsequent models will require.
+ The run method is responsible for 'running' the model, ensuring it updates
+ the data structure with variables that subsequent models will require.
"""
@abc.abstractmethod
def output(self) -> None:
"""Output model data.
- This method will always be called after run method and should output the model data to the
- output files.
+ This method will always be called after run method and should output the model
+ data to the output files.
"""
diff --git a/process/core/output.py b/process/core/output.py
index 1368eaae7f..82c070b44b 100644
--- a/process/core/output.py
+++ b/process/core/output.py
@@ -19,8 +19,9 @@ def write(models, data, _outfile):
Fortran output unit identifier
"""
- # ensure we are capturing warnings that occur in the 'output' stage as these are warnings
- # that occur at our solution point. So we clear existing warnings
+ # ensure we are capturing warnings that occur in the 'output' stage
+ # as these are warnings that occur at our solution point.
+ # So we clear existing warnings
logging_model_handler.start_capturing()
logging_model_handler.clear_logs()
diff --git a/process/core/process_output.py b/process/core/process_output.py
index 0fa3dfb222..d0863bbc6e 100644
--- a/process/core/process_output.py
+++ b/process/core/process_output.py
@@ -68,7 +68,10 @@ def write(file, string: str):
elif file == constants.IOTTY:
print(string)
else:
- error_msg = f"Unknown file identifier {file}, it is not recognised as either an MFile, OUTFile, or terminal."
+ error_msg = (
+ f"Unknown file identifier {file}, "
+ "it is not recognised as either an MFile, OUTFile, or terminal."
+ )
raise ProcessValueError(error_msg)
@@ -208,7 +211,10 @@ def ovarre(file, descr: str, varnam: str, value, output_flag: str = ""):
# # The ITV flag overwrites the output_flag
# output_flag = "ITV"
- line = f"{description}{replacement_character} {varname}{replacement_character} {format_value} {output_flag}"
+ line = (
+ f"{description}{replacement_character} {varname}{replacement_character} "
+ f"{format_value} {output_flag}"
+ )
write(file, line)
if file != constants.MFILE:
ovarre(constants.MFILE, descr, varnam, value, output_flag)
diff --git a/process/core/scan.py b/process/core/scan.py
index dbbbca4e93..535eae7f36 100644
--- a/process/core/scan.py
+++ b/process/core/scan.py
@@ -429,7 +429,8 @@ def post_optimise(self, ifail: int):
process_output.write(
constants.NOUT,
- f"{string1} the optimisation parameters to {string2} the objective function: {objf_name}\n",
+ f"{string1} the optimisation parameters to {string2} "
+ f"the objective function: {objf_name}\n",
)
written_warning = False
@@ -459,7 +460,8 @@ def post_optimise(self, ifail: int):
constants.NOUT,
(
"Certain operating limits have been reached,"
- "\n as shown by the following optimisation parameters that are"
+ "\n as shown by the following optimisation parameters"
+ " that are"
"\n at or near to the edge of their prescribed range :\n"
),
)
@@ -614,13 +616,14 @@ def post_optimise(self, ifail: int):
# Inequalities not necessarily satisfied when evaluating
process_output.osubhd(
constants.NOUT,
- "Negative inequality constraint (normalised) residuals indicate a constraint is satisfied.",
+ "Negative inequality constraint (normalised) residuals "
+ "indicate a constraint is satisfied.",
)
if self.solver == "fsolve":
process_output.osubhd(
constants.NOUT,
- "This MFile was produced via an evaluation, not an optimisation, and so the constraints "
- "might be violated.",
+ "This MFile was produced via an evaluation, not an optimisation, "
+ "and so the constraints might be violated.",
)
for i in range(
@@ -724,7 +727,8 @@ def verror(ifail: int):
)
process_output.ocmmnt(
constants.NOUT,
- "The code may be stuck in a minimum in the residual space that is significantly above zero.",
+ "The code may be stuck in a minimum in the residual space that is "
+ "significantly above zero.",
)
process_output.oblnkl(constants.NOUT)
process_output.ocmmnt(
@@ -744,7 +748,8 @@ def verror(ifail: int):
)
process_output.ocmmnt(
constants.IOTTY,
- "The code may be stuck in a minimum in the residual space that is significantly above zero.",
+ "The code may be stuck in a minimum in the residual space that is "
+ "significantly above zero.",
)
process_output.oblnkl(constants.NOUT)
process_output.oblnkl(constants.IOTTY)
@@ -869,9 +874,7 @@ def scan_1d(self):
# outvar now contains results
self.scan_1d_write_plot(self.data.scan)
- print(
- " ****************************************** Scan Convergence Summary ****************************************** \n"
- )
+ print("Scan Convergence Summary \n")
sweep_values = self.data.scan.sweep[: self.data.scan.isweep]
nsweep_var_name, _ = self.scan_select(
self.data.scan.nsweep, self.data.scan.sweep, self.data.scan.isweep
@@ -929,9 +932,7 @@ def scan_2d(self):
scan_2d_ifail_list[iscan_1][iscan_2] = ifail
iscan += 1
- print(
- " ****************************************** Scan Convergence Summary ****************************************** \n"
- )
+ print("Scan Convergence Summary\n")
sweep_1_values = self.data.scan.sweep[: self.data.scan.isweep]
sweep_2_values = self.data.scan.sweep_2[: self.data.scan.isweep_2]
nsweep_var_name, _ = self.scan_select(
@@ -962,14 +963,22 @@ def scan_2d(self):
if scan_2d_ifail_list[iscan_1][iscan_2] == 1:
converged_count += 1
print(
- f"Scan {scan_point:02d}: ({nsweep_var_name} = {sweep_1_values[iscan_1 - 1]}, {nsweep_2_var_name} = {sweep_2_values[iscan_2 - 1]}) "
+ (
+ f"Scan {scan_point:02d}: ({nsweep_var_name} = "
+ f"{sweep_1_values[iscan_1 - 1]}, {nsweep_2_var_name} "
+ f"= {sweep_2_values[iscan_2 - 1]}) "
+ )
+ " " * offsets[iscan_1 - 1][iscan_2 - 1]
+ "\u001b[32mCONVERGED \u001b[0m"
)
scan_point += 1
else:
print(
- f"Scan {scan_point:02d}: ({nsweep_var_name} = {sweep_1_values[iscan_1 - 1]}, {nsweep_2_var_name} = {sweep_2_values[iscan_2 - 1]}) "
+ (
+ f"Scan {scan_point:02d}: ({nsweep_var_name} = "
+ f"{sweep_1_values[iscan_1 - 1]}, {nsweep_2_var_name} = "
+ f"{sweep_2_values[iscan_2 - 1]}) "
+ )
+ " " * offsets[iscan_1 - 1][iscan_2 - 1]
+ "\u001b[31mUNCONVERGED \u001b[0m"
)
@@ -1029,7 +1038,8 @@ def scan_1d_write_point_header(self, iscan: int):
process_output.write(
constants.NOUT,
- f"***** Scan point {iscan} of {self.data.scan.isweep} : {self.data.globals.xlabel}"
+ f"***** Scan point {iscan} of {self.data.scan.isweep} : "
+ f"{self.data.globals.xlabel}"
f", {self.data.globals.vlabel} = {self.data.scan.sweep[iscan - 1]} "
"*****",
)
@@ -1061,7 +1071,8 @@ def scan_2d_write_point_header(self, iscan, iscan_1, iscan_2):
process_output.write(
constants.NOUT,
- f"***** 2D Scan point {iscan} of {self.data.scan.isweep * self.data.scan.isweep_2} : "
+ f"***** 2D Scan point {iscan} of "
+ f"{self.data.scan.isweep * self.data.scan.isweep_2} : "
f"{self.data.globals.vlabel} = {self.data.scan.sweep[iscan_1 - 1]} and"
f" {self.data.globals.vlabel_2} = {self.data.scan.sweep_2[iscan_r - 1]} "
"*****",
diff --git a/process/core/solver/constraints.py b/process/core/solver/constraints.py
index 481f2aca16..f79f2bb8d1 100644
--- a/process/core/solver/constraints.py
+++ b/process/core/solver/constraints.py
@@ -28,7 +28,9 @@ class ConstraintRegistration:
"""Contains the constraint equation and metadata about the constraint."""
name: Hashable
- """The name (often a number) of the constraint. It can be any hashable e.g. a string."""
+ """
+ The name (often a number) of the constraint. It can be any hashable e.g. a string.
+ """
constraint_equation: Callable[["ConstraintRegistration"], "ConstraintResult"]
"""The constraint equation that, when called, returns the normalised resiudal,
constraint value, and constraint error.
@@ -51,12 +53,14 @@ class ConstraintResult(ConstraintRegistration):
"""The residual of the constraint. Ie the amount a constraint is or is not violated.
A negative residual indicates infeasibility.
A positive residual indicates feasibility.
- A 0 residual indicates that a constraint value is exactly equal to its bound (feasible, just).
+ A 0 residual indicates that a constraint value is exactly equal to its bound
+ (feasible, just).
The residual will have the same physical units as the constraint value/bound.
"""
normalised_residual: float
- """The normalised residual of the constraint. The sign of the normalised residual is interpreted
+ """The normalised residual of the constraint.
+ The sign of the normalised residual is interpreted
identical to the residual.
"""
constraint_value: float
@@ -243,7 +247,8 @@ def constraint_equation_2(constraint_registration, data):
"""
i_rad_loss: switch for radiation loss term usage in power balance (see User Guide):
- - 0 total power lost is scaling power plus radiation (needed for i_plasma_pedestal=2,3)
+ - 0 total power lost is scaling power plus radiation
+ (needed for i_plasma_pedestal=2,3)
- 1 total power lost is scaling power plus core radiation only
- 2 total power lost is scaling power only, with no additional
allowance for radiation. This is not recommended for power plant models.
@@ -252,15 +257,24 @@ def constraint_equation_2(constraint_registration, data):
- 0 do not assume plasma ignition;
- 1 assume ignited (but include auxiliary power in costs)
- pden_electron_transport_loss_mw: electron transport power per volume (MW/m3)
- pden_ion_transport_loss_mw: ion transport power per volume (MW/m3)
- pden_plasma_rad_mw: total radiation power per volume (MW/m3)
- pden_plasma_core_rad_mw: total core radiation power per volume (MW/m3)
- f_p_alpha_plasma_deposited: fraction of alpha power deposited in plasma
- pden_alpha_total_mw: alpha power per volume (MW/m3)
- pden_non_alpha_charged_mw: non-alpha charged particle fusion power per volume (MW/m3)
- pden_plasma_ohmic_mw: ohmic heating power per volume (MW/m3)
- p_hcd_injected_total_mw: total auxiliary injected power (MW)
+ pden_electron_transport_loss_mw:
+ electron transport power per volume (MW/m3)
+ pden_ion_transport_loss_mw:
+ ion transport power per volume (MW/m3)
+ pden_plasma_rad_mw:
+ total radiation power per volume (MW/m3)
+ pden_plasma_core_rad_mw:
+ total core radiation power per volume (MW/m3)
+ f_p_alpha_plasma_deposited:
+ fraction of alpha power deposited in plasma
+ pden_alpha_total_mw:
+ alpha power per volume (MW/m3)
+ pden_non_alpha_charged_mw:
+ non-alpha charged particle fusion power per volume (MW/m3)
+ pden_plasma_ohmic_mw:
+ ohmic heating power per volume (MW/m3)
+ p_hcd_injected_total_mw:
+ total auxiliary injected power (MW)
vol_plasma: plasma volume (m3)
"""
# pscaling: total transport power per volume (MW/m3)
@@ -306,12 +320,18 @@ def constraint_equation_3(constraint_registration, data):
- 0 do not assume plasma ignition;
- 1 assume ignited (but include auxiliary power in costs)
- pden_ion_transport_loss_mw: ion transport power per volume (MW/m3)
- pden_ion_electron_equilibration_mw: ion/electron equilibration power per volume (MW/m3)
- f_p_alpha_plasma_deposited: fraction of alpha power deposited in plasma
- f_pden_alpha_ions_mw: alpha power per volume to ions (MW/m3)
- p_hcd_injected_ions_mw: auxiliary injected power to ions (MW)
- vol_plasma: plasma volume (m3)
+ pden_ion_transport_loss_mw:
+ ion transport power per volume (MW/m3)
+ pden_ion_electron_equilibration_mw:
+ ion/electron equilibration power per volume (MW/m3)
+ f_p_alpha_plasma_deposited:
+ fraction of alpha power deposited in plasma
+ f_pden_alpha_ions_mw:
+ alpha power per volume to ions (MW/m3)
+ p_hcd_injected_ions_mw:
+ auxiliary injected power to ions (MW)
+ vol_plasma:
+ plasma volume (m3)
"""
# No assume plasma ignition:
if (
@@ -347,7 +367,8 @@ def constraint_equation_4(constraint_registration, data):
"""Global power balance equation for electrons
i_rad_loss: switch for radiation loss term usage in power balance
- - 0 total power lost is scaling power plus radiation (needed for i_plasma_pedestal=2,3)
+ - 0 total power lost is scaling power plus radiation
+ (needed for i_plasma_pedestal=2,3)
- 1 total power lost is scaling power plus core radiation only
- 2 total power lost is scaling power only, with no additional
allowance for radiation. This is not recommended for power plant models.
@@ -356,13 +377,20 @@ def constraint_equation_4(constraint_registration, data):
- 0 do not assume plasma ignition;
- 1 assume ignited (but include auxiliary power in costs)
- pden_electron_transport_loss_mw: electron transport power per volume (MW/m3)
- pden_plasma_rad_mw: total radiation power per volume (MW/m3)
- pden_plasma_core_rad_mw: total core radiation power per volume (MW/m3)
- f_p_alpha_plasma_deposited: fraction of alpha power deposited in plasma
- f_pden_alpha_electron_mw: alpha power per volume to electrons (MW/m3)
- pden_ion_electron_equilibration_mw: ion/electron equilibration power per volume (MW/m3)
- p_hcd_injected_electrons_mw: auxiliary injected power to electrons (MW)
+ pden_electron_transport_loss_mw:
+ electron transport power per volume (MW/m3)
+ pden_plasma_rad_mw:
+ total radiation power per volume (MW/m3)
+ pden_plasma_core_rad_mw:
+ total core radiation power per volume (MW/m3)
+ f_p_alpha_plasma_deposited:
+ fraction of alpha power deposited in plasma
+ f_pden_alpha_electron_mw:
+ alpha power per volume to electrons (MW/m3)
+ pden_ion_electron_equilibration_mw:
+ ion/electron equilibration power per volume (MW/m3)
+ p_hcd_injected_electrons_mw:
+ auxiliary injected power to electrons (MW)
vol_plasma: plasma volume (m3)
"""
# pscaling: total transport power per volume (MW/m3)
@@ -417,8 +445,10 @@ def constraint_equation_5(constraint_registration, data):
- 7 Greenwald limit
f_nd_plasma_electron_limit_max scales the constraint such that:
- nd_plasma_electrons_vol_avg / nd_plasma_electrons_max <= f_nd_plasma_electron_limit_max.
- (Except when i_density_limit=7 when nd_plasma_electron_line is used, not nd_plasma_electrons_vol_avg)
+ nd_plasma_electrons_vol_avg / nd_plasma_electrons_max <=
+ f_nd_plasma_electron_limit_max.
+ (Except when i_density_limit=7 when nd_plasma_electron_line is used,
+ not nd_plasma_electrons_vol_avg)
"""
# Apply Greenwald limit to line-averaged density
if data.physics.i_density_limit == DensityLimitModel.GREENWALD:
@@ -526,9 +556,12 @@ def constraint_equation_11(constraint_registration, data):
def constraint_equation_12(constraint_registration, data):
"""Equation for volt-second capability lower limit
- vs_plasma_total_required: total Vs needed (Wb)
- vs_plasma_total_required (lower limit) is positive; vs_cs_pf_total_pulse (available) is negative
- vs_cs_pf_total_pulse: total flux swing for pulse (Wb)
+ vs_plasma_total_required:
+ total Vs needed (Wb)
+ vs_plasma_total_required (lower limit) is positive;
+ vs_cs_pf_total_pulse (available) is negative
+ vs_cs_pf_total_pulse:
+ total flux swing for pulse (Wb)
"""
# vs_cs_pf_total_pulse is negative, requires sign change
return geq(
@@ -556,8 +589,10 @@ def constraint_equation_13(constraint_registration, data):
def constraint_equation_14(constraint_registration, data):
"""Equation to fix number of NBI decay lengths to plasma centre
- n_beam_decay_lengths_core: neutral beam e-decay lengths to plasma centre
- n_beam_decay_lengths_core_required: permitted neutral beam e-decay lengths to plasma centre
+ n_beam_decay_lengths_core:
+ neutral beam e-decay lengths to plasma centre
+ n_beam_decay_lengths_core_required:
+ permitted neutral beam e-decay lengths to plasma centre
"""
return eq(
data.current_drive.n_beam_decay_lengths_core,
@@ -705,11 +740,17 @@ def constraint_equation_22(constraint_registration, data):
def constraint_equation_23(constraint_registration, data):
"""Equation for conducting shell radius / rminor upper limit
- rminor: plasma minor radius (m)
- dr_fw_plasma_gap_outboard: gap between plasma and first wall, outboard side (m)
- dr_fw_outboard: outboard first wall thickness, initial estimate (m)
- dr_blkt_outboard: outboard blanket thickness (m)
- f_r_conducting_wall: maximum ratio of conducting wall distance to plasma minor radius for vertical stability
+ rminor:
+ plasma minor radius (m)
+ dr_fw_plasma_gap_outboard:
+ gap between plasma and first wall, outboard side (m)
+ dr_fw_outboard:
+ outboard first wall thickness, initial estimate (m)
+ dr_blkt_outboard:
+ outboard blanket thickness (m)
+ f_r_conducting_wall:
+ maximum ratio of conducting wall distance to plasma minor radius
+ for vertical stability
"""
# conducting shell radius (m)
rcw = (
@@ -750,10 +791,12 @@ def constraint_equation_24(constraint_registration, data):
or data.stellarator.istell != 0
):
value = data.physics.beta_total_vol_avg
- # Here, the beta limit applies to only the thermal component, not the fast alpha or neutral beam parts
+ # Here, the beta limit applies to only the thermal component,
+ # not the fast alpha or neutral beam parts
elif data.physics.i_beta_component == BetaComponentLimits.THERMAL:
value = data.physics.beta_thermal_vol_avg
- # Beta limit applies to thermal + neutral beam: components of the total beta, i.e. excludes alphas
+ # Beta limit applies to thermal + neutral beam: components of the total beta,
+ # i.e. excludes alphas
elif data.physics.i_beta_component == BetaComponentLimits.THERMAL_AND_BEAM:
value = data.physics.beta_thermal_vol_avg + data.physics.beta_beam
# Beta limit applies to toroidal beta
@@ -786,8 +829,10 @@ def constraint_equation_26(constraint_registration, data):
"""Equation for Central Solenoid current density upper limit at EOF
fjohc: margin for central solenoid current at end-of-flattop
- j_cs_critical_flat_top_end: allowable central solenoid current density at end of flat-top (A/m²)
- j_cs_flat_top_end: central solenoid overall current density at end of flat-top (A/m²)
+ j_cs_critical_flat_top_end:
+ allowable central solenoid current density at end of flat-top (A/m²)
+ j_cs_flat_top_end:
+ central solenoid overall current density at end of flat-top (A/m²)
"""
return leq(
(data.pf_coil.j_cs_flat_top_end / data.pf_coil.j_cs_critical_flat_top_end),
@@ -801,8 +846,10 @@ def constraint_equation_27(constraint_registration, data):
"""Equation for Central Solenoid current density upper limit at BOP
fjohc0: margin for central solenoid current at beginning of pulse
- j_cs_critical_pulse_start: allowable central solenoid current density at beginning of pulse (A/m²)
- j_cs_pulse_start: central solenoid overall current density at beginning of pulse (A/m²)
+ j_cs_critical_pulse_start:
+ allowable central solenoid current density at beginning of pulse (A/m²)
+ j_cs_pulse_start:
+ central solenoid overall current density at beginning of pulse (A/m²)
"""
return leq(
(data.pf_coil.j_cs_pulse_start / data.pf_coil.j_cs_critical_pulse_start),
@@ -871,8 +918,10 @@ def constraint_equation_30(constraint_registration, data):
def constraint_equation_31(constraint_registration, data):
"""Equation for TF coil case stress upper limit (SCTF)
- sig_tf_case_max: Allowable maximum shear stress in TF coil case (Tresca criterion) (Pa)
- sig_tf_case: Constrained stress in TF coil case (Pa)
+ sig_tf_case_max:
+ Allowable maximum shear stress in TF coil case (Tresca criterion) (Pa)
+ sig_tf_case:
+ Constrained stress in TF coil case (Pa)
"""
return leq(
data.tfcoil.sig_tf_case,
@@ -885,8 +934,10 @@ def constraint_equation_31(constraint_registration, data):
def constraint_equation_32(constraint_registration, data):
"""Equation for TF coil conduit stress upper limit (SCTF)
- sig_tf_wp_max: Allowable maximum shear stress in TF coil conduit (Tresca criterion) (Pa)
- sig_tf_wp: Constrained stress in TF conductor conduit (Pa)
+ sig_tf_wp_max:
+ Allowable maximum shear stress in TF coil conduit (Tresca criterion) (Pa)
+ sig_tf_wp:
+ Constrained stress in TF conductor conduit (Pa)
"""
return leq(
data.tfcoil.sig_tf_wp,
@@ -933,9 +984,11 @@ def constraint_equation_34(constraint_registration, data):
def constraint_equation_35(constraint_registration, data):
"""Equation for TF coil J_wp/J_prot upper limit (SCTF)
- j_tf_wp_quench_heat_max: allowable TF coil winding pack current density, for dump temperature
- rise protection (A/m²)
- j_tf_wp: winding pack current density (A/m²)
+ j_tf_wp_quench_heat_max:
+ allowable TF coil winding pack current density, for dump temperature
+ rise protection (A/m²)
+ j_tf_wp:
+ winding pack current density (A/m²)
"""
return leq(
data.tfcoil.j_tf_wp,
@@ -948,8 +1001,10 @@ def constraint_equation_35(constraint_registration, data):
def constraint_equation_36(constraint_registration, data):
"""Equation for TF coil s/c temperature margin lower limit (SCTF)
- temp_tf_superconductor_margin: TF coil temperature margin (K)
- temp_tf_superconductor_margin_min: minimum allowable temperature margin : TF coils (K)
+ temp_tf_superconductor_margin:
+ TF coil temperature margin (K)
+ temp_tf_superconductor_margin_min:
+ minimum allowable temperature margin : TF coils (K)
"""
return geq(
data.tfcoil.temp_tf_superconductor_margin,
@@ -976,12 +1031,15 @@ def constraint_equation_37(constraint_registration, data):
def constraint_equation_39(constraint_registration, data):
"""Equation for first wall temperature upper limit
- temp_fw_max: maximum temperature of first wall material (K) (i_thermal_electric_conversion>1)
- temp_fw_peak: peak first wall temperature (K)
+ temp_fw_max:
+ maximum temperature of first wall material (K) (i_thermal_electric_conversion>1)
+ temp_fw_peak:
+ peak first wall temperature (K)
"""
if data.fwbs.temp_fw_peak < 1.0:
raise ProcessValueError(
- "temp_fw_peak = 0 implies i_pulsed_plant=0; do not use constraint 39 if i_pulsed_plant=0"
+ "temp_fw_peak = 0 implies i_pulsed_plant=0; do not use constraint 39 "
+ "if i_pulsed_plant=0"
)
return leq(
@@ -1009,8 +1067,10 @@ def constraint_equation_40(constraint_registration, data):
def constraint_equation_41(constraint_registration, data):
"""Equation for plasma current ramp-up time lower limit
- t_plant_pulse_plasma_current_ramp_up: plasma current ramp-up time for current initiation (s)
- t_current_ramp_up_min: minimum plasma current ramp-up time (s)
+ t_plant_pulse_plasma_current_ramp_up:
+ plasma current ramp-up time for current initiation (s)
+ t_current_ramp_up_min:
+ minimum plasma current ramp-up time (s)
"""
return geq(
data.times.t_plant_pulse_plasma_current_ramp_up,
@@ -1028,7 +1088,8 @@ def constraint_equation_42(constraint_registration, data):
"""
if data.constraints.t_cycle_min < 1.0:
raise ProcessValueError(
- "t_cycle_min = 0 implies that i_pulsed_plant=0; do not use constraint 42 if i_pulsed_plant=0"
+ "t_cycle_min = 0 implies that i_pulsed_plant=0; "
+ "do not use constraint 42 if i_pulsed_plant=0"
)
return geq(
@@ -1088,12 +1149,16 @@ def constraint_equation_44(constraint_registration, data):
def constraint_manager_45(constraint_registration, data):
"""Equation for edge safety factor lower limit (TART)
- q95 : safety factor 'near' plasma edge
- (unless i_plasma_current = 2 (ST current scaling), in which case q = mean edge safety factor qbar)
- q95_min: lower limit for edge safety factor
- itart : input integer : switch for spherical tokamak (ST) models:
- - 0 use conventional aspect ratio models;
- - 1 use spherical tokamak models
+ q95 :
+ safety factor 'near' plasma edge
+ (unless i_plasma_current = 2 (ST current scaling),
+ in which case q = mean edge safety factor qbar)
+ q95_min:
+ lower limit for edge safety factor
+ itart :
+ input integer : switch for spherical tokamak (ST) models:
+ - 0 use conventional aspect ratio models;
+ - 1 use spherical tokamak models
"""
if data.physics.itart == 0:
raise ProcessValueError("Do not use constraint 45 if itart=0")
@@ -1276,11 +1341,16 @@ def constraint_equation_61(constraint_registration, data):
@ConstraintManager.register_constraint(62, "", ">=")
def constraint_equation_62(constraint_registration, data):
- """Lower limit on f_t_alpha_energy_confinement the ratio of alpha particle to energy confinement times
+ """Lower limit on f_t_alpha_energy_confinement the ratio of alpha particle
+ to energy confinement times
- t_alpha_confinement: alpha particle confinement time (s)
- t_energy_confinement: global thermal energy confinement time (sec)
- f_t_alpha_energy_confinement_min: Lower limit on f_t_alpha_energy_confinement the ratio of alpha particle to energy confinement times
+ t_alpha_confinement:
+ alpha particle confinement time (s)
+ t_energy_confinement:
+ global thermal energy confinement time (sec)
+ f_t_alpha_energy_confinement_min:
+ Lower limit on f_t_alpha_energy_confinement the ratio of alpha particle to
+ energy confinement times
"""
return geq(
data.physics.f_t_alpha_energy_confinement,
@@ -1293,8 +1363,10 @@ def constraint_equation_62(constraint_registration, data):
def constraint_equation_63(constraint_registration, data):
"""Upper limit on n_iter_vacuum_pumps (i_vacuum_pumping = simple)
- tfno: number of TF coils (default = 50 for stellarators)
- n_iter_vacuum_pumps: number of high vacuum pumps (real number), each with the throughput
+ tfno:
+ number of TF coils (default = 50 for stellarators)
+ n_iter_vacuum_pumps:
+ number of high vacuum pumps (real number), each with the throughput
"""
return leq(
data.vacuum.n_iter_vacuum_pumps,
@@ -1336,8 +1408,10 @@ def constraint_equation_65(constraint_registration, data):
def constrain_equation_66(constraint_registration, data):
"""Upper limit on rate of change of energy in poloidal field
- maxpoloidalpower: Maximum permitted absolute rate of change of stored energy in poloidal field (MW)
- peakpoloidalpower: Peak absolute rate of change of stored energy in poloidal field (MW) (11/01/16)
+ maxpoloidalpower:
+ Maximum permitted absolute rate of change of stored energy in poloidal field (MW)
+ peakpoloidalpower:
+ Peak absolute rate of change of stored energy in poloidal field (MW) (11/01/16)
"""
return leq(
data.pf_power.peakpoloidalpower,
@@ -1364,14 +1438,22 @@ def constraint_equation_67(constraint_registration, data):
def constraint_equation_68(constraint_registration, data):
"""Upper limit on Psep scaling (PₛₑₚBₜ / q₉₅AR₀)
- p_div_bt_q_aspect_rmajor_max_mw: maximum permitted value of ratio of PₛₑₚBₜ / q₉₅AR₀ (MWT/m)
- p_plasma_separatrix_mw: Power crossing the separartrix (MW)
- b_plasma_toroidal_on_axis: toroidal field on axis (T) (iteration variable 2)
- q95: safety factor q at 95% flux surface
- aspect: aspect ratio (iteration variable 1)
- rmajor: plasma major radius (m) (iteration variable 3)
- i_q95_fixed: Switch that allows for fixing q95 only in this constraint.
- q95_fixed: fixed safety factor q at 95% flux surface
+ p_div_bt_q_aspect_rmajor_max_mw:
+ maximum permitted value of ratio of PₛₑₚBₜ / q₉₅AR₀ (MWT/m)
+ p_plasma_separatrix_mw:
+ Power crossing the separartrix (MW)
+ b_plasma_toroidal_on_axis:
+ toroidal field on axis (T) (iteration variable 2)
+ q95:
+ safety factor q at 95% flux surface
+ aspect:
+ aspect ratio (iteration variable 1)
+ rmajor:
+ plasma major radius (m) (iteration variable 3)
+ i_q95_fixed:
+ Switch that allows for fixing q95 only in this constraint.
+ q95_fixed:
+ fixed safety factor q at 95% flux surface
"""
if data.constraints.i_q95_fixed == 1:
p_div_bt_q_aspect_rmajor_mw = (
@@ -1406,9 +1488,11 @@ def constraint_equation_72(constraint_registration, data):
into account)
- CS stress at flux swing (no current in CS) from the TF inward pressure
This allow to cover the 2 worst stress scenario in the bucked and wedged design
- Otherwise (free standing TF), the stress limits are only set by the CS stress at max current
+ Otherwise (free standing TF),
+ the stress limits are only set by the CS stress at max current
Reverse the sign so it works as an inequality constraint (tmp_cc > 0)
- This will have no effect if it is used as an equality constraint because it will be squared.
+ This will have no effect if it is used as an equality constraint
+ because it will be squared.
stress_cs_steel_max: allowable stress in Central Solenoid structural material (Pa)
stress_shear_cs_peak: Maximum shear stress coils/central solenoid (Pa)
@@ -1439,7 +1523,8 @@ def constraint_equation_72(constraint_registration, data):
@ConstraintManager.register_constraint(73, "MW", ">=")
def constraint_equation_73(constraint_registration, data):
- """Lower limit to ensure separatrix power is greater than the L-H power + auxiliary power
+ """Lower limit to ensure separatrix power is greater than the L-H power +
+ auxiliary power
Related to constraint 15
p_l_h_threshold_mw: L-H mode power threshold (MW)
@@ -1490,13 +1575,20 @@ def constraint_equation_76(constraint_registration, data):
Eich critical separatrix density model
Added for issue 558 with ref to http://iopscience.iop.org/article/10.1088/1741-4326/aaa340/pdf
- alpha_crit: critical ballooning parameter value
- nd_plasma_separatrix_electron_eich_max: critical electron density at separatrix [/m³]
- kappa: plasma separatrix elongation (calculated if i_plasma_geometry = 1-5, 7 or 9)
- triang: plasma separatrix triangularity (calculated if i_plasma_geometry = 1, 3-5 or 7)
- aspect: aspect ratio (iteration variable 1)
- p_plasma_separatrix_mw: power to conducted to the divertor region (MW)
- nd_plasma_electron_max_array(7)array : density limit [/m³] as calculated using various models
+ alpha_crit:
+ critical ballooning parameter value
+ nd_plasma_separatrix_electron_eich_max:
+ critical electron density at separatrix [/m³]
+ kappa:
+ plasma separatrix elongation (calculated if i_plasma_geometry = 1-5, 7 or 9)
+ triang:
+ plasma separatrix triangularity (calculated if i_plasma_geometry = 1, 3-5 or 7)
+ aspect:
+ aspect ratio (iteration variable 1)
+ p_plasma_separatrix_mw:
+ power to conducted to the divertor region (MW)
+ nd_plasma_electron_max_array(7)array :
+ density limit [/m³] as calculated using various models
"""
# TODO: why on earth are these variables being set here!? Should they be local?
data.physics.alpha_crit = (data.physics.kappa**1.2) * (
@@ -1550,10 +1642,15 @@ def constraint_equation_78(constraint_registration, data):
def constraint_equation_79(constraint_registration, data):
"""Equation for maximum CS field
- b_cs_limit_max: Central solenoid max field limit [T]
- b_cs_peak_pulse_start: maximum field in central solenoid at beginning of pulse (T)
- b_cs_peak_flat_top_end: maximum field in central solenoid at end of flat-top (EoF) (T)
- (Note: original code has "b_cs_peak_flat_top_end/b_cs_peak_pulse_start | peak CS field [T]".)
+ b_cs_limit_max:
+ Central solenoid max field limit [T]
+ b_cs_peak_pulse_start:
+ maximum field in central solenoid at beginning of pulse (T)
+ b_cs_peak_flat_top_end:
+ maximum field in central solenoid at end of flat-top (EoF) (T)
+
+ (Note: original code has
+ "b_cs_peak_flat_top_end/b_cs_peak_pulse_start | peak CS field [T]".)
"""
return leq(
max(
@@ -1569,12 +1666,18 @@ def constraint_equation_79(constraint_registration, data):
def constraint_equation_80(constraint_registration, data):
"""Equation for p_plasma_separatrix_mw lower limit
- args : output structure : residual error; constraint value; residual error in physical units;
- output string; units string
+ args :
+ output structure :
+ residual error;
+ constraint value;
+ residual error in physical units;
+ output string; units string
Lower limit p_plasma_separatrix_mw
- p_plasma_separatrix_min_mw : input : Minimum power crossing separatrix p_plasma_separatrix_mw [MW]
- p_plasma_separatrix_mw : input : Power crossing separatrix [MW]
+ p_plasma_separatrix_min_mw :
+ Minimum power crossing separatrix p_plasma_separatrix_mw [MW]
+ p_plasma_separatrix_mw :
+ Power crossing separatrix [MW]
"""
return geq(
data.physics.p_plasma_separatrix_mw,
@@ -1619,8 +1722,10 @@ def constraint_equation_82(constraint_registration, data):
def constraint_equation_83(constraint_registration, data):
"""Equation for radial consistency of stellarator build
- available_radial_space: avaible space in radial direction as given by each s.-configuration
- required_radial_space: required space in radial direction
+ available_radial_space:
+ avaible space in radial direction as given by each s.-configuration
+ required_radial_space:
+ required space in radial direction
"""
return geq(
data.build.available_radial_space,
@@ -1720,7 +1825,8 @@ def constraint_equation_88(constraint_registration, data):
@ConstraintManager.register_constraint(89, "A/m²", "<=")
def constraint_equation_89(constraint_registration, data):
- """Upper limit to ensure that the Central Solenoid [OH] coil current / copper area < Maximum value
+ """Upper limit to ensure that the Central Solenoid [OH]
+ coil current / copper area < Maximum value
copperaoh_m2: CS coil current at EOF / copper area [A/m²]
copperaoh_m2_max: maximum coil current / copper area [A/m²]
@@ -1752,7 +1858,8 @@ def constraint_equation_90(constraint_registration, data):
@ConstraintManager.register_constraint(91, "MW", ">=")
def constraint_equation_91(constraint_registration, data):
"""Lower limit to ensure ECRH te is greater than required te for ignition
- at lower values for n and B. Or if the design point is ECRH heatable (if i_plasma_ignited==0)
+ at lower values for n and B. Or if the design point is ECRH heatable
+ (if i_plasma_ignited==0)
stellarators only (but in principle usable also for tokamaks).
max_gyrotron_frequency: Max. av. gyrotron frequency
@@ -1837,7 +1944,8 @@ def constraint_eqns(m: int, ieqn: int, data: DataStructure):
raise ProcessValueError(error_msg, cc=tmp_cc)
# Reverse the sign so it works as an inequality constraint (cc(i) > 0)
- # This will have no effect if it is used as an equality constraint because it will be squared.
+ # This will have no effect if it is used as an equality constraint
+ # because it will be squared.
cc.append(-tmp_cc)
con.append(tmp_con)
err.append(tmp_err)
diff --git a/process/core/solver/iteration_variables.py b/process/core/solver/iteration_variables.py
index 6324b43b62..38f53a7e70 100644
--- a/process/core/solver/iteration_variables.py
+++ b/process/core/solver/iteration_variables.py
@@ -238,7 +238,8 @@ class IterationVariable:
def check_iteration_variable(iteration_variable_value, name: str = ""):
- """Check that the iteration variable value is valid (not a weird number or too small).
+ """Check that the iteration variable value is valid
+ (not a weird number or too small).
Raises an error upon encountering an invalid value, otherwise does nothing.
@@ -263,12 +264,15 @@ def check_iteration_variable(iteration_variable_value, name: str = ""):
def load_iteration_variables(data):
- """Loads the physics and engineering variables into the optimisation variable array."""
+ """
+ Loads the physics and engineering variables into the optimisation variable array.
+ """
for i in range(data.numerics.nvar):
variable_index = data.numerics.ixc[i]
iteration_variable = ITERATION_VARIABLES[variable_index]
- # use ... as the default return value because None might be a valid return from Fortran?
+ # use ... as the default return value because
+ # None might be a valid return from Fortran?
module = (
getattr(data, iteration_variable.module)
@@ -332,7 +336,7 @@ def load_iteration_variables(data):
def set_scaled_iteration_variable(xc, nn: int, data: DataStructure):
- """Converts scaled iteration variables back to their real values and sets them in the code.
+ """Converts scaled iteration variables back to their real values and sets them.
Parameters
----------
diff --git a/process/core/solver/solver.py b/process/core/solver/solver.py
index 2d12f59148..a38e6aecf6 100644
--- a/process/core/solver/solver.py
+++ b/process/core/solver/solver.py
@@ -373,7 +373,8 @@ def get_solver(data: DataStructure, solver_name: str = "vmcon") -> _Solver:
solver = load_external_solver(solver_name)
except Exception as e:
raise ProcessValueError(
- f'Solver name is not an inbuilt PROCESS solver or recognised package "{solver_name}"'
+ "Solver name is not an inbuilt PROCESS solver or recognised package "
+ f'"{solver_name}"'
) from e
return solver
diff --git a/process/main.py b/process/main.py
index bfe683a62d..551fe9f852 100644
--- a/process/main.py
+++ b/process/main.py
@@ -213,7 +213,8 @@ def process_cli(
if varyiterparams:
if mfile_path is not None:
raise click.BadParameter(
- "--mfile not supported on vary run please specify in the configuration file"
+ "--mfile not supported on vary run please specify "
+ "in the configuration file"
)
runtype = VaryRun(config_file, solver)
elif indat is None:
@@ -438,7 +439,8 @@ def run_scan(self):
pass
# ioptimz == -2: evaluation
elif self.data.numerics.ioptimz == PROCESSRunMode.EVALUATION:
- # No optimisation: solve equality (consistency) constraints only using fsolve (HYBRD)
+ # No optimisation:
+ # solve equality (consistency) constraints only using fsolve (HYBRD)
self.solver = "fsolve"
else:
raise ValueError(
@@ -480,9 +482,10 @@ def append_input(self):
mfile_file.writelines(input_lines)
def validate_input(self, replace_obsolete: bool = False):
- """Checks the input IN.DAT file for any obsolete variables in the OBS_VARS dict contained
- within obsolete_variables.py. If obsolete variables are found, and if `replace_obsolete`
- is set to True, they are either removed or replaced by their updated names as specified
+ """Checks the input IN.DAT file for any obsolete variables in the OBS_VARS dict
+ contained within obsolete_variables.py.
+ If obsolete variables are found, and if `replace_obsolete` is set to True,
+ they are either removed or replaced by their updated names as specified
in the OBS_VARS dictionary.
"""
obsolete_variables = ov.OBS_VARS
@@ -525,13 +528,16 @@ def validate_input(self, replace_obsolete: bool = False):
# Raise an error if replacement is a list
replacement_str = ", ".join(replacement)
raise ValueError(
- f"The variable '{variable_name}' is obsolete and should be replaced by the following variables: {replacement_str}. "
+ f"The variable '{variable_name}' is obsolete and "
+ "should be replaced by the following variables: "
+ f"{replacement_str}. "
"Please set their values accordingly."
)
# Replace obsolete variable
modified_line = line.replace(variable_name, replacement, 1)
modified_lines.append(
- f"* Replaced '{variable_name}' with '{replacement}'\n{modified_line}"
+ f"* Replaced '{variable_name}' with "
+ f"'{replacement}'\n{modified_line}"
)
changes_made.append(
f"Replaced '{variable_name}' with '{replacement}'"
@@ -554,7 +560,8 @@ def validate_input(self, replace_obsolete: bool = False):
with open(filename, "w") as file:
file.writelines(modified_lines)
print(
- "The IN.DAT file has been updated to replace or comment out obsolete variables."
+ "The IN.DAT file has been updated to replace or "
+ "comment out obsolete variables."
)
print("Summary of changes made:")
for change in changes_made:
@@ -562,16 +569,25 @@ def validate_input(self, replace_obsolete: bool = False):
else:
# Only print the report if replace_obsolete is False
message = (
- "The IN.DAT file contains obsolete variables from the OBS_VARS dictionary. "
- f"The obsolete variables in your IN.DAT file are: {obs_vars_in_in_dat}. "
- "Either remove these or replace them with their updated variable names. "
+ "The IN.DAT file contains obsolete variables "
+ "from the OBS_VARS dictionary. "
+ "The obsolete variables in your IN.DAT file are: "
+ f"{obs_vars_in_in_dat}. "
+ "Either remove these or replace them with "
+ "their updated variable names. "
)
for obs_var in obs_vars_in_in_dat:
replacement = obsolete_variables.get(obs_var)
if replacement is None:
- message += f"\n\n{obs_var} is an obsolete variable and needs to be removed."
+ message += (
+ f"\n\n{obs_var} is an obsolete variable "
+ "and needs to be removed."
+ )
else:
- message += f"\n\n{obs_var} is an obsolete variable and needs to be replaced by {replacement}."
+ message += (
+ f"\n\n{obs_var} is an obsolete variable "
+ f"and needs to be replaced by {replacement}."
+ )
message += f" {obsolete_vars_help_message.get(obs_var, '')}"
raise ValueError(message)
@@ -720,8 +736,10 @@ def costs(self, value: Model):
@property
def models(self) -> tuple[Model, ...]:
- # At the moment, this property just returns models that implement the Model interface.
- # Eventually every Model will comply and then this method can be used as the caller/outputter!
+ # At the moment, this property just returns models
+ # that implement the Model interface.
+ # Eventually every Model will comply and then
+ # this method can be used as the caller/outputter!
return (
self.water_use,
self._costs_2015,
diff --git a/process/models/availability.py b/process/models/availability.py
index 6d604f452a..06d953b928 100644
--- a/process/models/availability.py
+++ b/process/models/availability.py
@@ -56,12 +56,14 @@ def run(self, output: bool = False):
Parameters
----------
output :
- indicate whether output should be written to the output file, or not (default = False)
+ indicate whether output should be written to the output file, or not
"""
if self.data.costs.i_plant_availability == 3:
if self.data.physics.itart != 1:
raise ProcessValueError(
- f"{self.data.costs.i_plant_availability=} is for a Spherical Tokamak. Please set itart=1 to use this model."
+ f"{self.data.costs.i_plant_availability=}"
+ " is for a Spherical Tokamak."
+ " Please set itart=1 to use this model."
)
self.avail_st(output) # ST model (2023)
elif self.data.costs.i_plant_availability == 2:
@@ -84,15 +86,21 @@ def avail(self, output: bool):
"""
# Full power lifetime (in years)
if self.data.ife.ife != 1:
- # Calculate DPA per FPY - based on neutronics-derived fusion power relation to DEMO blanket lifetime provided by Matti Coleman
- # Detailed and cited in T. Franke 2020, "The EU DEMO equatorial outboard limiter — Design and port integration concept"
+ # Calculate DPA per FPY - based on neutronics-derived fusion power relation
+ # to DEMO blanket lifetime provided by Matti Coleman
+ # Detailed and cited in T. Franke 2020,
+ # "The EU DEMO equatorial outboard limiter,
+ # Design and port integration concept"
# https://www.sciencedirect.com/science/article/pii/S0920379620301952#bib0075
- # Scaling w.r.t. fusion power drops out a large number of factors relating to neutronics, such as:
+ # Scaling w.r.t. fusion power drops out a large number of factors relating
+ # to neutronics, such as:
# - the actual neutron flux
- # - the geometry and material composition leading to the neutron flux at the EUROfer FW OMP
+ # - the geometry and material composition leading to the neutron flux at the
+ # EUROfer FW OMP
# - the neutron energy spectrum
# - all of the above and more leading to the dpa/fpy in EUROfer at the FW OMP
- # About a relatively "constant" reference point, we can reasonably assume they all equal to 1.0.
+ # About a relatively "constant" reference point, we can reasonably assume
+ # they all equal to 1.0.
ref_fusion_power = 2.0e3 # (MW) fusion power for EU-DEMO
f_scale = self.data.physics.p_fusion_total_mw / ref_fusion_power
ref_dpa_fpy = (
@@ -101,8 +109,10 @@ def avail(self, output: bool):
dpa_fpy = f_scale * ref_dpa_fpy
# First wall / blanket lifetime (years)
- # TODO MDK Do this calculation whatever the value of blktmodel (whatever that is)
- # For some reason life_fw_fpy is not always calculated, so ignore it if it is still zero.
+ # TODO MDK Do this calculation whatever the value of blktmodel
+ # (whatever that is)
+ # For some reason life_fw_fpy is not always calculated,
+ # so ignore it if it is still zero.
if self.data.fwbs.life_fw_fpy < 0.0001e0:
# Calculate blanket lifetime using neutron fluence model (ibkt_life=0)
# or DEMO fusion power model (ibkt_life=1)
@@ -225,7 +235,8 @@ def avail(self, output: bool):
self.data.costs.life_plant,
)
- # Current drive system lifetime (assumed equal to first wall and blanket lifetime)
+ # Current drive system lifetime
+ # (assumed equal to first wall and blanket lifetime)
self.data.costs.life_hcd_fpy = self.data.fwbs.life_blkt_fpy
# Output section
@@ -418,7 +429,8 @@ def avail_2(self, output: bool):
self.data.fwbs.life_blkt_fpy / self.data.costs.f_t_plant_available,
self.data.costs.life_plant,
)
- # Current drive system lifetime (assumed equal to first wall and blanket lifetime)
+ # Current drive system lifetime
+ # (assumed equal to first wall and blanket lifetime)
self.data.costs.life_hcd_fpy = self.data.fwbs.life_blkt_fpy
# Divertor
@@ -535,14 +547,18 @@ def calc_u_planned(self, output: bool) -> float:
# Full power lifetimes (in years) !
# Caculate DPA per FPY
- # Detailed and cited in T. Franke 2020, "The EU DEMO equatorial outboard limiter — Design and port integration concept"
+ # Detailed and cited in T. Franke 2020,
+ # "The EU DEMO equatorial outboard limiter — Design and port integration concept"
# https://www.sciencedirect.com/science/article/pii/S0920379620301952#bib0075
- # Scaling w.r.t. fusion power drops out a large number of factors relating to neutronics, such as:
+ # Scaling w.r.t. fusion power drops out a large number of factors relating
+ # to neutronics, such as:
# - the actual neutron flux
- # - the geometry and material composition leading to the neutron flux at the EUROfer FW OMP
+ # - the geometry and material composition leading to the neutron flux at
+ # the EUROfer FW OMP
# - the neutron energy spectrum
# - all of the above and more leading to the dpa/fpy in EUROfer at the FW OMP
- # About a relatively "constant" reference point, we can reasonably assume they all equal to 1.0.
+ # About a relatively "constant" reference point, we can reasonably assume
+ # they all equal to 1.0.
ref_fusion_power = 2.0e3 # (MW) fusion power for EU-DEMO
f_scale = self.data.physics.p_fusion_total_mw / ref_fusion_power
ref_dpa_fpy = 10.0e0 # dpa per fpy from T. Franke 2020 states up to 10 dpa/FPY
@@ -698,7 +714,8 @@ def calc_u_unplanned_magnets(self, output: bool) -> float:
# lifetime starts to decline.
start_of_risk = mag_temp_marg_limit / self.data.costs.conf_mag
- # Determine if temperature margin is in region with risk of unplanned unavailability
+ # Determine if temperature margin is in region with risk of
+ # unplanned unavailability
if self.data.tfcoil.temp_margin >= start_of_risk:
u_unplanned_magnets = mag_min_u_unplanned
else:
@@ -783,12 +800,15 @@ def calc_u_unplanned_divertor(self, output: bool) -> float:
# Integrating the instantaneous availability gives the mean
# availability over the planned cycle life N
if self.data.costs.div_nu <= self.data.costs.div_nref:
- logger.error("""div_nu <= div_nref
- The cycle when the divertor fails with 100% probability <= & Reference value for cycle life of divertor
- """)
+ logger.error(
+ "div_nu <= div_nref\n"
+ "The cycle when the divertor fails with 100% probability <="
+ " & Reference value for cycle life of divertor"
+ )
po.ocmmnt(
self.outfile,
- "ERROR: The cycle when the divertor fails with 100% probability & <= Reference value for cycle cycle life of divertor",
+ "ERROR: The cycle when the divertor fails with 100% probability & <="
+ " Reference value for cycle cycle life of divertor",
)
# Check number of cycles
@@ -893,12 +913,15 @@ def calc_u_unplanned_fwbs(self, output: bool) -> float:
)
if self.data.costs.fwbs_nu <= self.data.costs.fwbs_nref:
- logger.error("""fwbs_nu <= fwbs_nref
- The cycle when the blanket fails with 100% probability <= &Reference value for cycle life of blanket
- """)
+ logger.error(
+ "fwbs_nu <= fwbs_nref\n"
+ "The cycle when the blanket fails with 100% probability <="
+ " &Reference value for cycle life of blanket"
+ )
po.ocmmnt(
self.outfile,
- "EROROR: The cycle when the blanket fails with 100% probability& <= Reference value for cycle life of blanket",
+ "EROROR: The cycle when the blanket fails with 100% probability& <= "
+ "Reference value for cycle life of blanket",
)
# Integrating the instantaneous availability gives the mean
@@ -1027,7 +1050,8 @@ def calc_u_unplanned_bop(self, output: bool) -> float:
@staticmethod
def calc_u_unplanned_hcd() -> float:
- """Calculates the unplanned unavailability of the heating and current drive system
+ """Calculates the unplanned unavailability of the heating
+ and current drive system
This routine calculates the unplanned unavailability of the heating
@@ -1093,7 +1117,8 @@ def calc_u_unplanned_vacuum(self, output: bool) -> float:
sum_prob = 0.0e0
for n in range(self.data.costs.redun_vac + 1, total_pumps + 1):
- # Probability for n failures in the operational period, n > number of redundant pumps
+ # Probability for n failures in the operational period, n > number
+ # of redundant pumps
# calculate sum in formula for downtime
sum_prob += (
@@ -1150,8 +1175,9 @@ def calc_u_unplanned_vacuum(self, output: bool) -> float:
def avail_st(self, output: bool):
"""Calculate the availability for a plant with a Spherical Tokamak.
- This routine calculates the availability of a plant by considering various factors such as
- the lifetime of different components, planned and unplanned unavailability, and maintenance cycles.
+ This routine calculates the availability of a plant by considering various
+ factors such as the lifetime of different components,
+ planned and unplanned unavailability, and maintenance cycles.
Parameters
----------
@@ -1160,21 +1186,31 @@ def avail_st(self, output: bool):
Notes
-----
- - The method calculates the Displacements Per Atom (DPA) per Full Power Year (FPY) based on the fusion power.
- - It determines the lifetime of the first wall and blanket, divertor, and current drive.
- - It calculates the time for a maintenance cycle and the number of maintenance cycles over the plant's lifetime.
- - It computes the planned and unplanned unavailability of various components such as magnets, divertor, first wall and blanket, balance of plant, heating and current drive, and vacuum systems.
- - The total availability of the plant is then calculated considering both planned and unplanned unavailability.
- - The method also adjusts the lifetimes of components based on the calculated availability.
+ - The method calculates the Displacements Per Atom (DPA)
+ per Full Power Year (FPY) based on the fusion power.
+ - It determines the lifetime of the first wall and blanket, divertor,
+ and current drive.
+ - It calculates the time for a maintenance cycle and the number of maintenance
+ cycles over the plant's lifetime.
+ - It computes the planned and unplanned unavailability of various components
+ such as magnets, divertor, first wall and blanket,
+ balance of plant, heating and current drive, and vacuum systems.
+ - The total availability of the plant is then calculated considering
+ both planned and unplanned unavailability.
+ - The method also adjusts the lifetimes of components based on the
+ calculated availability.
- Finally, it calculates the capacity factor and operational time of the plant.
- If `output` is True, the method writes detailed availability information to the output file.
+ If `output` is True, the method writes detailed availability information to the
+ output file.
- The method assumes certain constants and reference points for calculations.
- - The method modifies the lifetimes of components to account for the calculated availability.
+ - The method modifies the lifetimes of components to account for the calculated
+ availability.
References
----------
- - T. Franke 2020, "The EU DEMO equatorial outboard limiter — Design and port integration concept"
+ - T. Franke 2020,
+ "The EU DEMO equatorial outboard limiter — Design and port integration concept"
https://www.sciencedirect.com/science/article/pii/S0920379620301952#bib0075
"""
ref_powfmw = 2.0e3 # (MW) fusion power for EU-DEMO
@@ -1483,7 +1519,8 @@ def cp_lifetime(self):
def divertor_lifetime(self):
"""Calculate Divertor Lifetime
- This routine calculates the lifetime of the divertor based on the allowable divertor heat fluence.
+ This routine calculates the lifetime of the divertor based on the
+ allowable divertor heat fluence.
Returns
-------
@@ -1491,7 +1528,8 @@ def divertor_lifetime(self):
Divertor lifetime
"""
# Divertor lifetime
- # Either 0.0, calculated from allowable divertor fluence and heat load, or lifetime of the plant
+ # Either 0.0, calculated from allowable divertor fluence and heat load,
+ # or lifetime of the plant
return max(
0.0,
min(
diff --git a/process/models/blankets/blanket_library.py b/process/models/blankets/blanket_library.py
index b231fc85b2..93433fe187 100644
--- a/process/models/blankets/blanket_library.py
+++ b/process/models/blankets/blanket_library.py
@@ -1,4 +1,4 @@
-"""This library contains routines that can be shared by the blanket modules used in PROCESS."""
+"""This library contains routines that can be shared by the blanket modules."""
import logging
from enum import IntEnum
@@ -45,7 +45,9 @@
class FWBlktCoolantLoopTypes(IntEnum):
- """Enumeration for first wall and blanket coolant loop types. `i_fw_blkt_shared_coolant`."""
+ """Enumeration for first wall and blanket coolant loop types.
+ `i_fw_blkt_shared_coolant`.
+ """
SHARED_LOOP = 0
SEPARATE_LOOPS = 1
@@ -264,8 +266,9 @@ def calculate_dshaped_blkt_areas(
Returns
-------
- tuple[float, float, float]
- Tuple containing inboard blanket surface area (m²), outboard blanket surface area (m²),
+ :
+ Tuple containing inboard blanket surface area (m²),
+ outboard blanket surface area (m²),
and total blanket surface area (m²)
"""
# Calculate major radius to outer edge of inboard ...
@@ -412,8 +415,9 @@ def calculate_elliptical_blkt_areas(
Returns
-------
- tuple[float, float, float]
- Tuple containing inboard blanket surface area (m²), outboard blanket surface area (m²),
+ :
+ Tuple containing inboard blanket surface area (m²),
+ outboard blanket surface area (m²),
and total blanket surface area (m²)
"""
# Major radius to centre of inboard and outboard ellipses (m)
@@ -695,7 +699,8 @@ def primary_coolant_properties(self, output: bool):
"""
# Make sure that, if the inputs for the FW and blanket inputs are different,
- # the i_fw_blkt_shared_coolant variable is appropriately set for separate coolants
+ # the i_fw_blkt_shared_coolant variable is
+ # appropriately set for separate coolants
if CoolantType(self.data.fwbs.i_fw_coolant_type) != CoolantType(
self.data.fwbs.i_blkt_coolant_type
):
@@ -765,7 +770,8 @@ def primary_coolant_properties(self, output: bool):
or np.isnan(self.data.fwbs.den_fw_coolant)
):
raise ProcessValueError(
- f"Error in primary_coolant_properties. {self.data.fwbs.den_fw_coolant = }"
+ "Error in primary_coolant_properties. "
+ f"{self.data.fwbs.den_fw_coolant = }"
)
if (
self.data.fwbs.den_blkt_coolant > 1e9
@@ -773,7 +779,8 @@ def primary_coolant_properties(self, output: bool):
or np.isnan(self.data.fwbs.den_blkt_coolant)
):
raise ProcessValueError(
- f"Error in primary_coolant_properties. {self.data.fwbs.den_blkt_coolant = }"
+ "Error in primary_coolant_properties. "
+ f"{self.data.fwbs.den_blkt_coolant = }"
)
if output:
@@ -782,7 +789,8 @@ def primary_coolant_properties(self, output: bool):
)
po.ocmmnt(
self.outfile,
- "Calculated using mid temp(s) of system (or systems if use different coolant types).",
+ "Calculated using mid temp(s) of system "
+ "(or systems if use different coolant types).",
)
# FW (or FW/BB)
@@ -888,22 +896,30 @@ def primary_coolant_properties(self, output: bool):
)
def set_blanket_module_geometry(self):
- """Sets the geometry parameters for blanket modules, including coolant channel dimensions,
- module segmentation, and flow lengths, based on the current configuration and input variables.
+ """Sets the geometry parameters for blanket modules,
+ including coolant channel dimensions,
+ module segmentation, and flow lengths,
+ based on the current configuration and input variables.
The method performs the following steps:
- - Determines inboard and outboard coolant channel radial lengths based on blanket type.
- - Segments the blanket modules poloidally and toroidally according to input segmentation settings.
- - Calculates the toroidal segment lengths for inboard and outboard blanket modules.
+ - Determines inboard and outboard coolant channel radial lengths
+ based on blanket type.
+ - Segments the blanket modules poloidally and toroidally according to input
+ segmentation settings.
+ - Calculates the toroidal segment lengths for inboard and outboard
+ blanket modules.
- Computes the poloidal height of blanket modules.
- - For dual coolant blankets, calculates the minimum available space for liquid breeder pipes
- in radial, toroidal, and poloidal directions, and checks for geometric constraints.
- - Calculates total flow lengths for primary coolant channels, used in pressure drop calculations.
+ - For dual coolant blankets, calculates the minimum available space
+ for liquid breeder pipes in radial, toroidal, and poloidal directions,
+ and checks for geometric constraints.
+ - Calculates total flow lengths for primary coolant channels,
+ used in pressure drop calculations.
Raises
------
Error
- If the poloidal segment length is less than three times the minimum liquid breeder pipe width.
+ If the poloidal segment length is less than three times
+ the minimum liquid breeder pipe width.
"""
i_blanket_type = BlktModelTypes(self.data.fwbs.i_blanket_type)
if i_blanket_type == BlktModelTypes.DCLL:
@@ -926,7 +942,8 @@ def set_blanket_module_geometry(self):
# blanket into nblktmodp*nblktmodt modules, all assumed to be the same size
# If SMS blanket then do not have separate poloidal modules....
- # Should not need this as n_blkt_inboard_modules_poloidal is input but make sure here.
+ # Should not need this as n_blkt_inboard_modules_poloidal is input
+ # but make sure here.
if self.data.fwbs.i_blkt_module_segmentation == 1:
self.data.fwbs.n_blkt_inboard_modules_poloidal = 1
self.data.fwbs.n_blkt_outboard_modules_poloidal = 1
@@ -935,12 +952,12 @@ def set_blanket_module_geometry(self):
self.data.physics.itart == 1
or self.data.fwbs.i_fw_blkt_vv_shape == FwBlktVVShape.D_SHAPED
):
- self.data.blanket.len_blkt_inboard_segment_poloidal = self.calculate_dshaped_inboard_blkt_segment_poloidal(
+ self.data.blanket.len_blkt_inboard_segment_poloidal = self.calculate_dshaped_inboard_blkt_segment_poloidal( # noqa: E501
dz_blkt_half=self.data.blanket.dz_blkt_half,
n_blkt_inboard_modules_poloidal=self.data.fwbs.n_blkt_inboard_modules_poloidal,
)
- self.data.blanket.len_blkt_outboard_segment_poloidal = self.calculate_dshaped_outboard_blkt_segment_poloidal(
+ self.data.blanket.len_blkt_outboard_segment_poloidal = self.calculate_dshaped_outboard_blkt_segment_poloidal( # noqa: E501
n_blkt_outboard_modules_poloidal=self.data.fwbs.n_blkt_outboard_modules_poloidal,
dr_fw_plasma_gap_inboard=self.data.build.dr_fw_plasma_gap_inboard,
rminor=self.data.physics.rminor,
@@ -950,7 +967,7 @@ def set_blanket_module_geometry(self):
f_ster_div_single=self.data.fwbs.f_ster_div_single,
)
else:
- self.data.blanket.len_blkt_inboard_segment_poloidal = self.calculate_elliptical_inboard_blkt_segment_poloidal(
+ self.data.blanket.len_blkt_inboard_segment_poloidal = self.calculate_elliptical_inboard_blkt_segment_poloidal( # noqa: E501
rmajor=self.data.physics.rmajor,
rminor=self.data.physics.rminor,
triang=self.data.physics.triang,
@@ -961,7 +978,7 @@ def set_blanket_module_geometry(self):
f_ster_div_single=self.data.fwbs.f_ster_div_single,
)
- self.data.blanket.len_blkt_outboard_segment_poloidal = self.calculate_elliptical_outboard_blkt_segment_poloidal(
+ self.data.blanket.len_blkt_outboard_segment_poloidal = self.calculate_elliptical_outboard_blkt_segment_poloidal( # noqa: E501
rmajor=self.data.physics.rmajor,
rminor=self.data.physics.rminor,
triang=self.data.physics.triang,
@@ -974,7 +991,8 @@ def set_blanket_module_geometry(self):
# If liquid breeder or dual coolant blanket then calculate
if self.data.fwbs.i_blkt_dual_coolant > 0:
- # Use smallest space available to pipes for pipe sizes in pumping calculations (worst case)
+ # Use smallest space available to pipes for pipe sizes
+ # in pumping calculations (worst case)
if (
self.data.build.i_blkt_inboard
== InboardBlanketConfiguration.INBOARD_BLANKET_PRESENT
@@ -1257,8 +1275,10 @@ def thermo_hydraulic_model_pressure_drop_calculations(self, output: bool):
flow_density=self.data.fwbs.den_blkt_coolant,
)
- # Get mass flow rate etc. for inboard blanket breeder flow for tritium extraction
- # Use the number of desired recirculations ([Aub2013]=10) and mass from dcll_masses
+ # Get mass flow rate etc. for inboard blanket breeder flow
+ # for tritium extraction
+ # Use the number of desired recirculations ([Aub2013]=10)
+ # and mass from dcll_masses
# N.B. wht_liq is BZ mass, does not include manifold.
self.data.blanket.mfblkto_liq = (
self.data.fwbs.n_liq_recirc * self.data.fwbs.wht_liq_ob
@@ -1307,8 +1327,10 @@ def thermo_hydraulic_model_pressure_drop_calculations(self, output: bool):
flow_density=self.data.fwbs.den_blkt_coolant,
)
- # Get mass flow rate etc. for inboard blanket breeder flow for tritium extraction
- # Use the number of desired recirculations ([Aub2013]=10) and mass from dcll_masses
+ # Get mass flow rate etc. for inboard blanket breeder flow for
+ # tritium extraction
+ # Use the number of desired recirculations ([Aub2013]=10) and
+ # mass from dcll_masses
# N.B. wht_liq is BZ mass, does not include manifold.
self.data.blanket.mfblkti_liq = (
self.data.fwbs.n_liq_recirc * self.data.fwbs.wht_liq_ib
@@ -1324,7 +1346,8 @@ def thermo_hydraulic_model_pressure_drop_calculations(self, output: bool):
# If the blanket is single-coolant with solid breeder...
else:
- # Calculate total number of pipes (in all outboard modules) from coolant fraction and
+ # Calculate total number of pipes (in all outboard modules) from
+ # coolant fraction and
# channel dimensions (assumes up/down flow, two 90 deg bends per length)
self.data.blanket.n_blkt_outboard_channels = (
self.data.fwbs.f_a_blkt_cooling_channels
@@ -1675,8 +1698,10 @@ def calculate_elliptical_inboard_blkt_segment_poloidal(
# Calculate ellipse circumference using Ramanujan approximation (m)
ptor = np.pi * (3.0 * (a + b) - np.sqrt((3.0 * a + b) * (a + 3.0 * b)))
- # Calculate inboard blanket poloidal length and segment, subtracting divertor length (m)
- # Assume divertor lies between the two ellipses, so fraction f_ster_div_single still applies
+ # Calculate inboard blanket poloidal length and segment,
+ # subtracting divertor length (m)
+ # Assume divertor lies between the two ellipses,
+ # so fraction f_ster_div_single still applies
# kit hcll version only had the single null option
if n_divertors == 2:
@@ -1745,7 +1770,8 @@ def calculate_elliptical_outboard_blkt_segment_poloidal(
ptor = np.pi * (3.0 * (a + b) - np.sqrt((3.0 * a + b) * (a + 3.0 * b)))
# kit hcll version only had the single null option
- # Calculate outboard blanket poloidal length and segment, subtracting divertor length (m)
+ # Calculate outboard blanket poloidal length and segment,
+ # subtracting divertor length (m)
if n_divertors == 2:
# Double null configuration
len_blkt_outboard_segment_poloidal = (
@@ -1762,8 +1788,11 @@ def calculate_elliptical_outboard_blkt_segment_poloidal(
return len_blkt_outboard_segment_poloidal
def liquid_breeder_properties(self, output: bool = False):
- """Calculates the fluid properties of the Liquid Metal Breeder/Coolant in the Blanket BZ
- Uses middle value of input and output temperatures of Liquid Metal Breeder/Coolant
+ """Calculates the fluid properties of the
+ Liquid Metal Breeder/Coolant in the Blanket BZ
+
+ Uses middle value of input and output temperatures of
+ Liquid Metal Breeder/Coolant
Curently have PbLi but can expand with e.g., Lithium
Parameters
@@ -1781,7 +1810,8 @@ def liquid_breeder_properties(self, output: bool = False):
nuclear fusion technology, Journal of Nuclear Materials, Vol. 376(6).
[Mar2019] Martelli et al. (2019), Literature review of lead-lithium
- thermophysical properties, Fusion Engineering and Design, 138, 183-195.
+ thermophysical properties, Fusion Engineering and Design, 138,
+ 183-195.
"""
# Use mid temp
if self.data.fwbs.inlet_temp_liq == self.data.fwbs.outlet_temp_liq:
@@ -1797,15 +1827,15 @@ def liquid_breeder_properties(self, output: bool = False):
# Constant pressure ~ 17 atmospheres ~ 1.7D6 Pa
# Li content is ~ 17%
#
- # density kg m-3 T in Kelvin range = 508-880 K
+ # density kg m-3 T in Kelvin range = 508-880 K
#
- # specific_heat J kg-1 K-1 T in Kelvin range = 508-880 K
+ # specific_heat J kg-1 K-1 T in Kelvin range = 508-880 K
#
- # thermal_conductivity W m-1 K-1 T in Celcius range = 508-773 K
+ # thermal_conductivity W m-1 K-1 T in Celcius range = 508-773 K
#
- # dynamic_viscosity Pa s T in Celcius range = 508-873 K
+ # dynamic_viscosity Pa s T in Celcius range = 508-873 K
#
- # electrical_conductivity A V-1 m-1 T in Kelvin range = 600-800 K
+ # electrical_conductivity A V-1 m-1 T in Kelvin range = 600-800 K
# Caculate properties
self.data.fwbs.den_liq = 1.052e4 * (1 - mid_temp_liq * 1.13e-4)
@@ -1837,7 +1867,8 @@ def liquid_breeder_properties(self, output: bool = False):
# If the liquid metal is Li...
elif self.data.fwbs.i_blkt_liquid_breeder_type == 1:
- # Temporary - should be updated with information from Li reviews conducted at CCFE once completed
+ # Temporary - should be updated with information from Li reviews conducted
+ # at CCFE once completed
# Li Properties from [Mal1995] at 300 Celcius
# den_liq = 505 kg/m3
# specific_heat_liq = 4260 J kg-1 K-1
@@ -1845,7 +1876,8 @@ def liquid_breeder_properties(self, output: bool = False):
# dynamic_viscosity_liq = 1.0D-6 m2 s-1
# electrical_conductivity_liq = 3.03D6 A V-1 m-1
- # New from 'Application of lithium in systems of fusion reactors. 1. Physical and chemical properties of lithium'
+ # New from 'Application of lithium in systems of fusion reactors.
+ # 1. Physical and chemical properties of lithium'
# Lyublinski et al., 2009, Plasma Devicec and Operations
self.data.fwbs.den_liq = (
504.43
@@ -1911,7 +1943,8 @@ def liquid_breeder_properties(self, output: bool = False):
self.data.fwbs.electrical_conductivity_liq
/ self.data.fwbs.dynamic_viscosity_liq
)
- # Use toroidal width of the rectangular cooling channel as characteristic length scale
+ # Use toroidal width of the rectangular cooling channel
+ # as characteristic length scale
self.data.fwbs.hartmann_liq = (
np.asarray(self.data.fwbs.b_mag_blkt)
* self.data.fwbs.a_bz_liq
@@ -1925,13 +1958,15 @@ def liquid_breeder_properties(self, output: bool = False):
or (t_ranges[:, 1] < mid_temp_liq).any()
):
logger.error(
- "Outside temperature limit for one or more liquid metal breeder properties"
+ "Outside temperature limit for one or more "
+ "liquid metal breeder properties"
)
if output:
po.ocmmnt(
self.outfile,
- "Outside temperature limit for one or more liquid metal breeder properties.",
+ "Outside temperature limit for one or "
+ "more liquid metal breeder properties.",
)
po.ovarre(
self.outfile,
@@ -2024,8 +2059,11 @@ def liquid_breeder_properties(self, output: bool = False):
)
def flow_velocity(self, i_channel_shape, mass_flow_rate, flow_density):
- """Calculate the coolant flow velocity (m/s) for given pipe mass flow rate and pipe size/shape.
- N.B. Assumed that primary BB and FW coolants have same pipe radius (= radius_fw_channel).
+ """Calculate the coolant flow velocity (m/s) for given pipe mass flow rate
+ and pipe size/shape.
+
+ N.B. Assumed that primary BB and FW coolants have same pipe radius
+ (= radius_fw_channel).
Parameters
@@ -2067,43 +2105,49 @@ def thermo_hydraulic_model(self, output: bool):
Dual-coolant modifications and generalisation refactor: G. Graham, CCFE
Three options:
- 1. Solid breeder - nuclear heating in the blanket is exctrated by the primary coolant.
+ 1. Solid breeder - nuclear heating in the blanket is
+ exctrated by the primary coolant.
2. Liquid metal breeder, single-coolant
- nuclear heating in the blanket is exctrated by the primary coolant.
- - liquid metal is circulated for tritium extraction, specified by number of circulations/day.
+ - liquid metal is circulated for tritium extraction, specified
+ by number of circulations/day.
3. Liquid metal breeder, dual-coolant -
- - nuclear heating in the liquid breeder/coolant is extracted by the liquid breeder/coolant.
- - nuclear heating in the blanket structure is extracted by the primary coolant
+ - nuclear heating in the liquid breeder/coolant is extracted
+ by the liquid breeder/coolant.
+ - nuclear heating in the blanket structure is extracted
+ by the primary coolant
Flow Channel and Coolant Input Info:
- N.B. Primary coolant applies to single-coolant BB, or structural cooling of dual-coolant BB.
- Secondary coolant applies to self-cooled breeder material.
+ N.B. Primary coolant applies to single-coolant BB, or structural cooling of
+ dual-coolant BB.
+ Secondary coolant applies to self-cooled breeder material.
- Coolant Channels FW BB primary BB Liquid Breeder/Coolant
+ Coolant Channels FW BB primary BB Liquid Breeder/Coolant
- length (m) len_fw_channel
- width (m) radius_fw_channel (radius, cicular) radius_fw_channel a_bz_liq, b_bz_liq (rectangular)
- wall thickness (m) dr_fw_wall dr_fw_wall th_wall_secondary
- dx_fw_module (m) dx_fw_module
- roughness epsilon roughness_fw_channel
- peak FW temp (K) temp_fw_peak
- maximum temp (K) temp_fw_max
- FCI switch --- --- i_blkt_liquid_breeder_channel_type
+ length (m) len_fw_channel
+ width (m) radius_fw_channel radius_fw_channel a_bz_liq, b_bz_liq (rectangular)
+ (radius, cicular)
+ wall thickness (m) dr_fw_wall dr_fw_wall th_wall_secondary
+ dx_fw_module (m) dx_fw_module
+ roughness epsilon roughness_fw_channel
+ peak FW temp (K) temp_fw_peak
+ maximum temp (K) temp_fw_max
+ FCI switch --- --- i_blkt_liquid_breeder_channel_type
- Coolant FW BB primary BB secondary
+ Coolant FW BB primary BB secondary
- primary coolant switch i_fw_coolant_type i_blkt_coolant_type ---
- secondary coolant switch --- --- i_blkt_liquid_breeder_type
- inlet temp (K) temp_fw_coolant_in temp_blkt_coolant_in inlet_temp_liq
- outlet temp (K) temp_fw_coolant_out temp_blkt_coolant_out outlet_temp_liq
- pressure (Pa) pres_fw_coolant pres_blkt_coolant blpressure_liq
+ primary coolant switch i_fw_coolant_type i_blkt_coolant_type ---
+ secondary coolant switch --- --- i_blkt_liquid_breeder_type
+ inlet temp (K) temp_fw_coolant_in temp_blkt_coolant_in inlet_temp_liq
+ outlet temp (K) temp_fw_coolant_out temp_blkt_coolant_out outlet_temp_liq
+ pressure (Pa) pres_fw_coolant pres_blkt_coolant blpressure_liq
Parameters
----------
output: bool
- """
+ """ # noqa: E501
######################################################
# Pre calculations needed for thermo-hydraulic model #
######################################################
@@ -2166,7 +2210,8 @@ def thermo_hydraulic_model(self, output: bool):
# FW and BB Mass Flow ###########
# Make sure that, if the inputs for the FW and blanket inputs are different,
- # the i_fw_blkt_shared_coolant variable is appropriately set for separate coolants
+ # the i_fw_blkt_shared_coolant variable is appropriately set
+ # for separate coolants
if CoolantType(self.data.fwbs.i_fw_coolant_type) != CoolantType(
self.data.fwbs.i_blkt_coolant_type
):
@@ -2348,8 +2393,10 @@ def thermo_hydraulic_model(self, output: bool):
)
)
- # Get mass flow rate etc. for inboard blanket breeder flow for tritium extraction
- # Use the number of desired recirculations ([Aub2013]=10) and mass from dcll_masses
+ # Get mass flow rate etc. for inboard blanket breeder flow
+ # for tritium extraction
+ # Use the number of desired recirculations ([Aub2013]=10)
+ # and mass from dcll_masses
# N.B. wht_liq is BZ mass, does not include manifold.
self.data.blanket.mfblkto_liq = (
self.data.fwbs.n_liq_recirc * self.data.fwbs.wht_liq_ob
@@ -2806,7 +2853,8 @@ def thermo_hydraulic_model(self, output: bool):
if self.data.fwbs.i_blkt_dual_coolant > 0:
po.ovarre(
self.outfile,
- "Total mechanical pumping power for FW, blanket and liquid metal breeder(MW)",
+ "Total mechanical pumping power for FW, "
+ "blanket and liquid metal breeder(MW)",
"(htpmw_blkt_tot)",
self.data.heat_transport.htpmw_blkt_tot,
"OP ",
@@ -2841,9 +2889,11 @@ def total_pressure_drop(
nopolchan: int,
label: str,
) -> float:
- """Calculate the total pressure drop (Pa) for coolant flow in the first wall (FW) and breeding blanket (BZ).
+ """Calculate the total pressure drop (Pa) for coolant flow in the
+ first wall (FW) and breeding blanket (BZ).
- This includes frictional losses and, for liquid breeder coolants, magnetohydrodynamic (MHD) losses.
+ This includes frictional losses and, for liquid breeder coolants,
+ magnetohydrodynamic (MHD) losses.
Parameters
----------
@@ -2941,8 +2991,10 @@ def liquid_breeder_mhd_pressure_drop(
label: str,
output: bool = False,
):
- """Calculates the pressure drop in a liquid metal flow channel due to MHD effects. The total pressure
- drop is the sum of contributions. This is only used for secondary coolant/breeder so rectangular flow
+ """Calculates the pressure drop in a liquid metal flow channel
+ due to MHD effects.
+ The total pressure drop is the sum of contributions.
+ This is only used for secondary coolant/breeder so rectangular flow
channels are assumed.
@@ -2966,8 +3018,10 @@ def liquid_breeder_mhd_pressure_drop(
References
----------
- [Miy1986] Miyazaki et al. (1986), Magneto-Hydro-Dynamic Pressure Drop of Lithium
- Flow in Rectangular Ducts, Fusion Technology, 10:3P2A, 830-836, DOI: 10.13182/FST10-830
+ [Miy1986] Miyazaki et al. (1986), Magneto-Hydro-Dynamic
+ Pressure Drop of Lithium
+ Flow in Rectangular Ducts, Fusion Technology, 10:3P2A, 830-836,
+ DOI: 10.13182/FST10-830
[Mal1995] Malang and Mattas (1995), Comparison of lithium and the eutectic
lead-lithium alloy, two candidate liquid metal breeder materials
@@ -3034,7 +3088,8 @@ def liquid_breeder_mhd_pressure_drop(
if self.data.fwbs.i_blkt_liquid_breeder_channel_type == 0:
po.ocmmnt(
self.outfile,
- "Flow channels have thin conducting walls (i_blkt_liquid_breeder_channel_type==0)",
+ "Flow channels have thin conducting walls "
+ "(i_blkt_liquid_breeder_channel_type==0)",
)
po.ovarre(
self.outfile,
@@ -3046,7 +3101,8 @@ def liquid_breeder_mhd_pressure_drop(
elif self.data.fwbs.i_blkt_liquid_breeder_channel_type == 2:
po.ocmmnt(
self.outfile,
- "Flow Channel Inserts (FCIs) used (i_blkt_liquid_breeder_channel_type==2)",
+ "Flow Channel Inserts (FCIs) used "
+ "(i_blkt_liquid_breeder_channel_type==2)",
)
po.ovarre(
self.outfile,
@@ -3058,7 +3114,8 @@ def liquid_breeder_mhd_pressure_drop(
else:
po.ocmmnt(
self.outfile,
- "Flow Channel Inserts - assumed perfect insulator (i_blkt_liquid_breeder_channel_type==1)",
+ "Flow Channel Inserts - assumed perfect insulator "
+ "(i_blkt_liquid_breeder_channel_type==1)",
)
po.ovarre(
@@ -3155,7 +3212,8 @@ def coolant_friction_pressure_drop(
)
# Calculate Darcy friction factor
- # N.B. friction function Uses Haaland approx. which assumes a filled circular pipe.
+ # N.B. friction function Uses Haaland approx.
+ # which assumes a filled circular pipe.
# Use dh which allows us to do fluid calculations for non-cicular tubes
# (dh is estimate appropriate for fully developed flow).
@@ -3328,7 +3386,8 @@ def elbow_coeff(
a = 0.7 + (0.35 * np.sin((deg_pipe_elbow / 90.0) * (np.pi / 180.0)))
else:
raise ProcessValueError(
- "No formula for 70 <= elbow angle(deg) <= 100, only 90 deg option available in this range."
+ "No formula for 70 <= elbow angle(deg) <= 100, "
+ "only 90 deg option available in this range."
)
r_ratio = radius_pipe_elbow / dia_pipe
@@ -3367,14 +3426,16 @@ def coolant_pumping_power(
den_coolant: float,
label: str,
) -> float:
- """Calculate the coolant pumping power in MW for the first wall (FW) or breeding blanket (BZ) coolant.
+ """Calculate the coolant pumping power in MW for the first wall (FW) or
+ breeding blanket (BZ) coolant.
Parameters
----------
output : bool
Whether to write data to output file.
i_liquid_breeder : int
- Switch for primary coolant or secondary coolant/breeder (1=primary He/H2O, 2=secondary PbLi/Li).
+ Switch for primary coolant or secondary coolant/breeder
+ (1=primary He/H2O, 2=secondary PbLi/Li).
temp_coolant_pump_outlet : float
Pump outlet temperature (K).
temp_coolant_pump_inlet : float
@@ -3423,7 +3484,8 @@ def coolant_pumping_power(
# Assume isentropic pump so that s1 = s2
s1 = pump_outlet_fluid_properties.entropy
- # Get specific enthalpy at the outlet (J/kg) before pump using pressure and entropy s1
+ # Get specific enthalpy at the outlet (J/kg) before pump using
+ # pressure and entropy s1
pump_inlet_fluid_properties = FluidProperties.of(
fluid_name=CoolantType(i_coolant_type).full_name,
pressure=pres_coolant_pump_inlet,
@@ -3677,7 +3739,8 @@ def calculate_blkt_inboard_poloidal_plasma_angle(
dz_blkt_half: float,
dr_fw_plasma_gap_inboard: float,
) -> float:
- """Calculate the poloidal angle subtended by the inboard blanket at the plasma mid-plane.
+ """Calculate the poloidal angle subtended by the inboard blanket
+ at the plasma mid-plane.
Angle is taken from the FW surface
@@ -3706,7 +3769,8 @@ def calculate_blanket_inboard_module_geometry(
rminor: float,
dr_fw_plasma_gap_inboard: float,
) -> float:
- """Calculate the mid-plane toroidal circumference and segment length of the inboard blanket.
+ """Calculate the mid-plane toroidal circumference and segment length
+ of the inboard blanket.
Parameters
----------
diff --git a/process/models/blankets/dcll.py b/process/models/blankets/dcll.py
index 74b5a9d6df..6d31e0c929 100644
--- a/process/models/blankets/dcll.py
+++ b/process/models/blankets/dcll.py
@@ -12,7 +12,7 @@
class DCLL(InboardBlanket, OutboardBlanket):
- """This module contains the Dual Coolant Lead Lithium (DCLL) specific submods of PROCESSS.
+ """This module contains the Dual Coolant Lead Lithium (DCLL).
@@ -39,16 +39,22 @@ class DCLL(InboardBlanket, OutboardBlanket):
Liquid Metal Breeder Material = PbLi
i_blkt_liquid_breeder_type = 0 * Liquid Metal Breeder Material = PbLi
- Specify dual-coolant i.e., get mass flow required from heat extracted from liqid metal breeder
+ Specify dual-coolant i.e., get mass flow required from heat extracted
+ from liqid metal breeder
i_blkt_dual_coolant = 2
- FIC switch: 0 = no FIC, Eurofer; 1 = FCIs, perfect electrical insulator, 2 = FCIs, with specified conductance
+ FIC switch: 0 = no FIC, Eurofer; 1 = FCIs, perfect electrical insulator,
+ 2 = FCIs, with specified conductance
i_blkt_liquid_breeder_channel_type = 0, 1, or 2
- Liquid metal duct wall conductance initialised at Eurofer value in fwbs_variables, or can input other value, used for i_blkt_liquid_breeder_channel_type = 0 or 2
+ Liquid metal duct wall conductance initialised at Eurofer value in
+ fwbs_variables, or can input other value,
+ used for i_blkt_liquid_breeder_channel_type = 0 or 2
(bz_channel_conduct_liq)
- Choose if FW and BB structure are on the same pumping system (unless have diffent coolants), default is same coolant with flow IN->FW->BB->OUT
+ Choose if FW and BB structure are on the same pumping system
+ (unless have diffent coolants), default is same coolant with
+ flow IN->FW->BB->OUT
(i_fw_blkt_shared_coolant)
Can set inlet and oulet temperature for liquid metal breeder
@@ -65,7 +71,8 @@ class DCLL(InboardBlanket, OutboardBlanket):
for self-cooled blankets, Fusion Engineering and Design 27, 399-406
[Gas2001] Gasior and Mozer (2001), Thermodynamic study of liquid lithium-lead
- alloys using the EMF method, Journal of Nuclear Materials, 294, 77-83
+ alloys using the EMF method, Journal of Nuclear Materials, 294,
+ 77-83
[Pal2016] Palermo et al. (2016), Neutronic analyses of the preliminary design
of a DCLL blanket for the EUROfusion DEMO power plant,
@@ -80,7 +87,8 @@ class DCLL(InboardBlanket, OutboardBlanket):
Design 167, 112380
- Note: request for when CCFE Bluemira neutronics work is added: output maximum values, as well as average values, for wall neutronics calculation if possible.
+ Note: request for when CCFE Bluemira neutronics work is added: output maximum values,
+ as well as average values, for wall neutronics calculation if possible.
"""
def output(self):
@@ -89,7 +97,9 @@ def output(self):
def run(self, output: bool = False):
self.component_volumes()
- # If Shfranov shift is added, the angle formula can be used where the shift is added to the minor radius. For now, the shift is neglected and the angle is calculated using the minor radius only.
+ # If Shfranov shift is added, the angle formula can be used where the shift is
+ # added to the minor radius. For now, the shift is neglected
+ # and the angle is calculated using the minor radius only.
self.data.blanket.deg_blkt_outboard_poloidal_plasma = (
self.blkt_outboard_poloidal_plasma_angle(
n_divertors=self.data.divertor.n_divertors,
@@ -125,13 +135,13 @@ def run(self, output: bool = False):
self.set_blanket_module_geometry()
- self.data.blanket.len_blkt_inboard_segment_toroidal = self.calculate_blanket_inboard_module_geometry(
+ self.data.blanket.len_blkt_inboard_segment_toroidal = self.calculate_blanket_inboard_module_geometry( # noqa: E501
n_blkt_inboard_modules_toroidal=self.data.fwbs.n_blkt_inboard_modules_toroidal,
rmajor=self.data.physics.rmajor,
rminor=self.data.physics.rminor,
dr_fw_plasma_gap_inboard=self.data.build.dr_fw_plasma_gap_inboard,
)
- self.data.blanket.len_blkt_outboard_segment_toroidal = self.calculate_blanket_outboard_module_geometry(
+ self.data.blanket.len_blkt_outboard_segment_toroidal = self.calculate_blanket_outboard_module_geometry( # noqa: E501
n_blkt_outboard_modules_toroidal=self.data.fwbs.n_blkt_outboard_modules_toroidal,
rmajor=self.data.physics.rmajor,
rminor=self.data.physics.rminor,
@@ -148,12 +158,14 @@ def run(self, output: bool = False):
self.write_output()
def dcll_neutronics_and_power(self, output: bool):
- """This is a temporary module that will use results from CCFE Bluemira nutronics work (once completed).
- Database will provide values for power deposition in FW & BB, BB TBR, and nuron fluence at TF coil for
- different thicknesses of BB and meterial fractions.
-
- For now we use the same method as KIT HCLL and the user can select appropriate fractional
- values from DCLL nutronics studies as inputs.
+ """This is a temporary module that will use results from
+ CCFE Bluemira nutronics work (once completed).
+ Database will provide values for power deposition in FW & BB, BB TBR,
+ and nuron fluence at TF coil for different thicknesses of BB
+ and meterial fractions.
+
+ For now we use the same method as KIT HCLL and the user can select
+ appropriate fractional values from DCLL nutronics studies as inputs.
See fwbs_variables:
- pnuc_fw_ratio_dcll
- pnuc_blkt_ratio_dcll
@@ -271,11 +283,13 @@ def dcll_neutronics_and_power(self, output: bool):
)
po.ocmmnt(
self.outfile,
- "(Note: f_p_blkt_multiplication is fixed for this model inside the code)",
+ "(Note: f_p_blkt_multiplication is fixed for "
+ "this model inside the code)",
)
po.ovarre(
self.outfile,
- "Total nuclear heating in the blanket (including f_p_blkt_multiplication) (MW)",
+ "Total nuclear heating in the blanket "
+ "(including f_p_blkt_multiplication) (MW)",
"(p_blkt_nuclear_heat_total_mw)",
self.data.fwbs.p_blkt_nuclear_heat_total_mw,
"OP ",
@@ -324,7 +338,8 @@ def dcll_power_and_heating(self, output: bool):
# For i_p_coolant_pumping == 0:
# User sets mechanical pumping power directly (primary_pumping_power)
- # Values of p_blkt_coolant_pump_mw, p_div_coolant_pump_mw, p_fw_coolant_pump_mw, p_shld_coolant_pump_mw set in input file
+ # Values of p_blkt_coolant_pump_mw, p_div_coolant_pump_mw, p_fw_coolant_pump_mw,
+ # p_shld_coolant_pump_mw set in input file
i_p_coolant_pumping = PumpingPowerModelTypes(self.data.fwbs.i_p_coolant_pumping)
if i_p_coolant_pumping == PumpingPowerModelTypes.FRACTION_OF_HEAT:
# User sets mechanical pumping power directly
@@ -355,7 +370,8 @@ def dcll_power_and_heating(self, output: bool):
}:
# Mechanical pumping power is calculated for first wall and blanket
self.thermo_hydraulic_model(output=output)
- # For divertor,mechanical pumping power is a fraction of thermal power removed by coolant
+ # For divertor,mechanical pumping power is a fraction of
+ # thermal power removed by coolant
self.data.heat_transport.p_div_coolant_pump_mw = (
self.data.heat_transport.f_p_div_coolant_pump_total_heat
* (
@@ -365,7 +381,8 @@ def dcll_power_and_heating(self, output: bool):
)
)
- # Shield power is negligible and this model doesn't have nuclear heating to the shield
+ # Shield power is negligible and this model doesn't have
+ # nuclear heating to the shield
self.data.heat_transport.p_shld_coolant_pump_mw = (
self.data.heat_transport.f_p_shld_coolant_pump_total_heat * 0.0
)
@@ -394,7 +411,8 @@ def dcll_power_and_heating(self, output: bool):
else:
po.ovarre(
self.outfile,
- "Mechanical pumping power for FW and blanket cooling loop including heat exchanger (MW)",
+ "Mechanical pumping power for FW and blanket cooling loop including "
+ "heat exchanger (MW)",
"(p_fw_blkt_coolant_pump_mw)",
self.data.primary_pumping.p_fw_blkt_coolant_pump_mw,
"OP ",
@@ -485,7 +503,9 @@ def dcll_masses(self, output: bool):
IB/OB FW = 1.98D-2 m, 85.54% EUROfer, 14.46% He
BZ
- IB/OB BZ radial stiffening plates total = 6.0D-2 m, 91.33% EUROfer, 8.67% He
+ IB/OB BZ radial stiffening plates
+ total = 6.0D-2 m, 91.33% EUROfer, 8.67% He
+
IB PbLi Channels = 3.0D-1 m, 100% PbLi
OB PbLi Channels = 6.4D-1 m, 100% PbLi
IB He plena EUROfer walls = 1.0D-1 m, 53% EUROfer, 47% He
@@ -514,7 +534,8 @@ def dcll_masses(self, output: bool):
else:
self.data.dcll.r_fci = 0.0
- # Back wall set 0.02m thickness but will vary BZ (structure and breeder) thickness
+ # Back wall set 0.02m thickness
+ # but will vary BZ (structure and breeder) thickness
self.data.dcll.bz_r_ib = self.data.build.blbuith - self.data.dcll.r_fci
self.data.dcll.bz_r_ob = self.data.build.blbuoth - self.data.dcll.r_fci
# Back wall thickness (m)
@@ -835,8 +856,10 @@ def dcll_masses(self, output: bool):
)
# Mass of material = density of material * fraction of material by volume * (
- # (volume OB blanket * blanket OB zone thickness/ total OB blanket thickness) +
- # (volume IB blanket * blanket IB zone thickness/ total IB blanket thickness)
+ # (volume OB blanket * blanket OB zone thickness/
+ # total OB blanket thickness) +
+ # (volume IB blanket * blanket IB zone thickness/
+ # total IB blanket thickness)
if output:
po.osubhd(self.outfile, "DCLL model: Masses")
diff --git a/process/models/blankets/hcpb.py b/process/models/blankets/hcpb.py
index 6cd5d2e862..4198403355 100644
--- a/process/models/blankets/hcpb.py
+++ b/process/models/blankets/hcpb.py
@@ -27,9 +27,10 @@ class CCFE_HCPB(OutboardBlanket, InboardBlanket):
References
----------
- - M. Kovari et al., “PROCESS: A systems code for fusion power plants - Part 2: Engineering,”
- Fusion Engineering and Design, vol. 104, pp. 9-20, Mar. 2016,
- doi: https://doi.org/10.1016/j.fusengdes.2016.01.007.
+ - M. Kovari et al., “PROCESS: A systems code for fusion power plants -
+ Part 2: Engineering,”
+ Fusion Engineering and Design, vol. 104, pp. 9-20, Mar. 2016,
+ doi: https://doi.org/10.1016/j.fusengdes.2016.01.007.
"""
def output(self):
@@ -43,7 +44,9 @@ def run(self, output: bool = False):
# Calculate blanket, shield, vacuum vessel and cryostat volumes
self.component_volumes()
- # If Shfranov shift is added, the angle formula can be used where the shift is added to the minor radius. For now, the shift is neglected and the angle is calculated using the minor radius only.
+ # If Shfranov shift is added, the angle formula can be used where the shift is
+ # added to the minor radius. For now, the shift is neglected and
+ # the angle is calculated using the minor radius only.
self.data.blanket.deg_blkt_outboard_poloidal_plasma = (
self.blkt_outboard_poloidal_plasma_angle(
n_divertors=self.data.divertor.n_divertors,
@@ -79,13 +82,13 @@ def run(self, output: bool = False):
self.set_blanket_module_geometry()
- self.data.blanket.len_blkt_inboard_segment_toroidal = self.calculate_blanket_inboard_module_geometry(
+ self.data.blanket.len_blkt_inboard_segment_toroidal = self.calculate_blanket_inboard_module_geometry( # noqa: E501
n_blkt_inboard_modules_toroidal=self.data.fwbs.n_blkt_inboard_modules_toroidal,
rmajor=self.data.physics.rmajor,
rminor=self.data.physics.rminor,
dr_fw_plasma_gap_inboard=self.data.build.dr_fw_plasma_gap_inboard,
)
- self.data.blanket.len_blkt_outboard_segment_toroidal = self.calculate_blanket_outboard_module_geometry(
+ self.data.blanket.len_blkt_outboard_segment_toroidal = self.calculate_blanket_outboard_module_geometry( # noqa: E501
n_blkt_outboard_modules_toroidal=self.data.fwbs.n_blkt_outboard_modules_toroidal,
rmajor=self.data.physics.rmajor,
rminor=self.data.physics.rminor,
@@ -177,7 +180,8 @@ def run(self, output: bool = False):
# Normalisation of the nuclear heating
# The nuclear heating are normalised assuming no energy multiplication
# in the divertor and the centrepost
- # Assume that all the neutrons are absorbed. (Not applicable for very thin blankets)
+ # Assume that all the neutrons are absorbed.
+ # (Not applicable for very thin blankets)
# Rem SK : This calculation effectively only uses the angular fractions to get
# the energy multiplication and hence the power balance ...
@@ -192,10 +196,13 @@ def run(self, output: bool = False):
)
# Total nuclear power deposited in the
- # if ( pnuc_tot_blk_sector < 1.0d0 .or. pnuc_tot_blk_sector /= pnuc_tot_blk_sector ) then
+ # if ( pnuc_tot_blk_sector < 1.0d0 .or.
+ # pnuc_tot_blk_sector /= pnuc_tot_blk_sector ) then
# #TODO This can flood the terminal, and should be logged once in Python
- # write(*,*)'p_fw_nuclear_heat_total_mw =', p_fw_nuclear_heat_total_mw, ' and ', 'p_blkt_nuclear_heat_total_mw =', p_blkt_nuclear_heat_total_mw
- # write(*,*)'p_shld_nuclear_heat_mw =', p_shld_nuclear_heat_mw, ' p_tf_nuclear_heat_mw =', p_tf_nuclear_heat_mw
+ # write(*,*)'p_fw_nuclear_heat_total_mw =', p_fw_nuclear_heat_total_mw, ' and ',
+ # 'p_blkt_nuclear_heat_total_mw =', p_blkt_nuclear_heat_total_mw
+ # write(*,*)'p_shld_nuclear_heat_mw =', p_shld_nuclear_heat_mw,
+ # ' p_tf_nuclear_heat_mw =', p_tf_nuclear_heat_mw
# end if
# Solid angle fraction taken by the breeding blankets/shields
@@ -309,10 +316,12 @@ def component_masses(self):
* self.data.fwbs.f_a_fw_coolant_outboard
)
- # Mass of He coolant = volume * density at typical coolant temperatures and pressures (kg)
+ # Mass of He coolant = volume * density at typical coolant temperatures
+ # and pressures (kg)
self.data.fwbs.m_fw_blkt_div_coolant_total = coolvol * 1.517
- # Average first wall coolant fraction, only used by old routines in fispact.f90, safety.f90
+ # Average first wall coolant fraction, only used by old routines in fispact.f90,
+ # safety.f90
self.data.fwbs.fwclfr = (
self.data.first_wall.a_fw_inboard
* self.data.build.dr_fw_inboard
@@ -326,9 +335,11 @@ def component_masses(self):
* (self.data.build.dr_fw_inboard + self.data.build.dr_fw_outboard)
)
- # CCFE HCPB calculates the mass of the divertor, blanket (including seprate masses for each material),
+ # CCFE HCPB calculates the mass of the divertor,
+ # blanket (including seprate masses for each material),
# shield, FW and FW armour.
- # KIT HCPB calculates the mass of the blanket (including seprate masses for each material)
+ # KIT HCPB calculates the mass of the blanket
+ # (including seprate masses for each material)
# and the void fraction for the blanket.
# N.B. i_blanket_type=1 for CCFE HCPB
@@ -657,7 +668,8 @@ def nuclear_heating_blanket(
Returns
-------
:
- p_blkt_nuclear_heat_total_mw (float): Total nuclear heating in the blanket (MW).
+ p_blkt_nuclear_heat_total_mw (float): Total nuclear heating in the blanket
+ (MW).
- exp_blanket (float): Exponential blanket factor (dimensionless).
Raises
@@ -699,9 +711,11 @@ def nuclear_heating_shield(
) -> tuple[float, float, float, float]:
"""Calculate the nuclear heating in the shield for the CCFE HCPB model.
- This method calculates the nuclear heating in the shield using empirical coefficients and exponents,
- based on the shield's geometry, density, and the total fusion power. The calculation distinguishes
- between spherical tokamak and conventional configurations for the average shield thickness.
+ This method calculates the nuclear heating in the shield using empirical
+ coefficients and exponents, based on the shield's geometry, density,
+ and the total fusion power. The calculation distinguishes
+ between spherical tokamak and
+ conventional configurations for the average shield thickness.
Parameters
----------
@@ -726,7 +740,8 @@ def nuclear_heating_shield(
p_shld_nuclear_heat_mw (float): Total nuclear heating in shield (MW).
- exp_shield1 (float): First exponential factor for shield heating.
- exp_shield2 (float): Second exponential factor for shield heating.
- - shld_u_nuc_heating (float): Unit nuclear heating of shield (W/kg/GW of fusion power) x mass.
+ - shld_u_nuc_heating (float): Unit nuclear heating of shield
+ (W/kg/GW of fusion power) x mass.
"""
# Shield nuclear heating coefficients and exponents
@@ -865,7 +880,8 @@ def powerflow_calc(self, output: bool):
# blanket inlet/pump oulet.
# The pressures (found in fwbs_variables) for coolants using
# i_p_coolant_pumping==2 are assumed to be the pressure at the
- # blanket oulet/pump inlet. The equation below is used for i_p_coolant_pumping==2:
+ # blanket oulet/pump inlet.
+ # The equation below is used for i_p_coolant_pumping==2:
# pfactor = ((pressure+deltap)/pressure)**((gamma-1.0d0)/gamma)
t_in_compressor = self.data.primary_pumping.t_in_bb / pfactor
dt_he = (
@@ -945,7 +961,8 @@ def powerflow_calc(self, output: bool):
)
po.ovarre(
self.outfile,
- "Mechanical pumping power for FW and blanket cooling loop including heat exchanger (MW)",
+ "Mechanical pumping power for FW and "
+ "blanket cooling loop including heat exchanger (MW)",
"(p_fw_blkt_coolant_pump_mw)",
self.data.primary_pumping.p_fw_blkt_coolant_pump_mw,
"OP ",
@@ -1188,7 +1205,8 @@ def st_centrepost_nuclear_heating(self, pneut, sh_width):
# so the TF is mostly copper, making the calculation also valid for
# Copper TF centrepost
else:
- # This subroutine uses an shielding length per decade (/10 drop in neutron heating)
+ # This subroutine uses an shielding length per decade
+ # (/10 drop in neutron heating)
# of 15.5 cm, within to the "15 - 16 cm" of Menard et al. 2016.
# (This is an e-folding lenth of 6.72 cm.)
@@ -1222,13 +1240,15 @@ def st_centrepost_nuclear_heating(self, pneut, sh_width):
-24.401 * sh_width_eff
)
- # Nuclear power density deposited in the tungsten carbyde shield by photons [MW]
+ # Nuclear power density deposited in the
+ # tungsten carbyde shield by photons [MW]
pnuc_cp_sh_gam = sh_width_eff * (
596 * np.exp(-4.130 * sh_width_eff)
+ 90.586 * np.exp(0.6837 * sh_width_eff)
)
- # Nuclear power density deposited in the tungsten carbyde shield by neutrons [MW]
+ # Nuclear power density deposited in the
+ # tungsten carbyde shield by neutrons [MW]
pnuc_cp_sh_n = sh_width_eff * (
202.10 * np.exp(-10.533 * sh_width_eff)
+ 80.510 * np.exp(-0.9801 * sh_width_eff)
@@ -1458,7 +1478,8 @@ def write_output(self):
)
po.ovarre(
self.outfile,
- "Total nuclear heating in the blanket (including f_p_blkt_multiplication) (MW)",
+ "Total nuclear heating in the blanket "
+ "(including f_p_blkt_multiplication) (MW)",
"(p_blkt_nuclear_heat_total_mw)",
self.data.fwbs.p_blkt_nuclear_heat_total_mw,
"OP ",
@@ -1568,7 +1589,8 @@ def write_output(self):
)
po.ovarre(
self.outfile,
- "Total electrical coolant pumping power: first wall, blanket, shield and divertor (MW)",
+ "Total electrical coolant pumping power: "
+ "first wall, blanket, shield and divertor (MW)",
"(p_coolant_pump_elec_total_mw)",
self.data.heat_transport.p_coolant_pump_elec_total_mw,
"OP ",
diff --git a/process/models/build.py b/process/models/build.py
index 038bff087f..f7846ec457 100644
--- a/process/models/build.py
+++ b/process/models/build.py
@@ -95,7 +95,8 @@ def calculate_beam_port_size(
tuple[float, float]
Tuple containing (radius_beam_tangency, radius_beam_tangency_max)
"""
- # Have kept the single letter variable names to match the original code and documentation diagram.
+ # Have kept the single letter variable names to match the original code and
+ # documentation diagram.
radius_beam_tangency = f_radius_beam_tangency_rmajor * rmajor
omega = 2.0 * np.pi / n_tf_coils
@@ -133,7 +134,8 @@ def calculate_beam_port_size(
radius_beam_tangency_max = f * np.cos(eps) - 0.5e0 * c
else:
logger.error(
- "Max beam tangency radius set =0 temporarily; change dx_beam_duct. %s %s",
+ "Max beam tangency radius set =0 temporarily; "
+ "change dx_beam_duct. %s %s",
g,
c,
)
@@ -144,8 +146,10 @@ def calculate_beam_port_size(
def calculate_vertical_build(self, output: bool):
"""Determines the vertical build of the machine.
- This method calculates various parameters related to the vertical build of the machine,
- such as thicknesses, radii, and areas. Results can be outputted with the `output` flag.
+ This method calculates various parameters related
+ to the vertical build of the machine,
+ such as thicknesses, radii, and areas.
+ Results can be outputted with the `output` flag.
Parameters
----------
@@ -779,7 +783,9 @@ def calculate_vertical_build(self, output: bool):
)
po.ocmmnt(
self.outfile,
- "\n*Cryostat roof allowance includes uppermost PF coil and outer thermal shield.\n*Cryostat floor allowance includes lowermost PF coil, outer thermal shield and gravity support.",
+ "\n*Cryostat roof allowance includes uppermost PF coil and "
+ "outer thermal shield.\n*Cryostat floor allowance "
+ "includes lowermost PF coil, outer thermal shield and gravity support.",
)
# Output the cdivertor geometry
@@ -1524,7 +1530,8 @@ def plasma_outboard_edge_toroidal_ripple(
tuple[float, float, int]
Tuple containing:
- ripple: Calculated ripple at plasma edge (percent)
- - r_tf_outboard_midmin: Minimum r_tf_outboard_mid that yields the specified maximum ripple (m)
+ - r_tf_outboard_midmin: Minimum r_tf_outboard_mid that yields the specified
+ maximum ripple (m)
- flag: Applicability flag (0 = OK, non-zero = fitted-range concern)
Notes
@@ -1532,7 +1539,8 @@ def plasma_outboard_edge_toroidal_ripple(
- Fitted coefficients originate from parametric MAGINT runs (M. Kovari, 2014).
- Picture-frame coil analytical model (Ken McClements, 2022) is used when
`i_tf_shape == 2` and gives approximate results (within ~10% of numerical).
- - The routine sets an applicability flag when fitted-range assumptions are exceeded.
+ - The routine sets an applicability flag when fitted-range assumptions are
+ exceeded.
"""
if i_tf_sup == 1:
# Minimal inboard WP radius [m]
@@ -1569,7 +1577,8 @@ def plasma_outboard_edge_toroidal_ripple(
# Ken McClements ST picture frame coil analytical ripple calc
# Calculated ripple for coil at r_tf_outboard_mid (%)
ripple = 100.0e0 * ((rmajor + rminor) / r_tf_outboard_mid) ** (n_tf_coils)
- # Calculated r_tf_outboard_mid to produce a ripple of amplitude ripple_b_tf_plasma_edge_max
+ # Calculated r_tf_outboard_mid to produce a ripple of amplitude
+ # ripple_b_tf_plasma_edge_max
r_tf_outboard_midmin = (rmajor + rminor) / (
(0.01e0 * ripple_b_tf_plasma_edge_max) ** (1.0e0 / n_tf_coils)
)
@@ -1588,7 +1597,8 @@ def plasma_outboard_edge_toroidal_ripple(
* ((rmajor + rminor) / r_tf_outboard_mid) ** (n_tf_coils - c2)
)
- # Calculated r_tf_outboard_mid to produce a ripple of amplitude ripple_b_tf_plasma_edge_max
+ # Calculated r_tf_outboard_mid to produce a ripple of amplitude
+ # ripple_b_tf_plasma_edge_max
base = 0.01 * ripple_b_tf_plasma_edge_max / c1
# Avoid potential negative or complex result: kludge base to be
# small and positive if required
@@ -1700,7 +1710,8 @@ def calculate_radial_build(self, output: bool):
self.data.build.dr_cs_precomp = 0.0e0
# Issue #514 Radial dimensions of inboard leg
- # Calculate self.data.build.dr_tf_inboard if self.data.tfcoil.dr_tf_wp_with_insulation is an iteration variable (140)
+ # Calculate self.data.build.dr_tf_inboard if
+ # self.data.tfcoil.dr_tf_wp_with_insulation is an iteration variable (140)
if 140 in self.data.numerics.ixc[0 : self.data.numerics.nvar]:
self.data.build.dr_tf_inboard = (
self.data.tfcoil.dr_tf_wp_with_insulation
@@ -1762,11 +1773,14 @@ def calculate_radial_build(self, output: bool):
+ self.data.tfcoil.drtop
)
- # Notify user that self.data.build.r_cp_top has been set to 1.01*self.data.build.r_tf_inboard_out (lvl 2 error)
+ # Notify user that self.data.build.r_cp_top has been set to
+ # 1.01*self.data.build.r_tf_inboard_out (lvl 2 error)
if self.data.build.r_cp_top < 1.01e0 * self.data.build.r_tf_inboard_out:
logger.error(
- "TF CP top radius (r_cp_top) replaced by 1.01*r_tf_inboard_out -> potential top rbuild issue"
- f"{self.data.build.r_cp_top=} {self.data.build.r_tf_inboard_out=}"
+ "TF CP top radius (r_cp_top) replaced by 1.01*r_tf_inboard_out "
+ "-> potential top rbuild issue"
+ f"{self.data.build.r_cp_top=} "
+ f"{self.data.build.r_tf_inboard_out=}"
)
# self.data.build.r_cp_top correction
@@ -1779,11 +1793,14 @@ def calculate_radial_build(self, output: bool):
# User defined self.data.build.r_cp_top
elif self.data.build.i_r_cp_top == 1:
- # Notify user that self.data.build.r_cp_top has been set to 1.01*self.data.build.r_tf_inboard_out (lvl 2 error)
+ # Notify user that self.data.build.r_cp_top has been set to
+ # 1.01*self.data.build.r_tf_inboard_out (lvl 2 error)
if self.data.build.r_cp_top < 1.01e0 * self.data.build.r_tf_inboard_out:
logger.error(
- "TF CP top radius (r_cp_top) replaced by 1.01*r_tf_inboard_out -> potential top rbuild issue"
- f"{self.data.build.r_cp_top=} {self.data.build.r_tf_inboard_out=}"
+ "TF CP top radius (r_cp_top) replaced by 1.01*r_tf_inboard_out "
+ "-> potential top rbuild issue"
+ f"{self.data.build.r_cp_top=} "
+ f"{self.data.build.r_tf_inboard_out=}"
)
# self.data.build.r_cp_top correction
@@ -1819,7 +1836,8 @@ def calculate_radial_build(self, output: bool):
+ self.data.tfcoil.drtop
):
logger.error(
- f"Top CP radius larger that its value determined with plasma shape {self.data.build.r_cp_top=}"
+ "Top CP radius larger that its value determined with plasma shape "
+ f"{self.data.build.r_cp_top=}"
)
if self.data.build.i_tf_inside_cs == TFCSRadialConfiguration.TF_INSIDE_CS:
# Radial position of vacuum vessel [m]
@@ -1989,12 +2007,15 @@ def calculate_radial_build(self, output: bool):
/ self.data.physics.rmajor
)
logger.warning(
- "(TF coil ripple calculation) Dimensionless coil width X out of fitted range. %s",
+ "(TF coil ripple calculation) "
+ "Dimensionless coil width X out of fitted range. %s",
diagnostic,
)
elif self.data.build.ripflag == 2:
logger.warning(
- f"(TF coil ripple calculation) No of TF coils not between 16 and 20 inclusive {self.data.tfcoil.n_tf_coils=}"
+ "(TF coil ripple calculation) "
+ "No of TF coils not between 16 and 20 inclusive "
+ f"{self.data.tfcoil.n_tf_coils=}"
)
else:
diagnostic = (
@@ -2002,7 +2023,8 @@ def calculate_radial_build(self, output: bool):
) / self.data.build.r_tf_outboard_mid
logger.warning(
- "(TF coil ripple calculation) (R+a)/rtot=%s out of fitted range.",
+ "(TF coil ripple calculation) "
+ "(R+a)/rtot=%s out of fitted range.",
diagnostic,
)
@@ -2015,7 +2037,8 @@ def calculate_radial_build(self, output: bool):
po.ocmmnt(
self.outfile,
(
- f" -> {TFCSRadialConfiguration(self.data.build.i_tf_inside_cs).description}"
+ " -> "
+ f"{TFCSRadialConfiguration(self.data.build.i_tf_inside_cs).description}"
),
)
po.oblnkl(self.outfile)
@@ -2031,13 +2054,15 @@ def calculate_radial_build(self, output: bool):
po.ocmmnt(
self.outfile,
(
- "\n (The stated machine dr_bore size is just for the hollow space, "
+ "\n "
+ "(The stated machine dr_bore size is just for the hollow space, "
),
)
po.ocmmnt(
self.outfile,
(
- "the true dr_bore size used for calculations is dr_bore + dr_tf_inboard + dr_cs_tf_gap)\n"
+ "the true dr_bore size used for calculations is "
+ "dr_bore + dr_tf_inboard + dr_cs_tf_gap)\n"
),
)
if (
@@ -2046,7 +2071,8 @@ def calculate_radial_build(self, output: bool):
):
po.ocmmnt(
self.outfile,
- "(Bore hollow space has been filled with a solid metal cyclinder to act as wedge support)\n",
+ "(Bore hollow space has been filled with a solid metal cyclinder to"
+ " act as wedge support)\n",
)
# an array that holds the following information
@@ -2350,7 +2376,8 @@ def calculate_radial_build(self, output: bool):
):
po.ovarre(
self.mfile,
- "Width of neutral beam duct where it passes between the TF coils (m)",
+ "Width of neutral beam duct where it passes between the "
+ "TF coils (m)",
"(dx_beam_duct)",
self.data.current_drive.dx_beam_duct,
)
diff --git a/process/models/buildings.py b/process/models/buildings.py
index 7e8f9f6f69..749ca6c433 100644
--- a/process/models/buildings.py
+++ b/process/models/buildings.py
@@ -31,7 +31,8 @@ def output(self):
def run(self, output: bool = False):
# Find TF coil radial positions
- # outboard edge: outboard mid-leg radial position + half-thickness of outboard leg
+ # outboard edge: outboard mid-leg radial position + half-thickness
+ # of outboard leg
tfro = self.data.build.r_tf_outboard_mid + (
self.data.build.dr_tf_outboard * 0.5e0
)
@@ -177,7 +178,9 @@ def bldgs(
# rxcl : clearance around reactor, m
# trcl : transportation clearance between components, m
# row : clearance to building wall for crane operation, m
- # 19.48258241468535 + 4 + max(13.764874193548387 - 4.7423258064516141, 17.123405859443331 - 2.9939411851091102) + 1 + 4 = 42.61204708901957
+ # 19.48258241468535 + 4 + max(13.764874193548387 - 4.7423258064516141,
+ # 17.123405859443331 - 2.9939411851091102) + 1 + 4
+ # = 42.61204708901957
self.data.buildings.wrbi = (
bmr
+ self.data.buildings.rxcl
@@ -307,7 +310,8 @@ def bldgs(
cryv = 55.0e0 * helpow**0.5
# Other building volumes
# pibv : power injection building volume, m3
- # esbldgm3 is forced to be zero if no energy storage is required (i_pulsed_plant=0)
+ # esbldgm3 is forced to be zero if no energy storage is required
+ # (i_pulsed_plant=0)
elev = (
self.data.buildings.tfcbv
+ self.data.buildings.pfbldgm3
@@ -519,8 +523,9 @@ def bldgs_sizes(self, output, tf_radial_dim, tf_vertical_dim):
reactor_building_vol = reactor_building_area * reactor_building_h
# Reactor maintenance basement and tunnel
- # Architecture proposed here is a basement directly beneath the reactor enabling the
- # downwards extraction of hot components. The footprint estimated here is oversized to
+ # Architecture proposed here is a basement directly beneath the reactor enabling
+ # the downwards extraction of hot components.
+ # The footprint estimated here is oversized to
# include allowance for a tunnel to the hot cell storage/maintenance building.
reactor_basement_l = self.data.buildings.reactor_hall_w
reactor_basement_w = self.data.buildings.reactor_hall_w
@@ -541,18 +546,25 @@ def bldgs_sizes(self, output, tf_radial_dim, tf_vertical_dim):
buildings_total_vol = reactor_hall_vol + reactor_basement_vol
# Hot Cell Facility
- # Provides hot cell facilities to maintain or dismantle highly radioactive components.
- # These are simplifications of R. Gowland's estimates of Operational Active Waste Storage,
- # which assumes all in-vessel components used through the life of the plant will need storage.
- # The storage area required is derived from the sizes and number of components, allowing
- # for a margin in component numbers as set by the quantity safety factor (self.data.buildings.qnty_sfty_fac).
- # Footprints and volumes required for storage include hot separation distance (self.data.buildings.hot_sepdist).
+ # Provides hot cell facilities to maintain or dismantle highly radioactive
+ # components.
+ # These are simplifications of R. Gowland's estimates of
+ # Operational Active Waste Storage,
+ # which assumes all in-vessel components used through the life of the plant
+ # will need storage.
+ # The storage area required is derived from the sizes and number of components,
+ # allowing for a margin in component numbers as set by the quantity safety factor
+ # (self.data.buildings.qnty_sfty_fac).
+ # Footprints and volumes required for storage include hot separation distance
+ # (self.data.buildings.hot_sepdist).
# Assumptions:
- # tokomak is toroidally segmented based on number of TF coils (self.data.tfcoil.n_tf_coils);
+ # tokomak is toroidally segmented based on number of TF coils
+ # (self.data.tfcoil.n_tf_coils);
# component will be stored with the largest dimension oriented horizontally;
# height is the largest dimension;
- # if a component lifetime == 0, that component is not in the current machine build.
+ # if a component lifetime == 0,
+ # that component is not in the current machine build.
# Inboard 'component': shield, blanket, first wall:
# find height, maximum radial dimension, maximum toroidal dimension
@@ -593,7 +605,8 @@ def bldgs_sizes(self, output, tf_radial_dim, tf_vertical_dim):
min(hcomp_rad_thk, hcomp_tor_thk) + self.data.buildings.hot_sepdist
)
# required lifetime supply of components =
- # ( number in build * (plant lifetime / component lifetime) ) * quantity safety factor
+ # ( number in build * (plant lifetime / component lifetime) )
+ # * quantity safety factor
hcomp_req_supply = (
self.data.tfcoil.n_tf_coils
* (self.data.costs.life_plant / self.data.costs.life_plant)
@@ -719,7 +732,8 @@ def bldgs_sizes(self, output, tf_radial_dim, tf_vertical_dim):
# Heat sink facilities, includes aux heat sink at heat energy island,
# low temp and emergency heat sink facilities, ultimate heat sink facility
- # to sea/river/cooling towers, including pumping, chemical dosing and heat exchangers
+ # to sea/river/cooling towers, including pumping,
+ # chemical dosing and heat exchangers
heat_sink_area = (
self.data.buildings.heat_sink_l * self.data.buildings.heat_sink_w
)
@@ -860,7 +874,8 @@ def bldgs_sizes(self, output, tf_radial_dim, tf_vertical_dim):
buildings_total_vol += elec_buildings_vol
# Turbine Hall
- # As proposed by R. Gowland, based on assessment of 18 existing fission power plants:
+ # As proposed by R. Gowland, based on assessment of 18 existing
+ # fission power plants:
# turbine hall size is largely independent of plant output power.
# The default footprint used here represents a weighted mean of those plants
# and the design of a Steam Rankine cycle turbine building,
@@ -964,9 +979,11 @@ def bldgs_sizes(self, output, tf_radial_dim, tf_vertical_dim):
# Staff Services
# Derived from W. Smith's estimates of necessary facilities and their sizes;
# includes main office buildings, contractor offices, staff restaurant and cafe,
- # staff induction and training facilities, main gate and reception, access control
+ # staff induction and training facilities, main gate and reception,
+ # access control
# and site pass office, occupational health centre.
- # Amalgamates estimates of floor area for all individual buildings, uses average height.
+ # Amalgamates estimates of floor area for all individual buildings,
+ # uses average height.
staff_buildings_vol = (
self.data.buildings.staff_buildings_area
* self.data.buildings.staff_buildings_h
diff --git a/process/models/costs/costs.py b/process/models/costs/costs.py
index 7d9702e8bc..3c657f24e8 100644
--- a/process/models/costs/costs.py
+++ b/process/models/costs/costs.py
@@ -55,7 +55,8 @@ def run(self):
self.acc26()
# Total plant direct cost
- # cdirt = c21 + c22 + self.data.costs.c23 + self.data.costs.c24 + self.data.costs.c25 + self.data.costs.c26
+ # cdirt = c21 + c22 + self.data.costs.c23 + self.data.costs.c24 +
+ # self.data.costs.c25 + self.data.costs.c26
self.data.costs.cdirt = (
self.data.costs.c21
+ self.data.costs.c22
@@ -1754,7 +1755,8 @@ def acc2222(self):
* constants.DEN_COPPER
)
else:
- # MDK I don't know if this is ccorrect as we never use the resistive model
+ # MDK I don't know if this is ccorrect as we never use the
+ # resistive model
costpfcu = (
self.data.costs.uccu
* self.data.pf_coil.a_cs_cable_space
@@ -1896,7 +1898,9 @@ def acc223(self):
# Account 223.3 : Neutral Beam
- # self.data.costs.c2233 = 1.0e-6 * self.data.costs.ucnbi * (1.0e6*p_hcd_beam_injected_total_mw)**exprf
+ # self.data.costs.c2233 =
+ # 1.0e-6 * self.data.costs.ucnbi
+ # * (1.0e6*p_hcd_beam_injected_total_mw)**exprf
# #327
self.data.costs.c2233 = (
@@ -2213,8 +2217,8 @@ def acc2261(self):
# Pumps and piping system
# N.B. with blktmodel > 0, the blanket is assumed to be helium-cooled,
- # but the shield etc. is water-cooled (i_blkt_coolant_type=2). Therefore, a slight
- # inconsistency exists here...
+ # but the shield etc. is water-cooled (i_blkt_coolant_type=2).
+ # Therefore, a slight inconsistency exists here...
self.data.costs.cpp = (
1.0e-6
* self.data.costs.uchts[self.data.fwbs.i_blkt_coolant_type - 1]
@@ -2334,7 +2338,8 @@ def acc2272(self):
"""
if self.data.ife.ife != 1:
# Previous calculation, using molflow_plasma_fuelling_required in Amps:
- # 1.3 should have been self.data.physics.m_fuel_amu*umass/electron_charge*1000*s/day = 2.2
+ # 1.3 should have been
+ # self.data.physics.m_fuel_amu*umass/electron_charge*1000*s/day = 2.2
# wtgpd = burnup * molflow_plasma_fuelling_required * 1.3e0
# New calculation: 2 nuclei * reactions/sec * kg/nucleus * g/kg * sec/day
@@ -2648,8 +2653,8 @@ def acc2253(self):
# of the cost of the piping within the block, etc.
#
# shcss is the specific heat capacity of stainless steel (J/kg/K)
- # self.data.pulse.dtstor is the maximum allowable temperature change in the
- # stainless steel block (input)
+ # self.data.pulse.dtstor is the maximum allowable temperature change in
+ # the stainless steel block (input)
shcss = 520.0e0
self.data.costs.c2253 = (
@@ -2863,7 +2868,9 @@ def coelc(self):
if self.data.heat_transport.p_plant_electric_net_mw < 0:
sqrt_p_plant_electric_net_mw_1200 = 0.0
logger.warning(
- "p_plant_electric_net_mw has gone negative! Clamping it to 0 for the calculation of annoam and annwst (cost of maintenance and cost of waste)."
+ "p_plant_electric_net_mw has gone negative! "
+ "Clamping it to 0 for the calculation of annoam and annwst "
+ "(cost of maintenance and cost of waste)."
)
else:
sqrt_p_plant_electric_net_mw_1200 = np.sqrt(
@@ -2932,8 +2939,9 @@ def coelc(self):
# this purpose at the start of the plant life.
# Final factor takes into account inflation over the plant lifetime
# (suggested by Tim Hender 07/03/96)
- # Difference (self.data.costs.dintrt) between borrowing and saving interest rates is
- # included, along with the possibility of completing the fund self.data.costs.dtlife
+ # Difference (self.data.costs.dintrt) between borrowing and
+ # saving interest rates is included,
+ # along with the possibility of completing the fund self.data.costs.dtlife
# years before the end of the plant's lifetime
anndecom = (
@@ -2981,7 +2989,8 @@ def convert_fpy_to_calendar(self):
self.data.fwbs.life_blkt = (
self.data.fwbs.life_blkt_fpy * self.data.costs.f_t_plant_available
)
- # Current drive system lifetime (assumed equal to first wall and blanket lifetime)
+ # Current drive system lifetime
+ # (assumed equal to first wall and blanket lifetime)
self.data.costs.cdrlife_cal = self.data.fwbs.life_blkt
else:
self.data.fwbs.life_blkt = self.data.fwbs.life_blkt_fpy
diff --git a/process/models/costs/costs_2015.py b/process/models/costs/costs_2015.py
index 311903ae6e..e9ba8d25b2 100644
--- a/process/models/costs/costs_2015.py
+++ b/process/models/costs/costs_2015.py
@@ -237,8 +237,10 @@ def calc_fwbs_costs(self):
"Blanket and shield materials and manufacturing"
)
# The cost of making the blanket was estimated for PPCS A.
- # This cost includes only manufacturing - not R&D, transport, or assembly in the reactor.
- # It includes the first wall, blanket and shield, but excludes the breeder and multiplier materials.
+ # This cost includes only manufacturing - not R&D, transport,
+ # or assembly in the reactor.
+ # It includes the first wall, blanket and shield, but excludes the breeder
+ # and multiplier materials.
self.data.costs_2015.s_cref[25] = 317.0e6
# Scale with steel mass in blanket + shield mass
self.data.costs_2015.s_k[25] = (
@@ -264,7 +266,8 @@ def output(self):
"""
po.oheadr(
self.outfile,
- 'Estimate of "overnight" capital cost for a first of kind power plant (2014 M$)',
+ 'Estimate of "overnight" capital cost for a first of kind power plant '
+ "(2014 M$)",
)
po.oshead(self.outfile, "Buildings (M$)")
@@ -1039,9 +1042,11 @@ def calc_remaining_subsystems(self):
self.data.costs_2015.s_label[51] = "Electrical power supply and distribution"
# Cost of ITER electrical power supply and distribution
self.data.costs_2015.s_cref[51] = 1188.0e6
- # Scale with total magnetic energy in the poloidal field / resistive diffusion time (W)
+ # Scale with total magnetic energy in the
+ # poloidal field / resistive diffusion time (W)
# For ITER value see
- # K:\Power Plant Physics and Technology\PROCESS\PROCESS documentation papers\resistive diffusion time.xmcd or pdf
+ # K:\Power Plant Physics and Technology\PROCESS\
+ # PROCESS documentation papers\resistive diffusion time.xmcd or pdf
self.data.costs_2015.s_k[51] = (
self.data.pf_power.ensxpfm * 1.0e6 / self.data.physics.t_plasma_res_diffusion
)
diff --git a/process/models/cryostat.py b/process/models/cryostat.py
index 611517afb1..edc6aaec4a 100644
--- a/process/models/cryostat.py
+++ b/process/models/cryostat.py
@@ -12,7 +12,8 @@ def __init__(self):
def run(self):
"""Run the cryostat calculations.
- This method runs the cryostat calculations, including the calculation of the cryostat geometry.
+ This method runs the cryostat calculations,
+ including the calculation of the cryostat geometry.
"""
# Calculate cryostat geometry
self.external_cryo_geometry()
@@ -20,10 +21,14 @@ def run(self):
def external_cryo_geometry(self):
"""Calculate cryostat geometry.
- This method calculates the geometry of the cryostat, including the inboard radius,
- the vertical clearance between the uppermost PF coil and the cryostat lid, the half-height
- of the cryostat, the vertical clearance between the TF coil and the cryostat, the cryostat volume,
- the vacuum vessel mass, and the sum of internal vacuum vessel and cryostat masses.
+ This method calculates the geometry of the cryostat, i
+ ncluding the inboard radius,
+ the vertical clearance between the uppermost PF coil and the cryostat lid,
+ the half-height of the cryostat,
+ the vertical clearance between the TF coil and the cryostat,
+ the cryostat volume,
+ the vacuum vessel mass,
+ and the sum of internal vacuum vessel and cryostat masses.
"""
# Cryostat radius [m]
# Take radius of furthest PF coil and add clearance
@@ -59,7 +64,8 @@ def external_cryo_geometry(self):
)
# Cryostat structure volume [m^3]
- # Calculate by taking the volume of the outer cryostat and subtracting the volume of the inner cryostat
+ # Calculate by taking the volume of the outer cryostat
+ # and subtracting the volume of the inner cryostat
self.data.fwbs.vol_cryostat = (
(
np.pi
diff --git a/process/models/cs_fatigue.py b/process/models/cs_fatigue.py
index a4de377778..5ef510cee4 100644
--- a/process/models/cs_fatigue.py
+++ b/process/models/cs_fatigue.py
@@ -75,7 +75,8 @@ def ncycle(
k_max = 0.0
# factor 2 taken as saftey factors in the crack sizes
- # Default CS steel undergoes fast fracture when SIF > 200 MPa, under a saftey factor 1.5 we use 133MPa
+ # Default CS steel undergoes fast fracture when SIF > 200 MPa,
+ # under a saftey factor 1.5 we use 133MPa
pi_2_arr = np.array([np.pi / 2.0e0, 0])
while (
(a <= dz_cs_turn_conduit / self.data.cs_fatigue.sf_vertical_crack)
@@ -111,19 +112,21 @@ def ncycle(
@staticmethod
@njit(cache=True)
def embedded_stress_intensity_factor(hoop_stress, t, w, a, c, phi):
- # ! Assumes an embedded elliptical efect geometry
- # ! geometric quantities
- # ! hoop_stress - change in hoop stress over cycle
- # ! t - plate thickness
- # ! w - plate width
- # ! a - crack depth (t -direction)
- # ! c - crack length (w - direction)
- # ! Ref: J. C. Newman, I. S. Raju "Stress-Intensity Factor Equations for Cracks in
- # ! Three-Dimensional Finite Bodies Subjected to Tension and Bending Loads"
- # ! https://core.ac.uk/download/pdf/42849129.pdf
- # ! Ref: C. Jong, Magnet Structural Design
- # ! Criteria Part 1: Main Structural Components and Welds 2012
-
+ """
+ Assumes an embedded elliptical efect geometry
+
+ geometric quantities
+ hoop_stress - change in hoop stress over cycle
+ t - plate thickness
+ w - plate width
+ a - crack depth (t -direction)
+ c - crack length (w - direction)
+ Ref: J. C. Newman, I. S. Raju "Stress-Intensity Factor Equations for Cracks in
+ Three-Dimensional Finite Bodies Subjected to Tension and Bending Loads"
+ https://core.ac.uk/download/pdf/42849129.pdf
+ Ref: C. Jong, Magnet Structural Design
+ Criteria Part 1: Main Structural Components and Welds 2012
+ """
# reuse of calc
a_c = a / c
a_t = a / t
@@ -171,19 +174,21 @@ def embedded_stress_intensity_factor(hoop_stress, t, w, a, c, phi):
@staticmethod
@njit(cache=True)
def surface_stress_intensity_factor(hoop_stress, t, w, a, c, phi):
- # ! Assumes an surface semi elliptical defect geometry
- # ! geometric quantities
- # ! hoop_stress - change in hoop stress over cycle
- # ! t - plate thickness
- # ! w - plate width
- # ! a - crack depth (t -direction)
- # ! c - crack length (w - direction)
- # ! Ref: J. C. Newman, I. S. Raju "Stress-Intensity Factor Equations for Cracks in
- # ! Three-Dimensional Finite Bodies Subjected to Tension and Bending Loads"
- # ! https://core.ac.uk/download/pdf/42849129.pdf
- # ! Ref: C. Jong, Magnet Structural Design
- # ! Criteria Part 1: Main Structural Components and Welds 2012
-
+ """
+ Assumes an surface semi elliptical defect geometry
+
+ geometric quantities
+ hoop_stress - change in hoop stress over cycle
+ t - plate thickness
+ w - plate width
+ a - crack depth (t -direction)
+ c - crack length (w - direction)
+ Ref: J. C. Newman, I. S. Raju "Stress-Intensity Factor Equations for Cracks in
+ Three-Dimensional Finite Bodies Subjected to Tension and Bending Loads"
+ https://core.ac.uk/download/pdf/42849129.pdf
+ Ref: C. Jong, Magnet Structural Design
+ Criteria Part 1: Main Structural Components and Welds 2012
+ """
bending_stress = 0.0e0 # * 3.0 * M / (w*d**2.0)
# reuse of calc
diff --git a/process/models/divertor.py b/process/models/divertor.py
index 4b20d8726c..15b77f315f 100644
--- a/process/models/divertor.py
+++ b/process/models/divertor.py
@@ -153,11 +153,16 @@ def divtart(
References
----------
- - Y.-K. M. Peng, J. B. Hicks, AEA Fusion, Culham (UK), "Engineering feasibility of tight aspect ratio Tokamak (spherical torus) reactors".
+ - Y.-K. M. Peng, J. B. Hicks, AEA Fusion, Culham (UK),
+ "Engineering feasibility of tight aspect ratio Tokamak (spherical torus)
+ reactors".
1990. https://inis.iaea.org/records/ey2rf-dah04
- - Y.-K. M. Peng, J. B. Hicks, “Engineering feasibility of tight aspect ratio tokamak (spherical torus) reactors,”
- Osti.gov, 1991. https://www.osti.gov/biblio/1022679 (accessed Mar. 24, 2025).
+ - Y.-K. M. Peng, J. B. Hicks,
+ “Engineering feasibility of tight aspect ratio tokamak (spherical torus)
+ reactors,”
+ Osti.gov, 1991. https://www.osti.gov/biblio/1022679
+ (accessed Mar. 24, 2025).
"""
# Thickness of centrepost + first wall at divertor height
@@ -258,8 +263,10 @@ def divwade(
This subroutine calculates the divertor heat flux for any machine,
with either a single null or double null configuration.
- It uses the Eich scaling (Eich et al. 2013) and spreading factor (Scarabosio et al. 2014)
- to calculate the SOL width. This is then used with a flux expansion factor to calculate
+ It uses the Eich scaling (Eich et al. 2013) and spreading factor
+ (Scarabosio et al. 2014)
+ to calculate the SOL width.
+ This is then used with a flux expansion factor to calculate
the wetted area and then the heat flux.
Parameters
@@ -340,7 +347,8 @@ def divwade(
# Divertor heat load
hldiv_base = p_plasma_separatrix_mw * (1 - rad_fraction_sol) / area_wetted
- # For double null, calculate heat loads to upper and lower divertors and use the highest
+ # For double null, calculate heat loads to upper and lower divertors
+ # and use the highest
if self.data.divertor.n_divertors == 2:
hldiv_lower = f_p_div_lower * hldiv_base
hldiv_upper = (1.0 - f_p_div_lower) * hldiv_base
diff --git a/process/models/engineering/ivc_functions.py b/process/models/engineering/ivc_functions.py
index b5aafc1913..01aa62f09f 100644
--- a/process/models/engineering/ivc_functions.py
+++ b/process/models/engineering/ivc_functions.py
@@ -39,7 +39,8 @@ def pumping_powers_as_fractions(
p_div_nuclear_heat_total_mw: float,
p_div_rad_total_mw: float,
) -> tuple[float, float, float, float]:
- """Calculate mechanical pumping powers as fractions of thermal power in each component.
+ """Calculate mechanical pumping powers as fractions of thermal power in each
+ component.
Parameters
----------
@@ -132,10 +133,12 @@ def eshellarea(rshell, rmini, rmino, zminor):
def dshellarea(
rmajor: float, rminor: float, zminor: float
) -> tuple[float, float, float]:
- """Calculate the inboard, outboard, and total surface areas of a D-shaped toroidal shell.
+ """Calculate the inboard, outboard, and total surface areas of a D-shaped toroidal
+ shell.
The inboard section is assumed to be a cylinder.
- The outboard section is defined by a semi-ellipse, centred on the major radius of the inboard section.
+ The outboard section is defined by a semi-ellipse,
+ centred on the major radius of the inboard section.
Parameters
----------
diff --git a/process/models/fw.py b/process/models/fw.py
index 4eb36a8a1d..68121fd33f 100644
--- a/process/models/fw.py
+++ b/process/models/fw.py
@@ -323,7 +323,8 @@ def apply_first_wall_coverage_factors(
if a_fw_outboard <= 0.0e0:
raise ProcessValueError(
- "fhole+f_ster_div_single+f_a_fw_outboard_hcd is too high for a credible outboard wall area",
+ "fhole+f_ster_div_single+f_a_fw_outboard_hcd is too high "
+ "for a credible outboard wall area",
f_ster_div_single=f_ster_div_single,
f_a_fw_outboard_hcd=f_a_fw_outboard_hcd,
)
@@ -367,16 +368,27 @@ def fw_temp(
Returns
-------
- tuple
+ :
+ Notes
+ -----
Detailed thermal hydraulic model for the blanket (first wall + breeding zone).
Given the heating incident on the first wall, and the coolant outlet temperature,
- the maximum temperature of the first wall is calculated to check it is below material limits.
+ the maximum temperature of the first wall is calculated to check it is below
+ material limits.
The routine is called separately for the inboard and outboard sides.
The calculation of the maximum temperature is described by Gardner:
- "Temperature distribution in the first wall", K:\\Power Plant Physics and Technology\\ PROCESS\\PROCESS References & Systems Codes\\Pulsed option - Gardner.
- This is in turn taken from "Methods of First Wall Structural Analysis with Application to the Long Pulse Commercial Tokamak Reactor Design", R.J. LeClaire, MIT, PFC/RR-84-9.
- Contains peak first wall temperature (K), coolant specific heat capacity at constant pressure (J/kg/K),
+ "Temperature distribution in the first wall",
+
+ K:\\Power Plant Physics and Technology\\ PROCESS\\
+ PROCESS References & Systems Codes\\Pulsed option - Gardner.
+
+ This is in turn taken from "Methods of First Wall Structural Analysis with
+ Application to the Long Pulse Commercial Tokamak Reactor Design", R.J. LeClaire,
+ MIT, PFC/RR-84-9.
+
+ Contains peak first wall temperature (K), coolant specific heat capacity
+ at constant pressure (J/kg/K),
"""
# First wall volume (inboard or outboard depending on arguments) (m^3)
vol_fw = a_fw * dr_fw
@@ -384,7 +396,8 @@ def fw_temp(
# First wall channel area (m^2)
a_fw_channel = np.pi * radius_fw_channel**2
- # Heat generation in the first wall due to neutron flux deposited in the material (W/m3)
+ # Heat generation in the first wall due to neutron flux
+ # deposited in the material (W/m3)
pden_fw_nuclear = 1e6 * pnuc_deposited / vol_fw
# the nuclear heating in the coolant is small. (W/m2)
@@ -442,7 +455,8 @@ def fw_temp(
# Coolant velocity (m/s)
vel_fw_coolant_average = mflux_fw_coolant / outlet_coolant_properties.density
- # Mean temperature of the wall material on the plasma side of the coolant 'temp_fw_peak'
+ # Mean temperature of the wall material on the plasma side of the coolant
+ # 'temp_fw_peak'
# is the estimate from the previous iteration of the wall surface temperature
# (underneath the armour)
temp_k = (self.data.fwbs.temp_fw_coolant_out + self.data.fwbs.temp_fw_peak) / 2
@@ -481,7 +495,8 @@ def fw_temp(
# Model B: Simple 1-dimensional calculation !
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- # This is optimistic as it neglects the higher temperature midway between the channels.
+ # This is optimistic as it neglects the higher temperature midway between the
+ # channels.
# I have included 1/4 of the volume load:
# 1/2 is absorbed in the plasma-facing wall (A)
# which on average has to pass through 1/2 the wall thickness.
@@ -654,7 +669,8 @@ def calculate_total_fw_channels(
len_fw_channel: float,
dx_fw_module: float,
) -> tuple[int, int]:
- """Calculate the total number of first wall channels for inboard and outboard sections.
+ """Calculate the total number of first wall channels for inboard and outboard
+ sections.
Parameters
----------
diff --git a/process/models/geometry/blanket.py b/process/models/geometry/blanket.py
index 51440b2388..0732a901d8 100644
--- a/process/models/geometry/blanket.py
+++ b/process/models/geometry/blanket.py
@@ -22,7 +22,8 @@ def blanket_geometry_single_null(
dr_blkt_inboard: float,
dr_blkt_outboard: float,
) -> ArbitraryGeometry:
- """Calculates radial and vertical distances for the geometry of the blanket in a single null configuration
+ """Calculates radial and vertical distances for the geometry of the blanket in a
+ single null configuration
Parameters
----------
@@ -111,7 +112,8 @@ def blanket_geometry_lower(
dr_blkt_outboard: float,
divgap: float,
) -> tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]:
- """Calculates radial and vertical distances for the geometry of section of blanket below the midplane
+ """Calculates radial and vertical distances for the geometry of section of blanket
+ below the midplane
Parameters
----------
@@ -133,7 +135,10 @@ def blanket_geometry_lower(
Returns
-------
:
- tuple containing the R coordinates for the outboard, Z coordinates for the outboard, R coordinates for the inboard, Z coordinates for the inboard of the blanket geometry below the midplane
+ tuple containing the R coordinates for the outboard,
+ Z coordinates for the outboard,
+ R coordinates for the inboard,
+ Z coordinates for the inboard of the blanket geometry below the midplane
"""
# Lower blanket
rs1, rs2, rs3, rs4, zs1, zs2, zs3, zs4 = dhgap_vertices(
@@ -164,8 +169,10 @@ def blanket_geometry_double_null(
dr_blkt_inboard: float,
dr_blkt_outboard: float,
) -> ArbitraryGeometry:
- """Calculates radial and vertical distances for the geometry of blanket in a double null configuration
- In a double null configuration, the geometry of the lower blanket is reflected across the midplane to create the section of blanket above the midplane
+ """Calculates radial and vertical distances for the geometry of blanket in a double
+ null configuration
+ In a double null configuration, the geometry of the lower blanket is reflected across
+ the midplane to create the section of blanket above the midplane
Parameters
----------
diff --git a/process/models/geometry/firstwall.py b/process/models/geometry/firstwall.py
index 31f25f141e..65759c0be6 100644
--- a/process/models/geometry/firstwall.py
+++ b/process/models/geometry/firstwall.py
@@ -23,7 +23,8 @@ def first_wall_geometry_single_null(
dr_fw_outboard: float,
tfwvt: float,
) -> ArbitraryGeometry:
- """Calculates radial and vertical distances for the geometry of first wall in a single null configuration
+ """Calculates radial and vertical distances for the geometry of first wall in a
+ single null configuration
Parameters
----------
@@ -113,7 +114,8 @@ def first_wall_geometry_lower(
tfwvt: float,
top_point: float,
) -> tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]:
- """Calculates radial and vertical distances for the geometry of section of first wall below the midplane
+ """Calculates radial and vertical distances for the geometry of section of first wall
+ below the midplane
Parameters
----------
@@ -135,8 +137,10 @@ def first_wall_geometry_lower(
Returns
-------
:
- tuple containing the R coordinates for the outboard, Z coordinates for the outboard,
- R coordinates for the inboard, Z coordinates for the inboard of the first wall geometry below the midplane
+ tuple containing the R coordinates for the outboard,
+ Z coordinates for the outboard,
+ R coordinates for the inboard,
+ Z coordinates for the inboard of the first wall geometry below the midplane
"""
# Lower first wall
rs1, rs2, rs3, rs4, zs1, zs2, zs3, zs4 = dhgap_vertices(
@@ -168,8 +172,10 @@ def first_wall_geometry_double_null(
dr_fw_outboard: float,
tfwvt: float,
) -> ArbitraryGeometry:
- """Calculates radial and vertical distances for the geometry of first wall in a double null configuration
- In a double null configuration, the geometry of the lower first wall is reflected across the midplane to create the section of first wall above the midplane
+ """Calculates radial and vertical distances for the geometry of first wall in a
+ double null configuration
+ In a double null configuration, the geometry of the lower first wall is reflected
+ across the midplane to create the section of first wall above the midplane
Parameters
----------
diff --git a/process/models/geometry/parameterisations.py b/process/models/geometry/parameterisations.py
index 39592832c7..79b1d171c0 100644
--- a/process/models/geometry/parameterisations.py
+++ b/process/models/geometry/parameterisations.py
@@ -1,5 +1,6 @@
"""
-Module to hold geometry parameterisation dataclasses common to multiple reactor components
+Module to hold geometry parameterisation dataclasses common to multiple reactor
+components
"""
from dataclasses import dataclass
@@ -25,7 +26,8 @@ class RectangleGeometry:
class ArbitraryGeometry:
"""Holds radial and vertical coordinates for arbitrary reactor component shapes
- Example: a triangular shaped component with vertices [(0,0), (1,0), (0,1)] would be represented by ArbitraryGeometry(rs=[0,1,0], zs=[0,0,1])
+ Example: a triangular shaped component with vertices [(0,0), (1,0), (0,1)]
+ would be represented by ArbitraryGeometry(rs=[0,1,0], zs=[0,0,1])
"""
rs: np.ndarray
diff --git a/process/models/geometry/pfcoil.py b/process/models/geometry/pfcoil.py
index f6298eebed..1d6bf76a42 100644
--- a/process/models/geometry/pfcoil.py
+++ b/process/models/geometry/pfcoil.py
@@ -1,5 +1,6 @@
"""
-Calculate radial and vertical coordinates for the geometry of the pf coils and central coil
+Calculate radial and vertical coordinates for the geometry of the pf coils and
+central coil
"""
import numpy as np
@@ -16,7 +17,8 @@ def pfcoil_geometry(
dr_cs: float,
ohdz: float,
) -> tuple[np.ndarray, np.ndarray, RectangleGeometry]:
- """Calculates radial and vertical distances for the geometry of the pf coils and central coil
+ """Calculates radial and vertical distances for the geometry of the pf coils and
+ central coil
Parameters
----------
@@ -38,7 +40,9 @@ def pfcoil_geometry(
Returns
-------
:
- tuple containing radial and vertical coordinates for pf coils, and dataclass returning coordinates representing a rectangular geometry used to plot the central coil
+ tuple containing radial and vertical coordinates for pf coils, and dataclass
+ returning coordinates representing a rectangular geometry
+ used to plot the central coil
"""
r_points = []
z_points = []
diff --git a/process/models/geometry/plasma.py b/process/models/geometry/plasma.py
index d322b85787..cd8c3f8f1d 100644
--- a/process/models/geometry/plasma.py
+++ b/process/models/geometry/plasma.py
@@ -1,5 +1,6 @@
"""
-Calculate plasma elongation and radial and vertical coordinates for the geometry of the plasma
+Calculate plasma elongation and radial and vertical coordinates for the geometry
+of the plasma
"""
import math
@@ -32,11 +33,14 @@ def plasma_geometry(
i_plasma_shape: int,
square: float,
) -> PlasmaGeometry:
- """Calculates radial and vertical distances and plasma elongation for the geometry of the plasma.
+ """Calculates radial and vertical distances and plasma elongation for the geometry
+ of the plasma.
- This function computes the radial and vertical coordinates of the plasma boundary, as well as the plasma elongation,
- based on the given major radius, minor radius, triangularity, and elongation at 95% of the plasma surface. It also
- considers whether the plasma configuration is single null or double null.
+ This function computes the radial and vertical coordinates of the plasma boundary,
+ as well as the plasma elongation,
+ based on the given major radius, minor radius, triangularity, and elongation at 95%
+ of the plasma surface.
+ It also considers whether the plasma configuration is single null or double null.
Parameters
----------
@@ -57,8 +61,9 @@ def plasma_geometry(
Returns
-------
- PlasmaGeometry
- A dataclass containing the plasma elongation and the radial and vertical coordinates of the plasma.
+ :
+ A dataclass containing the plasma elongation and the radial and vertical
+ coordinates of the plasma.
"""
# Original PROCESS double arc plasma shape
if i_plasma_shape == PlasmaShapeModelType.PROCESS_ORIGINAL:
diff --git a/process/models/geometry/shield.py b/process/models/geometry/shield.py
index f515bebebd..f6bec83ab3 100644
--- a/process/models/geometry/shield.py
+++ b/process/models/geometry/shield.py
@@ -17,7 +17,8 @@ def shield_geometry_single_null(
triang: float,
cumulative_lower: dict,
) -> ArbitraryGeometry:
- """Calculates radial and vertical distances for the geometry of shield in a single null configuration
+ """Calculates radial and vertical distances for the geometry of shield in a single
+ null configuration
Parameters
----------
@@ -89,7 +90,8 @@ def shield_geometry_lower(
rminx_near: float,
triang: float,
) -> tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]:
- """Calculates radial and vertical distances for the geometry of section of shield below the midplane
+ """Calculates radial and vertical distances for the geometry of section of shield
+ below the midplane
Parameters
----------
@@ -108,8 +110,11 @@ def shield_geometry_lower(
Returns
-------
- Tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]
- tuple containing the R coordinates for the outboard, Z coordinates for the outboard, R coordinates for the inboard, Z coordinates for the inboard of the shield geometry below the midplane
+ :
+ tuple containing the R coordinates for the outboard,
+ Z coordinates for the outboard,
+ R coordinates for the inboard,
+ Z coordinates for the inboard of the shield geometry below the midplane
"""
# Side furthest from plasma
kapx = cumulative_lower["dz_shld_lower"] / rminx_far
@@ -130,8 +135,10 @@ def shield_geometry_double_null(
rminx_near: float,
triang: float,
) -> ArbitraryGeometry:
- """Calculates radial and vertical distances for the geometry of shield in a double null configuration
- In a double null configuration, the geometry of the lower shield is reflected across the midplane to create the section of shield above the midplane
+ """Calculates radial and vertical distances for the geometry of shield in a double
+ null configuration
+ In a double null configuration, the geometry of the lower shield is reflected across
+ the midplane to create the section of shield above the midplane
Parameters
----------
@@ -150,7 +157,7 @@ def shield_geometry_double_null(
Returns
-------
- ArbitraryGeometry
+ :
dataclass returning radial and vertical coordinates
"""
# Lower shield
diff --git a/process/models/geometry/tfcoil.py b/process/models/geometry/tfcoil.py
index af1779e192..18347a2ba9 100644
--- a/process/models/geometry/tfcoil.py
+++ b/process/models/geometry/tfcoil.py
@@ -20,7 +20,8 @@ def tfcoil_geometry_rectangular_shape(
*,
offset_in: float = 0.0,
) -> list[RectangleGeometry]:
- """Calculates rectangular geometries for tf coils in a picture frame/rectangular shape parametrization
+ """Calculates rectangular geometries for tf coils in a picture frame/rectangular
+ shape parametrization
Parameters
----------
@@ -96,7 +97,8 @@ def tfcoil_geometry_d_shape(
*,
offset_in: float = 0.0,
) -> tuple[list[RectangleGeometry], list[list[tuple[float, float]]]]:
- """Calculates radial and vertical distances for the geometry of the tf coils in a D-shape parametrization
+ """Calculates radial and vertical distances for the geometry of the tf coils in a
+ D-shape parametrization
Parameters
----------
diff --git a/process/models/geometry/utils.py b/process/models/geometry/utils.py
index 5fd3177e4c..8f0918e1ff 100644
--- a/process/models/geometry/utils.py
+++ b/process/models/geometry/utils.py
@@ -1,5 +1,6 @@
"""
-Module to hold plotting functions, used in plot_summary, which are common to multiple reactor components
+Module to hold plotting functions, used in plot_summary, which are common to multiple
+reactor components
"""
import numpy as np
@@ -8,7 +9,8 @@
def dh_vertices(
r0: float, a: float, triang: float, kap: float
) -> tuple[np.ndarray, np.ndarray]:
- """Returns the radial and vertical coordinates which, when plotted, plots half a thin D-section, centred on z = 0
+ """Returns the radial and vertical coordinates which, when plotted, plots half a
+ thin D-section, centred on z = 0
Parameters
----------
@@ -24,7 +26,8 @@ def dh_vertices(
Returns
-------
:
- tuple containing radial and vertical coordinates which, when plotted, plots a half thin D-section with a gap
+ tuple containing radial and vertical coordinates which, when plotted,
+ plots a half thin D-section with a gap
"""
angs = np.linspace(0, np.pi, 50, endpoint=True)
rs = r0 + a * np.cos(angs + triang * np.sin(1.0 * angs))
@@ -50,7 +53,8 @@ def dhgap_vertices(
np.ndarray,
np.ndarray,
]:
- """Returns the radial and vertical coordinates which, when plotted, plots a half thick D-section with a gap
+ """Returns the radial and vertical coordinates which, when plotted,
+ plots a half thick D-section with a gap
Parameters
----------
@@ -72,7 +76,8 @@ def dhgap_vertices(
Returns
-------
:
- tuple containing radial and vertical coordinates which, when plotted, plots a half thick D-section with a gap
+ tuple containing radial and vertical coordinates which, when plotted,
+ plots a half thick D-section with a gap
"""
arc = np.pi / 4.0
r01 = (inpt + outpt) / 2.0
@@ -105,7 +110,8 @@ def ellips_fill_vertices(
ang1: float = 0,
ang2: float = np.pi / 2,
) -> list[tuple[float, float]]:
- """Returns the vertices of a shape which, when filled, fills the space between two concentric ellipse sectors
+ """Returns the vertices of a shape which, when filled, fills the space between
+ two concentric ellipse sectors
Parameters
----------
@@ -129,7 +135,8 @@ def ellips_fill_vertices(
Returns
-------
:
- list containing (R,Z) coordinates which, when plotted, fill space between ellipses
+ list containing (R,Z) coordinates which, when plotted,
+ fill space between ellipses
"""
angs = np.linspace(ang1, ang2, endpoint=True)
r1 = ((np.cos(angs) / a1) ** 2 + (np.sin(angs) / b1) ** 2) ** (-0.5)
diff --git a/process/models/geometry/vacuum_vessel.py b/process/models/geometry/vacuum_vessel.py
index 500dae9504..9c713e7297 100644
--- a/process/models/geometry/vacuum_vessel.py
+++ b/process/models/geometry/vacuum_vessel.py
@@ -19,7 +19,8 @@ def vacuum_vessel_geometry_single_null(
cumulative_lower: dict,
lower: dict,
) -> ArbitraryGeometry:
- """Calculates radial and vertical distances for the geometry of the vacuum vessel in a single null configuration
+ """Calculates radial and vertical distances for the geometry of the vacuum vessel in
+ a single null configuration
Parameters
----------
@@ -103,7 +104,8 @@ def vacuum_vessel_geometry_lower(
radx_inner: float,
rminx_inner: float,
) -> tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]:
- """Calculates radial and vertical distances for the geometry of section of vacuum vessel below the midplane
+ """Calculates radial and vertical distances for the geometry of section of
+ vacuum vessel below the midplane
Parameters
----------
@@ -125,7 +127,10 @@ def vacuum_vessel_geometry_lower(
Returns
-------
:
- tuple containing the R coordinates for the outboard, Z coordinates for the outboard, R coordinates for the inboard, Z coordinates for the inboard of the vacuum vessel geometry below the midplane
+ tuple containing the R coordinates for the outboard,
+ Z coordinates for the outboard,
+ R coordinates for the inboard,
+ Z coordinates for the inboard of the vacuum vessel geometry below the midplane
"""
kapx = cumulative_lower["dz_vv_lower"] / rminx_outer
rs_lower_outboard, zs_lower_outboard = dh_vertices(
@@ -151,8 +156,10 @@ def vacuum_vessel_geometry_double_null(
radx_inner: float,
rminx_inner: float,
) -> ArbitraryGeometry:
- """Calculates radial and vertical distances for the geometry of vacuum vessel in a double null configuration
- In a double null configuration, the geometry of the lower vacuum vessel is reflected across the midplane to create the section of vacuum vessel above the midplane
+ """Calculates radial and vertical distances for the geometry of vacuum vessel in a
+ double null configuration
+ In a double null configuration, the geometry of the lower vacuum vessel is reflected
+ across the midplane to create the section of vacuum vessel above the midplane
Parameters
----------
diff --git a/process/models/pfcoil.py b/process/models/pfcoil.py
index ed51fcc3fd..fc0cd99df6 100644
--- a/process/models/pfcoil.py
+++ b/process/models/pfcoil.py
@@ -229,7 +229,8 @@ def pfcoil(self):
nfixmx=NFIXMX,
)
- # Symmetric up/down Central Solenoid : Find (R,Z) and current of each filament at BOP
+ # Symmetric up/down Central Solenoid :
+ # Find (R,Z) and current of each filament at BOP
(
self.data.pf_coil.r_pf_cs_current_filaments,
@@ -280,8 +281,6 @@ def pfcoil(self):
z_pf_coil_middle_group_array[group, coil]
)
- # =========================================================================
-
elif self.data.pf_coil.i_pf_location[group] == PFLocationTypes.ABOVE_TF:
# PF coil is on top of the TF coil
(
@@ -311,7 +310,6 @@ def pfcoil(self):
self.data.pf_coil.z_pf_coil_middle_group_array[group, coil] = (
z_pf_coil_middle_group_array[group, coil]
)
- # =========================================================================
elif self.data.pf_coil.i_pf_location[group] == PFLocationTypes.OUTSIDE_TF:
# PF coil is radially outside the TF coil
@@ -336,8 +334,6 @@ def pfcoil(self):
z_pf_coil_middle_group_array[group, coil]
)
- # =========================================================================
-
elif (
self.data.pf_coil.i_pf_location[group]
== PFLocationTypes.GENERALLY_PLACED
@@ -368,7 +364,6 @@ def pfcoil(self):
group=group,
i_pf_location=self.data.pf_coil.i_pf_location[group],
)
- # =========================================================================
# Allocate current to the PF coils:
# "Flux swing coils" participate in cancellation of the CS
@@ -483,8 +478,8 @@ def pfcoil(self):
"i_pf_location(i) should not be 1 if iohcl=0"
)
# PF coil is stacked on top of the Central Solenoid
- # This coil is to balance Central Solenoid flux and should not be involved
- # in equilibrium calculation -- RK 07/12
+ # This coil is to balance Central Solenoid flux and should
+ # not be involved in equilibrium calculation -- RK 07/12
self.data.pf_coil.ccls[i] = 0.0e0
nfxf0 += self.data.pf_coil.n_pf_coils_in_group[i]
for ccount in range(self.data.pf_coil.n_pf_coils_in_group[i]):
@@ -575,7 +570,7 @@ def pfcoil(self):
zpts[0] = 0.0e0
brin[0] = 0.0e0
- # Added self.data.physics.ind_plasma_internal_norm term correctly -- RK 07/12
+ # Added physics.ind_plasma_internal_norm term correctly -- RK 07/12
bzin[0] = (
-1.0e-7
@@ -617,8 +612,8 @@ def pfcoil(self):
# Flux swing from vertical field
# If this is the first visit to the routine the inductance matrix
- # ind_pf_cs_plasma_mutual and the turns array have not yet been calculated, so we set
- # them to (very) approximate values to avoid strange behaviour...
+ # ind_pf_cs_plasma_mutual and the turns array have not yet been calculated,
+ # so we set them to (very) approximate values to avoid strange behaviour...
if self.data.pf_coil.first_call:
self.data.pf_coil.ind_pf_cs_plasma_mutual[:, :] = 1.0e0
self.data.pf_coil.n_pf_coil_turns[:] = 100.0e0
@@ -644,8 +639,10 @@ def pfcoil(self):
# Required current change in CS coil
# Proposed new calculation...
- # dics = csflux / ind_pf_cs_plasma_mutual(n_cs_pf_coils,n_pf_cs_plasma_circuits)
- # BUT... ind_pf_cs_plasma_mutual(n_cs_pf_coils,n_pf_cs_plasma_circuits) is around 2000 times ddics below...
+ # dics = csflux / ind_pf_cs_plasma_mutual
+ # (n_cs_pf_coils,n_pf_cs_plasma_circuits)
+ # BUT... ind_pf_cs_plasma_mutual(n_cs_pf_coils,n_pf_cs_plasma_circuits)
+ # is around 2000 times ddics below...
ddics = (
4.0e-7
@@ -667,7 +664,8 @@ def pfcoil(self):
if np.abs(self.data.pf_coil.f_j_cs_start_end_flat_top) > 1.0:
logger.warning(
"Ratio of central solenoid overall current density at "
- "beginning of flat-top / end of flat-top > 1 (|f_j_cs_start_end_flat_top| > 1)"
+ "beginning of flat-top / end of flat-top > 1 "
+ "(|f_j_cs_start_end_flat_top| > 1)"
)
else:
dics = 0.0e0
@@ -688,12 +686,13 @@ def pfcoil(self):
# Currents at different times:
# If PF coil currents are computed, not input via ccl0_ma, ccls_ma:
- # Then set ccl0_ma,ccls_ma from the computed self.data.pf_coil.ccl0,self.data.pf_coil.ccls
+ # Then set ccl0_ma,ccls_ma from the computed pf_coil.ccl0, pf_coil.ccls
if self.data.pf_coil.i_pf_current != 0:
self.data.pf_coil.ccl0_ma[nng] = 1.0e-6 * self.data.pf_coil.ccl0[nng]
self.data.pf_coil.ccls_ma[nng] = 1.0e-6 * self.data.pf_coil.ccls[nng]
else:
- # Otherwise set self.data.pf_coil.ccl0,self.data.pf_coil.ccls via the input ccl0_ma and ccls_ma
+ # Otherwise set self.data.pf_coil.ccl0,self.data.pf_coil.ccls via
+ # the input ccl0_ma and ccls_ma
self.data.pf_coil.ccl0[nng] = 1.0e6 * self.data.pf_coil.ccl0_ma[nng]
self.data.pf_coil.ccls[nng] = 1.0e6 * self.data.pf_coil.ccls_ma[nng]
@@ -702,7 +701,9 @@ def pfcoil(self):
1.0e-6 * self.data.pf_coil.ccl0[nng]
)
- # Beginning of flat-top: t = self.data.times.t_plant_pulse_coil_precharge+self.data.times.t_plant_pulse_plasma_current_ramp_up
+ # Beginning of flat-top:
+ # t = times.t_plant_pulse_coil_precharge
+ # + times.t_plant_pulse_plasma_current_ramp_up
self.data.pf_coil.c_pf_cs_coil_flat_top_ma[ncl] = 1.0e-6 * (
self.data.pf_coil.ccls[nng]
- (
@@ -712,7 +713,10 @@ def pfcoil(self):
)
)
- # End of flat-top: t = self.data.times.t_plant_pulse_coil_precharge+self.data.times.t_plant_pulse_plasma_current_ramp_up+self.data.times.t_plant_pulse_fusion_ramp+self.data.times.t_plant_pulse_burn
+ # End of flat-top:
+ # t = times.t_plant_pulse_coil_precharge
+ # +times.t_plant_pulse_plasma_current_ramp_up
+ # +times.t_plant_pulse_fusion_ramp+times.t_plant_pulse_burn
self.data.pf_coil.c_pf_cs_coil_pulse_end_ma[ncl] = 1.0e-6 * (
self.data.pf_coil.ccls[nng]
- (
@@ -802,8 +806,8 @@ def pfcoil(self):
)
else:
- # Other coils. N.B. Current density j_pf_coil_wp_peak[i] is defined in
- # routine INITIAL for these coils.
+ # Other coils. N.B. Current density j_pf_coil_wp_peak[i] is defined
+ # in routine INITIAL for these coils.
area = (
abs(
self.data.pf_coil.c_pf_cs_coils_peak_ma[i]
@@ -874,7 +878,8 @@ def pfcoil(self):
) # returns b_pf_coil_peak, bpf2
# Issue 1871. MDK
- # Allowable current density (for superconducting coils) for each coil, index i
+ # Allowable current density (for superconducting coils) for each coil,
+ # index i
if self.data.pf_coil.i_pf_conductor == PFConductorModel.SUPERCONDUCTING:
bmax = max(
abs(self.data.pf_coil.b_pf_coil_peak[i]),
@@ -1086,7 +1091,9 @@ def pfcoil(self):
self.data.pf_coil.n_pf_coil_turns[self.data.pf_coil.n_cs_pf_coils] = 1.0e0
# Generate coil currents as a function of time using
- # user-provided waveforms etc. (c_pf_coil_turn_peak_input, f_j_cs_start_pulse_end_flat_top, f_j_cs_start_end_flat_top)
+ # user-provided waveforms etc.
+ # (c_pf_coil_turn_peak_input, f_j_cs_start_pulse_end_flat_top,
+ # f_j_cs_start_end_flat_top)
for k in range(6): # time points
for i in range(self.data.pf_coil.n_pf_cs_plasma_circuits - 1):
self.data.pf_coil.c_pf_coil_turn[i, k] = (
@@ -1149,7 +1156,8 @@ def place_pf_above_cs(
Returns
-------
tuple[np.ndarray, np.ndarray]
- Tuple of arrays containing the radial and vertical coordinates of PF coils in the group.
+ Tuple of arrays containing the radial and vertical coordinates of PF coils
+ in the group.
"""
# Initialise as empty arrays; will be resized in the loop
r_pf_coil_middle_group_array = np.zeros((
@@ -1162,7 +1170,8 @@ def place_pf_above_cs(
))
for coil in range(n_pf_coils_in_group[n_pf_group]):
- # Positions PF coil directly above centre of CS with offset from dr_pf_cs_middle_offset
+ # Positions PF coil directly above centre of CS with offset from
+ # dr_pf_cs_middle_offset
r_pf_coil_middle_group_array[n_pf_group, coil] = (
r_cs_middle + dr_pf_cs_middle_offset
)
@@ -1194,7 +1203,8 @@ def place_pf_above_tf(
rpf2: float,
zref: np.ndarray,
) -> tuple[np.ndarray, np.ndarray, int]:
- """Calculates and places poloidal field (PF) coils above the toroidal field (TF) coils for a given group.
+ """Calculates and places poloidal field (PF) coils above the toroidal field (TF)
+ coils for a given group.
Parameters
----------
@@ -1228,8 +1238,8 @@ def place_pf_above_tf(
Returns
-------
tuple[np.ndarray, np.ndarray, int]
- Tuple containing arrays of radial and vertical positions of PF coil middles for the specified group,
- and the updated top_bottom indicator.
+ Tuple containing arrays of radial and vertical positions of PF coil middles
+ for the specified group, and the updated top_bottom indicator.
"""
# Initialise as empty arrays; will be resized in the loop
r_pf_coil_middle_group_array = np.zeros((
@@ -1274,7 +1284,8 @@ def place_pf_outside_tf(
i_r_pf_outside_tf_placement: int,
r_pf_outside_tf_midplane: float,
) -> tuple[np.ndarray, np.ndarray]:
- """Calculates the radial and vertical positions of poloidal field (PF) coils placed outside the toroidal field (TF) coil.
+ """Calculates the radial and vertical positions of poloidal field (PF) coils
+ placed outside the toroidal field (TF) coil.
Parameters
----------
@@ -1287,16 +1298,19 @@ def place_pf_outside_tf(
zref : np.ndarray
Reference vertical positions for each PF coil group.
i_tf_shape : int
- Integer flag indicating TF coil shape (2 for picture frame, others for D-shape).
+ Integer flag indicating TF coil shape
+ (2 for picture frame, others for D-shape).
i_r_pf_outside_tf_placement : int
- Placement switch for PF coil radius (1 for constant/stacked, 0 for following TF curve).
+ Placement switch for PF coil radius
+ (1 for constant/stacked, 0 for following TF curve).
r_pf_outside_tf_midplane : float
Radial position of PF coil at the midplane.
Returns
-------
tuple[np.ndarray, np.ndarray]
- Tuple containing arrays of radial and vertical positions of PF coil centers for the specified group.
+ Tuple containing arrays of radial and vertical positions of PF coil centers
+ for the specified group.
"""
# Initialise as empty arrays; will be resized in the loop
r_pf_coil_middle_group_array = np.zeros((
@@ -1316,7 +1330,8 @@ def place_pf_outside_tf(
z_pf_coil_middle_group_array[n_pf_group, coil] = (
rminor * zref[n_pf_group] * sign
)
- # Coil radius is constant / stacked for picture frame TF or if placement switch is set
+ # Coil radius is constant / stacked for picture frame TF or
+ # if placement switch is set
if (
i_tf_shape == TFCoilShapeModel.PICTURE_FRAME
or i_r_pf_outside_tf_placement == 1
@@ -1330,7 +1345,8 @@ def place_pf_outside_tf(
)
if np.isinf(r_pf_coil_middle_group_array[n_pf_group, coil]):
logger.error(
- "Element of self.data.pf_coil.r_pf_coil_middle_group_array is inf. Kludging to 1e10."
+ "Element of self.data.pf_coil.r_pf_coil_middle_group_array "
+ "is inf. Kludging to 1e10."
)
r_pf_coil_middle_group_array[n_pf_group, coil] = 1e10
return (
@@ -1347,7 +1363,8 @@ def place_pf_generally(
zref: np.ndarray,
rref: np.ndarray,
) -> tuple[np.ndarray, np.ndarray]:
- """Calculates the radial and vertical positions of poloidal field (PF) coils placed in a general location.
+ """Calculates the radial and vertical positions of poloidal field (PF) coils
+ placed in a general location.
Parameters
----------
@@ -1367,7 +1384,8 @@ def place_pf_generally(
Returns
-------
tuple[numpy.ndarray, numpy.ndarray]
- Tuple containing arrays of radial and vertical positions of PF coil centers for the specified group.
+ Tuple containing arrays of radial and vertical positions of PF coil centers
+ for the specified group.
"""
r_pf_coil_middle_group_array: np.ndarray = np.zeros((
self.data.pf_coil.n_pf_coil_groups,
@@ -1738,7 +1756,9 @@ def induct(self, output):
rplasma = np.zeros(nplas)
zplasma = np.zeros(nplas)
- self.data.pf_coil.ind_pf_cs_plasma_mutual[:, :] = 0.0
+ pf_d = self.data.pf_coil
+
+ pf_d.ind_pf_cs_plasma_mutual[:, :] = 0.0
# Break Central Solenoid into noh segments
#
@@ -1748,16 +1768,17 @@ def induct(self, output):
noh = math.ceil(
2.0e0
- * self.data.pf_coil.z_pf_coil_upper[self.data.pf_coil.n_cs_pf_coils - 1]
+ * pf_d.z_pf_coil_upper[pf_d.n_cs_pf_coils - 1]
/ (
- self.data.pf_coil.r_pf_coil_outer[self.data.pf_coil.n_cs_pf_coils - 1]
- - self.data.pf_coil.r_pf_coil_inner[self.data.pf_coil.n_cs_pf_coils - 1]
+ pf_d.r_pf_coil_outer[pf_d.n_cs_pf_coils - 1]
+ - pf_d.r_pf_coil_inner[pf_d.n_cs_pf_coils - 1]
)
)
if noh > nohmax:
logger.error(
- "Max no. of segments noh for OH coil > nohmax; increase dr_cs lower bound"
+ "Max no. of segments noh for OH coil > nohmax; "
+ "increase dr_cs lower bound"
f"{noh=} {nohmax=} {self.data.build.dr_cs=}"
)
@@ -1771,25 +1792,24 @@ def induct(self, output):
zoh = np.zeros(noh)
if self.data.build.iohcl != 0:
- roh[:] = self.data.pf_coil.r_cs_middle
+ roh[:] = pf_d.r_cs_middle
delzoh = (
- 2.0e0
- * self.data.pf_coil.z_pf_coil_upper[self.data.pf_coil.n_cs_pf_coils - 1]
- / noh
+ 2.0e0 * pf_d.z_pf_coil_upper[pf_d.n_cs_pf_coils - 1] / noh
) # z_pf_coil_upper(n_cs_pf_coils) is the half-height of the coil
for i in range(noh):
- zoh[i] = self.data.pf_coil.z_pf_coil_upper[
- self.data.pf_coil.n_cs_pf_coils - 1
- ] - delzoh * (0.5e0 + i)
+ zoh[i] = pf_d.z_pf_coil_upper[pf_d.n_cs_pf_coils - 1] - delzoh * (
+ 0.5e0 + i
+ )
rplasma[0] = self.data.physics.rmajor # assumes nplas==1
zplasma[0] = 0.0
# Central Solenoid / plasma mutual inductance
#
- # Improved calculation: Each Central Solenoid segment is now split into two filaments,
- # of radius reqv+deltar and reqv-deltar, respectively. The mutual inductance
+ # Improved calculation: Each Central Solenoid segment is now split into two
+ # filaments, of radius reqv+deltar and reqv-deltar, respectively.
+ # The mutual inductance
# of the segment with a plasma circuit is the mean of that calculated
# using the two equivalent filaments.
# Formulas and tables for the calculation of mutual and self-inductance
@@ -1834,36 +1854,32 @@ def induct(self, output):
xc[ii] = 0.5e0 * (xcin[ii] + xcout[ii])
xohpl += xc[ii]
- self.data.pf_coil.ind_pf_cs_plasma_mutual[
- self.data.pf_coil.n_pf_cs_plasma_circuits - 1,
- self.data.pf_coil.n_cs_pf_coils - 1,
- ] = (
- xohpl
- / (nplas * noh)
- * self.data.pf_coil.n_pf_coil_turns[self.data.pf_coil.n_cs_pf_coils - 1]
- )
- self.data.pf_coil.ind_pf_cs_plasma_mutual[
- self.data.pf_coil.n_cs_pf_coils - 1,
- self.data.pf_coil.n_pf_cs_plasma_circuits - 1,
- ] = self.data.pf_coil.ind_pf_cs_plasma_mutual[
- self.data.pf_coil.n_pf_cs_plasma_circuits - 1,
- self.data.pf_coil.n_cs_pf_coils - 1,
+ pf_d.ind_pf_cs_plasma_mutual[
+ pf_d.n_pf_cs_plasma_circuits - 1,
+ pf_d.n_cs_pf_coils - 1,
+ ] = xohpl / (nplas * noh) * pf_d.n_pf_coil_turns[pf_d.n_cs_pf_coils - 1]
+ pf_d.ind_pf_cs_plasma_mutual[
+ pf_d.n_cs_pf_coils - 1,
+ pf_d.n_pf_cs_plasma_circuits - 1,
+ ] = pf_d.ind_pf_cs_plasma_mutual[
+ pf_d.n_pf_cs_plasma_circuits - 1,
+ pf_d.n_cs_pf_coils - 1,
]
# Plasma self inductance
- self.data.pf_coil.ind_pf_cs_plasma_mutual[
- self.data.pf_coil.n_pf_cs_plasma_circuits - 1,
- self.data.pf_coil.n_pf_cs_plasma_circuits - 1,
+ pf_d.ind_pf_cs_plasma_mutual[
+ pf_d.n_pf_cs_plasma_circuits - 1,
+ pf_d.n_pf_cs_plasma_circuits - 1,
] = self.data.physics.ind_plasma
# PF coil / plasma mutual inductances
ncoils = 0
- for i in range(self.data.pf_coil.n_pf_coil_groups):
+ for i in range(pf_d.n_pf_coil_groups):
xpfpl = 0.0
- ncoils += self.data.pf_coil.n_pf_coils_in_group[i]
- rp = self.data.pf_coil.r_pf_coil_middle[ncoils - 1]
- zp = self.data.pf_coil.z_pf_coil_middle[ncoils - 1]
+ ncoils += pf_d.n_pf_coils_in_group[i]
+ rp = pf_d.r_pf_coil_middle[ncoils - 1]
+ zp = pf_d.z_pf_coil_middle[ncoils - 1]
xc, _br, _bz, _psi = calculate_b_field_at_point(
r_current_loop=rc,
z_current_loop=zc,
@@ -1874,35 +1890,32 @@ def induct(self, output):
for ii in range(nplas):
xpfpl += xc[ii]
- for j in range(self.data.pf_coil.n_pf_coils_in_group[i]):
+ for j in range(pf_d.n_pf_coils_in_group[i]):
ncoilj = ncoils + 1 - (j + 1)
- self.data.pf_coil.ind_pf_cs_plasma_mutual[
- ncoilj - 1, self.data.pf_coil.n_pf_cs_plasma_circuits - 1
- ] = xpfpl / nplas * self.data.pf_coil.n_pf_coil_turns[ncoilj - 1]
- self.data.pf_coil.ind_pf_cs_plasma_mutual[
- self.data.pf_coil.n_pf_cs_plasma_circuits - 1, ncoilj - 1
- ] = self.data.pf_coil.ind_pf_cs_plasma_mutual[
- ncoilj - 1, self.data.pf_coil.n_pf_cs_plasma_circuits - 1
+ pf_d.ind_pf_cs_plasma_mutual[
+ ncoilj - 1, pf_d.n_pf_cs_plasma_circuits - 1
+ ] = xpfpl / nplas * pf_d.n_pf_coil_turns[ncoilj - 1]
+ pf_d.ind_pf_cs_plasma_mutual[
+ pf_d.n_pf_cs_plasma_circuits - 1, ncoilj - 1
+ ] = pf_d.ind_pf_cs_plasma_mutual[
+ ncoilj - 1, pf_d.n_pf_cs_plasma_circuits - 1
]
if self.data.build.iohcl != 0:
# Central Solenoid self inductance
- a = self.data.pf_coil.r_cs_middle # mean radius of coil
- b = (
- 2.0e0
- * self.data.pf_coil.z_pf_coil_upper[self.data.pf_coil.n_cs_pf_coils - 1]
- ) # length of coil
+ a = pf_d.r_cs_middle # mean radius of coil
+ b = 2.0e0 * pf_d.z_pf_coil_upper[pf_d.n_cs_pf_coils - 1] # length of coil
c = (
- self.data.pf_coil.r_pf_coil_outer[self.data.pf_coil.n_cs_pf_coils - 1]
- - self.data.pf_coil.r_pf_coil_inner[self.data.pf_coil.n_cs_pf_coils - 1]
+ pf_d.r_pf_coil_outer[pf_d.n_cs_pf_coils - 1]
+ - pf_d.r_pf_coil_inner[pf_d.n_cs_pf_coils - 1]
) # radial winding thickness
- self.data.pf_coil.ind_pf_cs_plasma_mutual[
- self.data.pf_coil.n_cs_pf_coils - 1, self.data.pf_coil.n_cs_pf_coils - 1
+ pf_d.ind_pf_cs_plasma_mutual[
+ pf_d.n_cs_pf_coils - 1, pf_d.n_cs_pf_coils - 1
] = self.selfinductance(
a,
b,
c,
- self.data.pf_coil.n_pf_coil_turns[self.data.pf_coil.n_cs_pf_coils - 1],
+ pf_d.n_pf_coil_turns[pf_d.n_cs_pf_coils - 1],
)
# Central Solenoid / PF coil mutual inductances
@@ -1911,11 +1924,11 @@ def induct(self, output):
zc[i] = zoh[i]
ncoils = 0
- for i in range(self.data.pf_coil.n_pf_coil_groups):
+ for i in range(pf_d.n_pf_coil_groups):
xohpf = 0.0
- ncoils += self.data.pf_coil.n_pf_coils_in_group[i]
- rp = self.data.pf_coil.r_pf_coil_middle[ncoils - 1]
- zp = self.data.pf_coil.z_pf_coil_middle[ncoils - 1]
+ ncoils += pf_d.n_pf_coils_in_group[i]
+ rp = pf_d.r_pf_coil_middle[ncoils - 1]
+ zp = pf_d.z_pf_coil_middle[ncoils - 1]
xc, _br, _bz, _psi = calculate_b_field_at_point(
r_current_loop=rc,
z_current_loop=zc,
@@ -1926,39 +1939,33 @@ def induct(self, output):
for ii in range(noh):
xohpf += xc[ii]
- for j in range(self.data.pf_coil.n_pf_coils_in_group[i]):
+ for j in range(pf_d.n_pf_coils_in_group[i]):
ncoilj = ncoils + 1 - (j + 1)
- self.data.pf_coil.ind_pf_cs_plasma_mutual[
- ncoilj - 1, self.data.pf_coil.n_cs_pf_coils - 1
- ] = (
+ pf_d.ind_pf_cs_plasma_mutual[ncoilj - 1, pf_d.n_cs_pf_coils - 1] = (
xohpf
- * self.data.pf_coil.n_pf_coil_turns[ncoilj - 1]
- * self.data.pf_coil.n_pf_coil_turns[
- self.data.pf_coil.n_cs_pf_coils - 1
- ]
+ * pf_d.n_pf_coil_turns[ncoilj - 1]
+ * pf_d.n_pf_coil_turns[pf_d.n_cs_pf_coils - 1]
/ noh
)
- self.data.pf_coil.ind_pf_cs_plasma_mutual[
- self.data.pf_coil.n_cs_pf_coils - 1, ncoilj - 1
- ] = self.data.pf_coil.ind_pf_cs_plasma_mutual[
- ncoilj - 1, self.data.pf_coil.n_cs_pf_coils - 1
- ]
+ pf_d.ind_pf_cs_plasma_mutual[pf_d.n_cs_pf_coils - 1, ncoilj - 1] = (
+ pf_d.ind_pf_cs_plasma_mutual[ncoilj - 1, pf_d.n_cs_pf_coils - 1]
+ )
# PF coil - PF coil inductances
if self.data.build.iohcl == 0:
- self.data.pf_coil.nef = self.data.pf_coil.n_cs_pf_coils
+ pf_d.nef = pf_d.n_cs_pf_coils
else:
- self.data.pf_coil.nef = self.data.pf_coil.n_cs_pf_coils - 1
+ pf_d.nef = pf_d.n_cs_pf_coils - 1
- for i in range(self.data.pf_coil.nef):
- for j in range(self.data.pf_coil.nef - 1):
+ for i in range(pf_d.nef):
+ for j in range(pf_d.nef - 1):
jj = j + 1 + 1 if j >= i else j + 1
- zc[j] = self.data.pf_coil.z_pf_coil_middle[jj - 1]
- rc[j] = self.data.pf_coil.r_pf_coil_middle[jj - 1]
+ zc[j] = pf_d.z_pf_coil_middle[jj - 1]
+ rc[j] = pf_d.r_pf_coil_middle[jj - 1]
- rp = self.data.pf_coil.r_pf_coil_middle[i]
- zp = self.data.pf_coil.z_pf_coil_middle[i]
+ rp = pf_d.r_pf_coil_middle[i]
+ zp = pf_d.z_pf_coil_middle[i]
xc, _br, _bz, _psi = calculate_b_field_at_point(
r_current_loop=rc,
z_current_loop=zc,
@@ -1966,32 +1973,24 @@ def induct(self, output):
r_test_point=rp,
z_test_point=zp,
)
- for k in range(self.data.pf_coil.nef):
+ for k in range(pf_d.nef):
if k < i:
- self.data.pf_coil.ind_pf_cs_plasma_mutual[i, k] = (
- xc[k]
- * self.data.pf_coil.n_pf_coil_turns[k]
- * self.data.pf_coil.n_pf_coil_turns[i]
+ pf_d.ind_pf_cs_plasma_mutual[i, k] = (
+ xc[k] * pf_d.n_pf_coil_turns[k] * pf_d.n_pf_coil_turns[i]
)
elif k == i:
rl = abs(
- self.data.pf_coil.z_pf_coil_upper[k]
- - self.data.pf_coil.z_pf_coil_lower[k]
+ pf_d.z_pf_coil_upper[k] - pf_d.z_pf_coil_lower[k]
) / math.sqrt(np.pi)
- self.data.pf_coil.ind_pf_cs_plasma_mutual[k, k] = (
+ pf_d.ind_pf_cs_plasma_mutual[k, k] = (
constants.RMU0
- * self.data.pf_coil.n_pf_coil_turns[k] ** 2
- * self.data.pf_coil.r_pf_coil_middle[k]
- * (
- math.log(8.0e0 * self.data.pf_coil.r_pf_coil_middle[k] / rl)
- - 1.75e0
- )
+ * pf_d.n_pf_coil_turns[k] ** 2
+ * pf_d.r_pf_coil_middle[k]
+ * (math.log(8.0e0 * pf_d.r_pf_coil_middle[k] / rl) - 1.75e0)
)
else:
- self.data.pf_coil.ind_pf_cs_plasma_mutual[i, k] = (
- xc[k - 1]
- * self.data.pf_coil.n_pf_coil_turns[k]
- * self.data.pf_coil.n_pf_coil_turns[i]
+ pf_d.ind_pf_cs_plasma_mutual[i, k] = (
+ xc[k - 1] * pf_d.n_pf_coil_turns[k] * pf_d.n_pf_coil_turns[i]
)
# Output section
@@ -2001,32 +2000,33 @@ def induct(self, output):
op.oheadr(self.outfile, "PF Coil Inductances")
op.ocmmnt(self.outfile, "Inductance matrix [H]:")
op.oblnkl(self.outfile)
-
with np.printoptions(precision=1):
- for ig in range(self.data.pf_coil.nef):
+ n_pf_cs = pf_d.n_pf_cs_plasma_circuits
+ for ig in range(pf_d.nef):
op.write(
self.outfile,
- f"{ig}\t{self.data.pf_coil.ind_pf_cs_plasma_mutual[: self.data.pf_coil.n_pf_cs_plasma_circuits, ig]}",
+ f"{ig}\t{pf_d.ind_pf_cs_plasma_mutual[:n_pf_cs, ig]}",
)
if self.data.build.iohcl != 0:
op.write(
self.outfile,
- f"CS\t{self.data.pf_coil.ind_pf_cs_plasma_mutual[: self.data.pf_coil.n_pf_cs_plasma_circuits, self.data.pf_coil.n_pf_cs_plasma_circuits - 2]}",
+ f"CS\t{pf_d.ind_pf_cs_plasma_mutual[:n_pf_cs, n_pf_cs - 2]}",
)
op.write(
self.outfile,
- f"Plasma\t{self.data.pf_coil.ind_pf_cs_plasma_mutual[: self.data.pf_coil.n_pf_cs_plasma_circuits, self.data.pf_coil.n_pf_cs_plasma_circuits - 1]}",
+ f"Plasma\t{pf_d.ind_pf_cs_plasma_mutual[:n_pf_cs, n_pf_cs - 1]}",
)
# Output to MFILE for use in other modules
- for coil in range(self.data.pf_coil.n_pf_cs_plasma_circuits):
- for circuit in range(self.data.pf_coil.n_pf_cs_plasma_circuits):
+ for coil in range(pf_d.n_pf_cs_plasma_circuits):
+ for circuit in range(pf_d.n_pf_cs_plasma_circuits):
op.ovarre(
self.mfile,
- f"Mutual inductance between PF/CS/plasma circuits {coil} and {circuit} (H)",
+ f"Mutual inductance between PF/CS/plasma circuits {coil} "
+ f"and {circuit} (H)",
f"(ind_pf_cs_plasma_mutual[{coil},_{circuit}])",
- self.data.pf_coil.ind_pf_cs_plasma_mutual[coil, circuit],
+ pf_d.ind_pf_cs_plasma_mutual[coil, circuit],
)
def outpf(self):
@@ -2035,6 +2035,8 @@ def outpf(self):
This routine writes the PF coil information to the output file.
"""
+ pf_d = self.data.pf_coil
+
op.oheadr(self.outfile, "Central Solenoid and PF Coils")
op.ovarre(
@@ -2046,33 +2048,33 @@ def outpf(self):
if self.data.build.iohcl == 0:
op.ocmmnt(self.outfile, "No central solenoid included")
op.oblnkl(self.outfile)
- elif self.data.pf_coil.i_pf_conductor == PFConductorModel.SUPERCONDUCTING:
+ elif pf_d.i_pf_conductor == PFConductorModel.SUPERCONDUCTING:
op.ocmmnt(self.outfile, "Superconducting central solenoid")
op.ovarre(
self.outfile,
"Central solenoid superconductor material",
"(i_cs_superconductor)",
- self.data.pf_coil.i_cs_superconductor,
+ pf_d.i_cs_superconductor,
)
op.ocmmnt(
self.outfile,
f"Superconductor used: "
- f"{SuperconductorModel(self.data.pf_coil.i_cs_superconductor).full_name}",
+ f"{SuperconductorModel(pf_d.i_cs_superconductor).full_name}",
)
op.oblnkl(self.outfile)
op.ovarre(
self.outfile,
"CS superconductor operating temperature (K)",
"(temp_cs_superconductor_operating)",
- self.data.pf_coil.temp_cs_superconductor_operating,
+ pf_d.temp_cs_superconductor_operating,
)
op.ovarre(
self.outfile,
"CS temperature margin (K)",
"(temp_cs_superconductor_margin)",
- self.data.pf_coil.temp_cs_superconductor_margin,
+ pf_d.temp_cs_superconductor_margin,
"OP ",
)
op.ovarre(
@@ -2090,35 +2092,35 @@ def outpf(self):
self.outfile,
"Maximum field at Beginning Of Pulse (T)",
"(b_cs_peak_pulse_start)",
- self.data.pf_coil.b_cs_peak_pulse_start,
+ pf_d.b_cs_peak_pulse_start,
"OP ",
)
op.ovarre(
self.outfile,
"Critical superconductor current density at BOP [A/m²]",
"(j_cs_conductor_critical_pulse_start)",
- self.data.pf_coil.j_cs_conductor_critical_pulse_start,
+ pf_d.j_cs_conductor_critical_pulse_start,
"OP ",
)
op.ovarre(
self.outfile,
"Critical cable current density at BOP [A/m²]",
"(jcableoh_bop)",
- self.data.pf_coil.jcableoh_bop,
+ pf_d.jcableoh_bop,
"OP ",
)
op.ovarre(
self.outfile,
"Allowable overall current density at BOP [A/m²]",
"(j_cs_critical_pulse_start)",
- self.data.pf_coil.j_cs_critical_pulse_start,
+ pf_d.j_cs_critical_pulse_start,
"OP ",
)
op.ovarre(
self.outfile,
"Actual overall current density at BOP [A/m²]",
"(j_cs_pulse_start)",
- self.data.pf_coil.j_cs_pulse_start,
+ pf_d.j_cs_pulse_start,
"OP ",
)
op.oblnkl(self.outfile)
@@ -2126,49 +2128,49 @@ def outpf(self):
self.outfile,
"Maximum field at End Of Flattop [T]",
"(b_cs_peak_flat_top_end)",
- self.data.pf_coil.b_cs_peak_flat_top_end,
+ pf_d.b_cs_peak_flat_top_end,
"OP ",
)
op.ovarre(
self.outfile,
"Critical superconductor current density at EOF [A/m²]",
"(j_cs_conductor_critical_flat_top_end)",
- self.data.pf_coil.j_cs_conductor_critical_flat_top_end,
+ pf_d.j_cs_conductor_critical_flat_top_end,
"OP ",
)
op.ovarre(
self.outfile,
"Critical cable current density at EOF [A/m²]",
"(jcableoh_eof)",
- self.data.pf_coil.jcableoh_eof,
+ pf_d.jcableoh_eof,
"OP ",
)
op.ovarre(
self.outfile,
"Allowable overall current density at EOF [A/m²]",
"(j_cs_critical_flat_top_end)",
- self.data.pf_coil.j_cs_critical_flat_top_end,
+ pf_d.j_cs_critical_flat_top_end,
"OP ",
)
op.ovarre(
self.outfile,
"Actual overall current density at EOF [A/m²]",
"(j_cs_flat_top_end)",
- self.data.pf_coil.j_cs_flat_top_end,
+ pf_d.j_cs_flat_top_end,
)
- for i in range(len(self.data.pf_coil.r_pf_cs_current_filaments)):
+ for i in range(len(pf_d.r_pf_cs_current_filaments)):
op.ovarre(
self.mfile,
f"Radial position of CS filament {i}",
f"r_pf_cs_current_filaments{i}",
- self.data.pf_coil.r_pf_cs_current_filaments[i],
+ pf_d.r_pf_cs_current_filaments[i],
)
- for i in range(len(self.data.pf_coil.z_pf_cs_current_filaments)):
+ for i in range(len(pf_d.z_pf_cs_current_filaments)):
op.ovarre(
self.mfile,
f"Vertical position of CS filament {i}",
f"z_pf_cs_current_filaments{i}",
- self.data.pf_coil.z_pf_cs_current_filaments[i],
+ pf_d.z_pf_cs_current_filaments[i],
)
op.oblnkl(self.outfile)
@@ -2179,55 +2181,55 @@ def outpf(self):
self.outfile,
"Allowable stress in CS steel (Pa)",
"(stress_cs_steel_max)",
- self.data.pf_coil.stress_cs_steel_max,
+ pf_d.stress_cs_steel_max,
)
op.ovarre(
self.outfile,
"Hoop stress in CS steel (Pa)",
"(stress_hoop_cs_inner)",
- self.data.pf_coil.stress_hoop_cs_inner,
+ pf_d.stress_hoop_cs_inner,
"OP ",
)
op.ovarre(
self.outfile,
"Axial stress in CS steel (Pa)",
"(stress_z_cs_self_peak_midplane)",
- self.data.pf_coil.stress_z_cs_self_peak_midplane,
+ pf_d.stress_z_cs_self_peak_midplane,
"OP ",
)
op.ovarre(
self.outfile,
"Radial stress in CS steel at midplane at coil centre (Pa)",
"(stress_radial_cs_peak)",
- self.data.pf_coil.stress_radial_cs_peak,
+ pf_d.stress_radial_cs_peak,
"OP ",
)
op.ovarre(
self.outfile,
"Radial stress in CS steel at inboard edge (Pa)",
"(stress_radial_cs_inner)",
- self.data.pf_coil.stress_radial_cs_inner,
+ pf_d.stress_radial_cs_inner,
"OP ",
)
op.ovarre(
self.outfile,
"Maximum shear stress in CS steel for the Tresca criterion (Pa)",
"(stress_shear_cs_peak)",
- self.data.pf_coil.stress_shear_cs_peak,
+ pf_d.stress_shear_cs_peak,
"OP ",
)
op.ovarre(
self.outfile,
"Maximum von Mises stress in CS steel (Pa)",
"(stress_mises_cs_peak)",
- self.data.pf_coil.stress_mises_cs_peak,
+ pf_d.stress_mises_cs_peak,
"OP ",
)
op.ovarre(
self.outfile,
"Axial force in CS (N)",
"(forc_z_cs_self_peak_midplane)",
- self.data.pf_coil.forc_z_cs_self_peak_midplane,
+ pf_d.forc_z_cs_self_peak_midplane,
"OP ",
)
op.ovarre(
@@ -2281,68 +2283,59 @@ def outpf(self):
)
# Check whether CS coil is hitting any limits
if (
- abs(self.data.pf_coil.j_cs_flat_top_end)
+ abs(pf_d.j_cs_flat_top_end)
> 0.99e0
- * abs(
- self.data.constraints.fjohc
- * self.data.pf_coil.j_cs_critical_flat_top_end
- )
+ * abs(self.data.constraints.fjohc * pf_d.j_cs_critical_flat_top_end)
) or (
- abs(self.data.pf_coil.j_cs_pulse_start)
+ abs(pf_d.j_cs_pulse_start)
> 0.99e0
- * abs(
- self.data.constraints.fjohc0
- * self.data.pf_coil.j_cs_critical_pulse_start
- )
+ * abs(self.data.constraints.fjohc0 * pf_d.j_cs_critical_pulse_start)
):
- self.data.pf_coil.cslimit = True
+ pf_d.cslimit = True
- if (
- self.data.pf_coil.j_cs_flat_top_end
- / self.data.pf_coil.j_cs_critical_flat_top_end
- > 0.7
- ):
+ if pf_d.j_cs_flat_top_end / pf_d.j_cs_critical_flat_top_end > 0.7:
logger.error(
- "j_cs_flat_top_end / j_cs_critical_flat_top_end shouldn't be above 0.7 "
+ "j_cs_flat_top_end / j_cs_critical_flat_top_end "
+ "shouldn't be above 0.7 "
"for engineering reliability"
)
- if (
- self.data.pf_coil.j_cs_pulse_start
- / self.data.pf_coil.j_cs_critical_pulse_start
- > 0.7
- ):
+ if pf_d.j_cs_pulse_start / pf_d.j_cs_critical_pulse_start > 0.7:
logger.error(
- "j_cs_pulse_start / j_cs_critical_pulse_start shouldn't be above 0.7 "
+ "j_cs_pulse_start / j_cs_critical_pulse_start "
+ "shouldn't be above 0.7 "
"for engineering reliability"
)
if (
- self.data.pf_coil.temp_cs_superconductor_margin
+ pf_d.temp_cs_superconductor_margin
< 1.01e0 * self.data.tfcoil.temp_cs_superconductor_margin_min
):
- self.data.pf_coil.cslimit = True
- if not self.data.pf_coil.cslimit:
+ pf_d.cslimit = True
+ if not pf_d.cslimit:
logger.warning(
- "CS not using max current density: further optimisation may be possible"
+ "CS not using max current density: "
+ "further optimisation may be possible"
)
# REBCO fractures in strains above ~+/- 0.7%
if (
- SuperconductorModel(self.data.pf_coil.i_pf_superconductor).material
+ SuperconductorModel(pf_d.i_pf_superconductor).material
== SuperconductorMaterial.REBCO
) and abs(self.data.tfcoil.str_cs_con_res) > 0.7e-2:
logger.error(
- "Non physical strain used in CS. Use superconductor strain < +/- 0.7%"
+ "Non physical strain used in CS. "
+ "Use superconductor strain < +/- 0.7%"
)
if (
- SuperconductorModel(self.data.pf_coil.i_pf_superconductor).material
+ SuperconductorModel(pf_d.i_pf_superconductor).material
== SuperconductorMaterial.REBCO
and abs(self.data.tfcoil.str_pf_con_res) > 0.7e-2
):
logger.error(
- "Non physical strain used in PF. Use superconductor strain < +/- 0.7%"
+ "Non physical strain used in PF. "
+ "Use superconductor strain < +/- 0.7%"
)
else:
@@ -2352,7 +2345,7 @@ def outpf(self):
op.ocmmnt(self.outfile, "----------------------------")
op.oblnkl(self.outfile)
- if self.data.pf_coil.i_pf_conductor == PFConductorModel.SUPERCONDUCTING:
+ if pf_d.i_pf_conductor == PFConductorModel.SUPERCONDUCTING:
op.oblnkl(self.outfile)
op.ocmmnt(self.outfile, "Superconducting PF coils")
@@ -2360,19 +2353,20 @@ def outpf(self):
self.outfile,
"PF coil superconductor material",
"(i_pf_superconductor)",
- self.data.pf_coil.i_pf_superconductor,
+ pf_d.i_pf_superconductor,
)
op.ocmmnt(
self.outfile,
- f"Superconductor used: {SuperconductorModel(self.data.pf_coil.i_pf_superconductor).full_name}",
+ "Superconductor used: "
+ f"{SuperconductorModel(pf_d.i_pf_superconductor).full_name}",
)
op.ovarre(
self.outfile,
"Copper fraction in conductor",
"(fcupfsu)",
- self.data.pf_coil.fcupfsu,
+ pf_d.fcupfsu,
)
op.osubhd(self.outfile, "PF Coil Case Stress :")
@@ -2380,13 +2374,13 @@ def outpf(self):
self.outfile,
"Maximum permissible tensile stress (MPa)",
"(sigpfcalw)",
- self.data.pf_coil.sigpfcalw,
+ pf_d.sigpfcalw,
)
op.ovarre(
self.outfile,
"JxB hoop force fraction supported by case",
"(sigpfcf)",
- self.data.pf_coil.sigpfcf,
+ pf_d.sigpfcf,
)
else:
@@ -2398,7 +2392,7 @@ def outpf(self):
self.outfile,
"PF coil resistive power (W)",
"(p_pf_coil_resistive_total_flat_top)",
- self.data.pf_coil.p_pf_coil_resistive_total_flat_top,
+ pf_d.p_pf_coil_resistive_total_flat_top,
"OP ",
)
if self.data.build.iohcl != 0:
@@ -2406,40 +2400,42 @@ def outpf(self):
self.outfile,
"Central solenoid resistive power (W)",
"(p_cs_resistive_flat_top)",
- self.data.pf_coil.p_cs_resistive_flat_top,
+ pf_d.p_cs_resistive_flat_top,
"OP ",
)
- # self.data.pf_coil.nef is the number of coils excluding the Central Solenoid
- self.data.pf_coil.nef = self.data.pf_coil.n_cs_pf_coils
+ # pf_d.nef is the number of coils excluding the Central Solenoid
+ pf_d.nef = pf_d.n_cs_pf_coils
if self.data.build.iohcl != 0:
- self.data.pf_coil.nef -= 1
+ pf_d.nef -= 1
op.osubhd(self.outfile, "Geometry of PF coils, central solenoid and plasma:")
op.oblnkl(self.outfile)
-
# PF coils
pf_coil_geometry_rows = [
[
f"PF {k}",
- f"{self.data.pf_coil.r_pf_coil_middle[k]:.2e}",
- f"{self.data.pf_coil.z_pf_coil_middle[k]:.2e}",
- f"{self.data.pf_coil.r_pf_coil_outer[k] - self.data.pf_coil.r_pf_coil_inner[k]:.2e}",
- f"{abs(self.data.pf_coil.z_pf_coil_upper[k] - self.data.pf_coil.z_pf_coil_lower[k]):.2e}",
- f"{self.data.pf_coil.n_pf_coil_turns[k]:.2e}",
+ f"{pf_d.r_pf_coil_middle[k]:.2e}",
+ f"{pf_d.z_pf_coil_middle[k]:.2e}",
+ f"{pf_d.r_pf_coil_outer[k] - pf_d.r_pf_coil_inner[k]:.2e}",
+ f"{abs(pf_d.z_pf_coil_upper[k] - pf_d.z_pf_coil_lower[k]):.2e}",
+ f"{pf_d.n_pf_coil_turns[k]:.2e}",
]
- for k in range(self.data.pf_coil.nef)
+ for k in range(pf_d.nef)
]
if self.data.build.iohcl != 0:
- cs_index = self.data.pf_coil.n_cs_pf_coils - 1
+ cs_index = pf_d.n_cs_pf_coils - 1
+ pf_centre = abs(
+ pf_d.z_pf_coil_upper[cs_index] - pf_d.z_pf_coil_lower[cs_index]
+ )
pf_coil_geometry_rows.append([
"CS",
- f"{self.data.pf_coil.r_pf_coil_middle[cs_index]:.2e}",
- f"{self.data.pf_coil.z_pf_coil_middle[cs_index]:.2e}",
- f"{self.data.pf_coil.r_pf_coil_outer[cs_index] - self.data.pf_coil.r_pf_coil_inner[cs_index]:.2e}",
- f"{abs(self.data.pf_coil.z_pf_coil_upper[cs_index] - self.data.pf_coil.z_pf_coil_lower[cs_index]):.2e}",
- f"{self.data.pf_coil.n_pf_coil_turns[cs_index]:.2e}",
+ f"{pf_d.r_pf_coil_middle[cs_index]:.2e}",
+ f"{pf_d.z_pf_coil_middle[cs_index]:.2e}",
+ f"{pf_d.r_pf_coil_outer[cs_index] - pf_d.r_pf_coil_inner[cs_index]:.2e}",
+ f"{pf_centre:.2e}",
+ f"{pf_d.n_pf_coil_turns[cs_index]:.2e}",
])
pf_coil_geometry_rows.append([
@@ -2458,61 +2454,57 @@ def outpf(self):
).splitlines():
op.write(self.outfile, line)
- for k in range(self.data.pf_coil.nef):
+ for k in range(pf_d.nef):
op.ovarre(
self.mfile,
f"PF coil {k} radius (m)",
f"(r_pf_coil_middle[{k}])",
- self.data.pf_coil.r_pf_coil_middle[k],
+ pf_d.r_pf_coil_middle[k],
)
op.ovarre(
self.mfile,
f"PF coil {k} vertical position (m)",
f"(z_pf_coil_middle[{k}])",
- self.data.pf_coil.z_pf_coil_middle[k],
+ pf_d.z_pf_coil_middle[k],
)
op.ovarre(
self.mfile,
f"PF coil {k} radial thickness (m)",
f"(pfdr({k}))",
- self.data.pf_coil.r_pf_coil_outer[k]
- - self.data.pf_coil.r_pf_coil_inner[k],
+ pf_d.r_pf_coil_outer[k] - pf_d.r_pf_coil_inner[k],
)
op.ovarre(
self.mfile,
f"PF coil {k} vertical thickness (m)",
f"(pfdz({k}))",
- self.data.pf_coil.z_pf_coil_upper[k]
- - self.data.pf_coil.z_pf_coil_lower[k],
+ pf_d.z_pf_coil_upper[k] - pf_d.z_pf_coil_lower[k],
)
op.ovarre(
self.mfile,
f"PF coil {k} turns",
f"(n_pf_coil_turns[{k}])",
- self.data.pf_coil.n_pf_coil_turns[k],
+ pf_d.n_pf_coil_turns[k],
)
op.ovarre(
self.mfile,
f"PF coil {k} current (MA)",
f"(c_pf_cs_coils_peak_ma[{k}])",
- self.data.pf_coil.c_pf_cs_coils_peak_ma[k],
+ pf_d.c_pf_cs_coils_peak_ma[k],
)
op.ovarre(
self.mfile,
f"PF coil {k} field (T)",
f"(b_pf_coil_peak[{k}])",
- self.data.pf_coil.b_pf_coil_peak[k],
+ pf_d.b_pf_coil_peak[k],
)
for time in range(6):
op.ovarre(
self.mfile,
f"CS coil midplane axial stress at time point {time} (MPa)",
f"(stress_z_cs_self_midplane_profile[{time}])",
- self.data.pf_coil.stress_z_cs_self_midplane_profile[time],
+ pf_d.stress_z_cs_self_midplane_profile[time],
)
- for position, stress in enumerate(
- self.data.pf_coil.stress_z_cs_self_profile.tolist()
- ):
+ for position, stress in enumerate(pf_d.stress_z_cs_self_profile.tolist()):
op.ovarre(
self.mfile,
f"CS coil axial stress at position {position} (MPa)",
@@ -2526,46 +2518,40 @@ def outpf(self):
self.mfile,
"Central solenoid radius (m)",
"(r_pf_coil_middle[n_cs_pf_coils-1])",
- self.data.pf_coil.r_pf_coil_middle[self.data.pf_coil.n_cs_pf_coils - 1],
+ pf_d.r_pf_coil_middle[pf_d.n_cs_pf_coils - 1],
)
op.ovarre(
self.mfile,
"Central solenoid vertical position (m)",
"(z_pf_coil_middle[n_cs_pf_coils-1])",
- self.data.pf_coil.z_pf_coil_middle[self.data.pf_coil.n_cs_pf_coils - 1],
+ pf_d.z_pf_coil_middle[pf_d.n_cs_pf_coils - 1],
)
op.ovarre(
self.mfile,
"Central solenoid radial thickness (m)",
"(ohdr)",
(
- self.data.pf_coil.r_pf_coil_outer[
- self.data.pf_coil.n_cs_pf_coils - 1
- ]
- - self.data.pf_coil.r_pf_coil_inner[
- self.data.pf_coil.n_cs_pf_coils - 1
- ]
+ pf_d.r_pf_coil_outer[pf_d.n_cs_pf_coils - 1]
+ - pf_d.r_pf_coil_inner[pf_d.n_cs_pf_coils - 1]
),
)
op.ovarre(
self.mfile,
"Central solenoid turns",
"(n_pf_coil_turns[n_cs_pf_coils-1])",
- self.data.pf_coil.n_pf_coil_turns[self.data.pf_coil.n_cs_pf_coils - 1],
+ pf_d.n_pf_coil_turns[pf_d.n_cs_pf_coils - 1],
)
op.ovarre(
self.mfile,
"Central solenoid current (MA)",
"(c_pf_cs_coils_peak_ma[n_cs_pf_coils-1])",
- self.data.pf_coil.c_pf_cs_coils_peak_ma[
- self.data.pf_coil.n_cs_pf_coils - 1
- ],
+ pf_d.c_pf_cs_coils_peak_ma[pf_d.n_cs_pf_coils - 1],
)
op.ovarre(
self.mfile,
"Central solenoid field (T)",
"(b_pf_coil_peak[n_cs_pf_coils-1])",
- self.data.pf_coil.b_pf_coil_peak[self.data.pf_coil.n_cs_pf_coils - 1],
+ pf_d.b_pf_coil_peak[pf_d.n_cs_pf_coils - 1],
)
op.oblnkl(self.outfile)
@@ -2587,69 +2573,69 @@ def outpf(self):
rows = []
# PF coils
- for k in range(self.data.pf_coil.nef):
- if self.data.pf_coil.i_pf_conductor == PFConductorModel.SUPERCONDUCTING:
+ for k in range(pf_d.nef):
+ if pf_d.i_pf_conductor == PFConductorModel.SUPERCONDUCTING:
rows.append([
f"PF {k}",
- f"{self.data.pf_coil.c_pf_cs_coils_peak_ma[k]:.3e}",
- f"{self.data.pf_coil.j_pf_wp_critical[k]:.3e}",
- f"{self.data.pf_coil.j_pf_coil_wp_peak[k]:.3e}",
- f"{self.data.pf_coil.j_pf_coil_wp_peak[k] / self.data.pf_coil.j_pf_wp_critical[k]:.3e}",
- f"{self.data.pf_coil.m_pf_coil_conductor[k]:.3e}",
- f"{self.data.pf_coil.m_pf_coil_structure[k]:.3e}",
- f"{self.data.pf_coil.b_pf_coil_peak[k]:.3e}",
+ f"{pf_d.c_pf_cs_coils_peak_ma[k]:.3e}",
+ f"{pf_d.j_pf_wp_critical[k]:.3e}",
+ f"{pf_d.j_pf_coil_wp_peak[k]:.3e}",
+ f"{pf_d.j_pf_coil_wp_peak[k] / pf_d.j_pf_wp_critical[k]:.3e}",
+ f"{pf_d.m_pf_coil_conductor[k]:.3e}",
+ f"{pf_d.m_pf_coil_structure[k]:.3e}",
+ f"{pf_d.b_pf_coil_peak[k]:.3e}",
])
else:
rows.append([
f"PF {k}",
- f"{self.data.pf_coil.c_pf_cs_coils_peak_ma[k]:.3e}",
+ f"{pf_d.c_pf_cs_coils_peak_ma[k]:.3e}",
"-1.0e0",
- f"{self.data.pf_coil.j_pf_coil_wp_peak[k]:.3e}",
+ f"{pf_d.j_pf_coil_wp_peak[k]:.3e}",
"1.0e0",
- f"{self.data.pf_coil.m_pf_coil_conductor[k]:.3e}",
- f"{self.data.pf_coil.m_pf_coil_structure[k]:.3e}",
- f"{self.data.pf_coil.b_pf_coil_peak[k]:.3e}",
+ f"{pf_d.m_pf_coil_conductor[k]:.3e}",
+ f"{pf_d.m_pf_coil_structure[k]:.3e}",
+ f"{pf_d.b_pf_coil_peak[k]:.3e}",
])
# Central Solenoid, if present
if self.data.build.iohcl != 0:
- cs_index = self.data.pf_coil.n_cs_pf_coils - 1
+ cs_index = pf_d.n_cs_pf_coils - 1
cs_peak_j = max(
- abs(self.data.pf_coil.j_cs_pulse_start),
- abs(self.data.pf_coil.j_cs_flat_top_end),
+ abs(pf_d.j_cs_pulse_start),
+ abs(pf_d.j_cs_flat_top_end),
)
- if self.data.pf_coil.i_pf_conductor == PFConductorModel.SUPERCONDUCTING:
+ if pf_d.i_pf_conductor == PFConductorModel.SUPERCONDUCTING:
# Issue #328
rows.append([
"CS",
- f"{self.data.pf_coil.c_pf_cs_coils_peak_ma[cs_index]:.3e}",
- f"{self.data.pf_coil.j_pf_wp_critical[cs_index]:.3e}",
+ f"{pf_d.c_pf_cs_coils_peak_ma[cs_index]:.3e}",
+ f"{pf_d.j_pf_wp_critical[cs_index]:.3e}",
f"{cs_peak_j:.3e}",
- f"{(cs_peak_j / self.data.pf_coil.j_pf_wp_critical[cs_index]):.3e}",
- f"{self.data.pf_coil.m_pf_coil_conductor[cs_index]:.3e}",
- f"{self.data.pf_coil.m_pf_coil_structure[cs_index]:.3e}",
- f"{self.data.pf_coil.b_pf_coil_peak[cs_index]:.3e}",
+ f"{(cs_peak_j / pf_d.j_pf_wp_critical[cs_index]):.3e}",
+ f"{pf_d.m_pf_coil_conductor[cs_index]:.3e}",
+ f"{pf_d.m_pf_coil_structure[cs_index]:.3e}",
+ f"{pf_d.b_pf_coil_peak[cs_index]:.3e}",
])
else:
rows.append([
"CS",
- f"{self.data.pf_coil.c_pf_cs_coils_peak_ma[cs_index]:.3e}",
+ f"{pf_d.c_pf_cs_coils_peak_ma[cs_index]:.3e}",
"-1.0e0",
f"{cs_peak_j:.3e}",
"1.0e0",
- f"{self.data.pf_coil.m_pf_coil_conductor[cs_index]:.3e}",
- f"{self.data.pf_coil.m_pf_coil_structure[cs_index]:.3e}",
- f"{self.data.pf_coil.b_pf_coil_peak[cs_index]:.3e}",
+ f"{pf_d.m_pf_coil_conductor[cs_index]:.3e}",
+ f"{pf_d.m_pf_coil_structure[cs_index]:.3e}",
+ f"{pf_d.b_pf_coil_peak[cs_index]:.3e}",
])
rows.append([
"Total",
- f"{self.data.pf_coil.ricpf:.3e}",
+ f"{pf_d.ricpf:.3e}",
"",
"",
"",
- f"{self.data.pf_coil.m_pf_coil_conductor_total:.3e}",
- f"{self.data.pf_coil.m_pf_coil_structure_total:.3e}",
+ f"{pf_d.m_pf_coil_conductor_total:.3e}",
+ f"{pf_d.m_pf_coil_structure_total:.3e}",
"",
])
@@ -2671,12 +2657,10 @@ def outpf(self):
self.outfile,
"Sum of squares of residuals ",
"(ssq0)",
- self.data.pf_coil.ssq0,
+ pf_d.ssq0,
"OP ",
)
- op.ovarre(
- self.outfile, "Smoothing parameter ", "(alfapf)", self.data.pf_coil.alfapf
- )
+ op.ovarre(self.outfile, "Smoothing parameter ", "(alfapf)", pf_d.alfapf)
def outvolt(self):
"""Writes volt-second information to output file.
@@ -2691,11 +2675,13 @@ def outvolt(self):
op.write(self.outfile, "\t" * 6 + "start-up\t\t\tburn\t\t\t\ttotal")
op.write(
self.outfile,
- f"PF coils:\t\t{pf.vs_pf_coils_total_ramp:.2f}\t\t\t\t{pf.vs_pf_coils_total_burn:.2f}\t\t\t{pf.vs_pf_coils_total_pulse:.2f}",
+ f"PF coils:\t\t{pf.vs_pf_coils_total_ramp:.2f}"
+ f"\t\t\t\t{pf.vs_pf_coils_total_burn:.2f}\t\t\t{pf.vs_pf_coils_total_pulse:.2f}",
)
op.write(
self.outfile,
- f"CS coil:\t\t{pf.vs_cs_ramp:.2f}\t\t\t\t{pf.vs_cs_burn:.2f}\t\t\t{pf.vs_cs_total_pulse:.2f}",
+ f"CS coil:\t\t{pf.vs_cs_ramp:.2f}"
+ f"\t\t\t\t{pf.vs_cs_burn:.2f}\t\t\t{pf.vs_cs_total_pulse:.2f}",
)
op.write(
self.outfile, "\t" * 6 + "-" * 7 + "\t" * 4 + "-" * 7 + "\t" * 3 + "-" * 7
@@ -2725,16 +2711,18 @@ def outvolt(self):
op.write(self.outfile, "Circuit\t\t\tBOP\t\t\tBOF\t\tEOF")
op.oblnkl(self.outfile)
- for k in range(self.data.pf_coil.nef):
+ for k in range(pf.nef):
op.write(
self.outfile,
- f"\t{k}\t\t\t{self.data.pf_coil.vsdum[k, 0]:.3f}\t\t\t{self.data.pf_coil.vsdum[k, 1]:.3f}\t\t{self.data.pf_coil.vsdum[k, 2]:.3f}",
+ f"\t{k}\t\t\t{pf.vsdum[k, 0]:.3f}"
+ f"\t\t\t{pf.vsdum[k, 1]:.3f}\t\t{pf.vsdum[k, 2]:.3f}",
)
- n_cs = self.data.pf_coil.n_cs_pf_coils - 1
+ n_cs = pf.n_cs_pf_coils - 1
op.write(
self.outfile,
- f"\tCS coil\t\t\t{self.data.pf_coil.vsdum[n_cs, 0]:.3f}\t\t\t{self.data.pf_coil.vsdum[n_cs, 1]:.3f}\t\t{self.data.pf_coil.vsdum[n_cs, 2]:.3f}",
+ f"\tCS coil\t\t\t{pf.vsdum[n_cs, 0]:.3f}"
+ f"\t\t\t{pf.vsdum[n_cs, 1]:.3f}\t\t{pf.vsdum[n_cs, 2]:.3f}",
)
op.oshead(self.outfile, "Waveforms")
@@ -2755,43 +2743,53 @@ def outvolt(self):
op.ocmmnt(self.outfile, "circuit")
+ pf_d = self.data.pf_coil
+ cpft = self.data.pf_coil.c_pf_coil_turn
+ nturn = self.data.pf_coil.n_pf_coil_turns
+ se_ft_eft = (
+ self.data.pf_coil.f_j_cs_start_end_flat_top
+ / pf_d.f_j_cs_start_pulse_end_flat_top
+ )
+ inv_st_pulse = 1.0e0 / pf_d.f_j_cs_start_pulse_end_flat_top
+
for k in range(self.data.pf_coil.n_pf_cs_plasma_circuits - 1):
line = f"\t{k}\t\t"
for jj in range(6):
- line += f"\t{self.data.pf_coil.c_pf_coil_turn[k, jj] * self.data.pf_coil.n_pf_coil_turns[k]:.3e}"
+ line += f"\t{cpft[k, jj] * self.data.pf_coil.n_pf_coil_turns[k]:.3e}"
op.write(self.outfile, line)
line = "Plasma (A)\t\t"
for jj in range(6):
- line += f"\t{self.data.pf_coil.c_pf_coil_turn[self.data.pf_coil.n_pf_cs_plasma_circuits - 1, jj]:.3e}"
+ line += f"\t{cpft[self.data.pf_coil.n_pf_cs_plasma_circuits - 1, jj]:.3e}"
op.write(self.outfile, line)
op.oblnkl(self.outfile)
op.ocmmnt(self.outfile, "This consists of: CS coil field balancing:")
- for k in range(self.data.pf_coil.n_pf_cs_plasma_circuits - 1):
+
+ for k in range(pf_d.n_pf_cs_plasma_circuits - 1):
op.write(
self.outfile,
(
- f"{k}\t\t\t{self.data.pf_coil.c_pf_coil_turn[k, 0] * self.data.pf_coil.n_pf_coil_turns[k]:.3e}\t"
- f"{self.data.pf_coil.c_pf_coil_turn[k, 1] * self.data.pf_coil.n_pf_coil_turns[k]:.3e}\t"
- f"{-self.data.pf_coil.c_pf_coil_turn[k, 1] * self.data.pf_coil.n_pf_coil_turns[k] * (self.data.pf_coil.f_j_cs_start_end_flat_top / self.data.pf_coil.f_j_cs_start_pulse_end_flat_top):.3e}\t"
- f"{-self.data.pf_coil.c_pf_coil_turn[k, 1] * self.data.pf_coil.n_pf_coil_turns[k] * (self.data.pf_coil.f_j_cs_start_end_flat_top / self.data.pf_coil.f_j_cs_start_pulse_end_flat_top):.3e}\t"
- f"{-self.data.pf_coil.c_pf_coil_turn[k, 1] * self.data.pf_coil.n_pf_coil_turns[k] * (1.0e0 / self.data.pf_coil.f_j_cs_start_pulse_end_flat_top):.3e}\t"
- f"{self.data.pf_coil.c_pf_coil_turn[k, 5] * self.data.pf_coil.n_pf_coil_turns[k]:.3e}"
+ f"{k}\t\t\t{cpft[k, 0] * pf_d.n_pf_coil_turns[k]:.3e}\t"
+ f"{cpft[k, 1] * nturn[k]:.3e}\t"
+ f"{-cpft[k, 1] * nturn[k] * se_ft_eft:.3e}\t"
+ f"{-cpft[k, 1] * nturn[k] * se_ft_eft:.3e}\t"
+ f"{-cpft[k, 1] * nturn[k] * inv_st_pulse:.3e}\t"
+ f"{cpft[k, 5] * nturn[k]:.3e}"
),
)
op.oblnkl(self.outfile)
op.ocmmnt(self.outfile, "And: equilibrium field:")
- for k in range(self.data.pf_coil.n_pf_cs_plasma_circuits - 1):
+ for k in range(pf_d.n_pf_cs_plasma_circuits - 1):
op.write(
self.outfile,
(
f"{k}\t\t\t{0.0:.3e}\t{0.0:.3e}\t"
- f"{(self.data.pf_coil.c_pf_coil_turn[k, 2] + self.data.pf_coil.c_pf_coil_turn[k, 1] * self.data.pf_coil.f_j_cs_start_end_flat_top / self.data.pf_coil.f_j_cs_start_pulse_end_flat_top) * self.data.pf_coil.n_pf_coil_turns[k]:.3e}\t"
- f"{(self.data.pf_coil.c_pf_coil_turn[k, 3] + self.data.pf_coil.c_pf_coil_turn[k, 1] * self.data.pf_coil.f_j_cs_start_end_flat_top / self.data.pf_coil.f_j_cs_start_pulse_end_flat_top) * self.data.pf_coil.n_pf_coil_turns[k]:.3e}\t"
- f"{(self.data.pf_coil.c_pf_coil_turn[k, 4] + self.data.pf_coil.c_pf_coil_turn[k, 1] * 1.0e0 / self.data.pf_coil.f_j_cs_start_pulse_end_flat_top) * self.data.pf_coil.n_pf_coil_turns[k]:.3e}\t"
+ f"{(cpft[k, 2] + cpft[k, 1] * se_ft_eft) * nturn[k]:.3e}\t"
+ f"{(cpft[k, 3] + cpft[k, 1] * se_ft_eft) * nturn[k]:.3e}\t"
+ f"{(cpft[k, 4] + cpft[k, 1] * inv_st_pulse) * nturn[k]:.3e}\t"
"0.0e0"
),
)
@@ -2805,7 +2803,8 @@ def outvolt(self):
)
op.ovarre(
self.outfile,
- "Ratio of central solenoid current at beginning of Flat-top / end of flat-top",
+ "Ratio of central solenoid current at beginning of Flat-top / "
+ "end of flat-top",
"(f_j_cs_start_end_flat_top)",
self.data.pf_coil.f_j_cs_start_end_flat_top,
"OP ",
@@ -2896,7 +2895,8 @@ def waveform(self):
self.data.pf_coil.c_pf_cs_coil_pulse_start_ma[ic]
)
- # Beginning of flat-top, t = t_plant_pulse_coil_precharge + t_plant_pulse_plasma_current_ramp_up
+ # Beginning of flat-top,
+ # t = t_plant_pulse_coil_precharge + t_plant_pulse_plasma_current_ramp_up
if (
abs(self.data.pf_coil.c_pf_cs_coil_flat_top_ma[ic])
>= abs(self.data.pf_coil.c_pf_cs_coil_pulse_start_ma[ic])
@@ -2908,7 +2908,9 @@ def waveform(self):
self.data.pf_coil.c_pf_cs_coil_flat_top_ma[ic]
)
- # End of flat-top, t = t_plant_pulse_coil_precharge + t_plant_pulse_plasma_current_ramp_up + t_plant_pulse_fusion_ramp + t_plant_pulse_burn
+ # End of flat-top,
+ # t = t_plant_pulse_coil_precharge + t_plant_pulse_plasma_current_ramp_up
+ # + t_plant_pulse_fusion_ramp + t_plant_pulse_burn
if (
abs(self.data.pf_coil.c_pf_cs_coil_pulse_end_ma[ic])
>= abs(self.data.pf_coil.c_pf_cs_coil_pulse_end_ma[ic])
@@ -3095,8 +3097,9 @@ def calculate_cs_turn_geometry_eu_demo(
Returns
-------
- CSEUDEMOTurnGeometry:
- Data class to hold the geometry parameters of a CS turn using the EU DEMO stadium-shaped model
+ :
+ Data class to hold the geometry parameters of a CS turn using
+ the EU DEMO stadium-shaped model
Notes
@@ -3156,35 +3159,41 @@ def place_cs_filaments(
c_cs_flat_top_end: float,
f_j_cs_start_pulse_end_flat_top: float,
nfxf: int,
- ):
- """Places central solenoid (CS) filaments and assigns their positions and currents.
+ ) -> tuple[list[float], list[float], list[float]]:
+ """Places central solenoid (CS) filaments and assigns their
+ positions and currents.
- This function calculates the radial (R) and vertical (Z) positions, as well as the current values,
- for a set of CS filaments based on the provided parameters. Each filament is placed symmetrically
- about the midplane, and currents are assigned according to the flat-top end current and scaling factors.
+ This function calculates the radial (R) and vertical (Z) positions,
+ as well as the current values, for a set of CS filaments based on
+ the provided parameters.
+ Each filament is placed symmetrically about the midplane,
+ and currents are assigned according to the flat-top end current
+ and scaling factors.
Parameters
----------
- n_cs_current_filaments : int
+ n_cs_current_filaments:
Number of CS current filaments to place (per side).
- r_cs_middle : float
+ r_cs_middle:
Radial coordinate of the middle of the CS.
- z_cs_inside_half : float
+ z_cs_inside_half:
Half-height of the CS in the vertical (Z) direction.
- c_cs_flat_top_end : float
+ c_cs_flat_top_end:
Flat-top end current for the CS.
- f_j_cs_start_pulse_end_flat_top : float
+ f_j_cs_start_pulse_end_flat_top:
Scaling factor for the CS current at the start of the pulse and flat-top end.
- nfxf : int
+ nfxf:
Number of flux loops or scaling factor for current distribution.
Returns
-------
- tuple[list[float], list[float], list[float]]
- Tuple containing:
- - r_pf_cs_current_filaments (list of float): Radial positions of the CS filaments.
- - z_pf_cs_current_filaments (list of float): Vertical positions of the CS filaments.
- - c_pf_cs_current_filaments (list of float): Current values assigned to each CS filament.
+ :
+ - r_pf_cs_current_filaments:
+ Radial positions of the CS filaments.
+ - z_pf_cs_current_filaments:
+ Vertical positions of the CS filaments.
+ - c_pf_cs_current_filaments:
+ Current values assigned to each CS filament.
"""
r_pf_cs_current_filaments = np.zeros(NFIXMX)
z_pf_cs_current_filaments = np.zeros(NFIXMX)
@@ -3318,7 +3327,8 @@ def ohcalc(self):
)
# Peak field at the End-Of-Flattop (EOF)
- # Occurs at inner edge of coil; b_cs_self_peak_flat_top_end and b_pf_inner_vertical are of opposite sign at EOF
+ # Occurs at inner edge of coil; b_cs_self_peak_flat_top_end and
+ # b_pf_inner_vertical are of opposite sign at EOF
# Peak field due to central Solenoid itself
b_cs_self_peak_flat_top_end = self.calculate_cs_self_peak_magnetic_field(
@@ -3355,7 +3365,8 @@ def ohcalc(self):
bohco = abs(b_pf_outer_vertical)
# Peak field at the Beginning-Of-Pulse (BOP)
- # Occurs at inner edge of coil; b_cs_peak_pulse_start and b_pf_inner_vertical are of same sign at BOP
+ # Occurs at inner edge of coil; b_cs_peak_pulse_start and b_pf_inner_vertical
+ # are of same sign at BOP
self.data.pf_coil.b_cs_peak_pulse_start = (
self.calculate_cs_self_peak_magnetic_field(
j_cs=self.data.pf_coil.j_cs_pulse_start,
@@ -3427,7 +3438,8 @@ def ohcalc(self):
a_cs_toroidal=self.data.pf_coil.a_cs_toroidal,
)
- # Create vertical profile of the self-axial stress in the CS coil, for fatigue calculations
+ # Create vertical profile of the self-axial stress in the CS coil,
+ # for fatigue calculations
for i, position in enumerate(
np.linspace(
-self.data.pf_coil.z_cs_upper,
@@ -3448,7 +3460,8 @@ def ohcalc(self):
* 1.0e6,
a_cs_toroidal=self.data.pf_coil.a_cs_toroidal,
)
- # If the stress value is NaN (e.g., due to a division by zero or other numerical issue), set it to 0.0
+ # If the stress value is NaN (e.g., due to a division by zero or other
+ # numerical issue), set it to 0.0
# The value will always be NaN at the top and bottom of the coil
self.data.pf_coil.stress_z_cs_self_profile[i] = (
0.0 if np.isnan(stress_value) else stress_value
@@ -3539,8 +3552,8 @@ def ohcalc(self):
self.data.pf_coil.a_cs_poloidal - self.data.pf_coil.a_cs_steel_poloidal
)
- # Issue #97. Fudge to ensure a_cs_cable_space is positive; result is continuous, smooth and
- # monotonically decreases
+ # Issue #97. Fudge to ensure a_cs_cable_space is positive; result is continuous,
+ # smooth and monotonically decreases
da = 0.0001e0 # 1 cm^2
if self.data.pf_coil.a_cs_cable_space < da:
@@ -3700,7 +3713,8 @@ def calculate_cs_bore_magnetic_field(
r_cs_outer: float,
dz_cs_half: float,
) -> float:
- """Calculates the magnetic field at the centre of the bore of a solenoid of circular winding and rectangular cross-section.
+ """Calculates the magnetic field at the centre of the bore of a solenoid of
+ circular winding and rectangular cross-section.
Parameters
----------
@@ -3743,7 +3757,8 @@ def calculate_cs_self_peak_magnetic_field(
r_cs_outer: float,
dz_cs_half: float,
) -> float:
- """Calculates the maximum field of a solenoid of circular winding and rectangular cross-section.
+ """Calculates the maximum field of a solenoid of circular winding and
+ rectangular cross-section.
Parameters
----------
@@ -4399,7 +4414,8 @@ def calculate_cs_radial_stress(
def peak_b_field_at_pf_coil(
n_coil: int, n_coil_group: int, t_b_field_peak: int, data: DataStructure
) -> tuple[float, float, float, float]:
- """Calculates the peak magnetic field components at the inner and outer edges of a given PF coil.
+ """Calculates the peak magnetic field components at the inner and outer edges
+ of a given PF coil.
Parameters
----------
@@ -4423,7 +4439,8 @@ def peak_b_field_at_pf_coil(
Notes
-----
- This routine calculates the peak magnetic field components at the inner and outer edges of a given PF coil.
+ This routine calculates the peak magnetic field components at the inner and
+ outer edges of a given PF coil.
The calculation includes the effects from all the coils and the plasma.
"""
if data.build.iohcl != 0 and n_coil == data.pf_coil.n_cs_pf_coils:
@@ -4694,14 +4711,23 @@ def superconpf(
Superconducting strand non-copper critical current density [A/m²] (j_crit_sc)
Temperature margin [K] (tmarg)
"""
+
+ def j_crit_cable_frac(j_crit_sc, fcu, fhe):
+ """
+ j_crit_cable = j_crit_sc *
+ non-copper fraction of conductor * conductor fraction of cable
+ """
+ return j_crit_sc * (1.0e0 - fcu) * (1.0e0 - fhe)
+
# Find critical current density in superconducting strand, jcritstr
if isumat == SuperconductorModel.ITER_NB3SN:
# ITER Nb3Sn critical surface parameterization
bc20m = 32.97e0 # [T] critical field at 0 K and 0 strain
tc0m = 16.06e0 # [K] critical temperature at 0 T and 0 strain
- # j_crit_sc returned by superconductors.itersc is the critical current density in the
- # superconductor - not the whole strand, which contains copper
+ # j_crit_sc returned by superconductors.itersc is
+ # the critical current density in the superconductor
+ # - not the whole strand, which contains copper
j_crit_sc, _, _ = superconductors.itersc(
temp_conductor=temp_pf_peak_field,
@@ -4710,10 +4736,7 @@ def superconpf(
b_c20max=bc20m,
temp_c0max=tc0m,
)
- # j_crit_cable = j_crit_sc * non-copper fraction of conductor * conductor fraction of cable
- j_crit_cable = j_crit_sc * (1.0e0 - fcu) * (1.0e0 - fhe)
-
- # =================================================================
+ j_crit_cable = j_crit_cable_frac(j_crit_sc, fcu, fhe)
elif isumat == SuperconductorModel.BI2212:
# Bi-2212 high temperature superconductor parameterization
@@ -4736,8 +4759,6 @@ def superconpf(
# j_crit_cable / non-copper fraction of conductor
j_crit_sc = j_crit_cable / (1.0e0 - fcu)
- # =================================================================
-
elif isumat == SuperconductorModel.OLD_LUBELL_NBTI:
# NbTi data
bc20m = 15.0e0 # [T] critical field at 0 K and 0 strain
@@ -4750,10 +4771,7 @@ def superconpf(
b_c20max=bc20m,
temp_c0max=tc0m,
)
- # j_crit_cable = j_crit_sc * non-copper fraction of conductor * conductor fraction of cable
- j_crit_cable = j_crit_sc * (1.0e0 - fcu) * (1.0e0 - fhe)
-
- # =================================================================
+ j_crit_cable = j_crit_cable_frac(j_crit_sc, fcu, fhe)
elif isumat == SuperconductorModel.USER_DEFINED_NB3SN:
# As (1), but user-defined parameters
@@ -4766,18 +4784,15 @@ def superconpf(
b_c20max=bc20m,
temp_c0max=tc0m,
)
- # j_crit_cable = j_crit_sc * non-copper fraction of conductor * conductor fraction of cable
- j_crit_cable = j_crit_sc * (1.0e0 - fcu) * (1.0e0 - fhe)
-
- # =================================================================
+ j_crit_cable = j_crit_cable_frac(j_crit_sc, fcu, fhe)
elif isumat == SuperconductorModel.WST_NB3SN:
# WST Nb3Sn parameterisation
bc20m = 32.97e0 # [T] critical field at 0 K and 0 strain
tc0m = 16.06e0 # [K] critical temperature at 0 T and 0 strain
- # j_crit_sc returned by superconductors.itersc is the critical current density in the
- # superconductor - not the whole strand, which contains copper
+ # j_crit_sc returned by superconductors.itersc is the critical current density
+ # in the superconductor - not the whole strand, which contains copper
j_crit_sc, _, _ = superconductors.western_superconducting_nb3sn(
temp_conductor=temp_pf_peak_field,
@@ -4786,20 +4801,14 @@ def superconpf(
b_c20max=bc20m,
temp_c0max=tc0m,
)
- # j_crit_cable = j_crit_sc * non-copper fraction of conductor * conductor fraction of cable
- j_crit_cable = j_crit_sc * (1.0e0 - fcu) * (1.0e0 - fhe)
-
- # =================================================================
+ j_crit_cable = j_crit_cable_frac(j_crit_sc, fcu, fhe)
elif isumat == SuperconductorModel.CROCO_REBCO:
# "REBCO" 2nd generation HTS superconductor in CrCo strand
j_crit_sc, _, _, _ = superconductors.jcrit_rebco(
temp_conductor=temp_pf_peak_field, b_conductor=b_pf_peak
)
- # j_crit_cable = j_crit_sc * non-copper fraction of conductor * conductor fraction of cable
- j_crit_cable = j_crit_sc * (1.0e0 - fcu) * (1.0e0 - fhe)
-
- # =================================================================
+ j_crit_cable = j_crit_cable_frac(j_crit_sc, fcu, fhe)
elif isumat == SuperconductorModel.DURHAM_NBTI:
# Durham Ginzburg-Landau critical surface model for Nb-Ti
@@ -4812,10 +4821,7 @@ def superconpf(
b_c20max=bc20m,
t_c0=tc0m,
)
- # j_crit_cable = j_crit_sc * non-copper fraction of conductor * conductor fraction of cable
- j_crit_cable = j_crit_sc * (1.0e0 - fcu) * (1.0e0 - fhe)
-
- # =================================================================
+ j_crit_cable = j_crit_cable_frac(j_crit_sc, fcu, fhe)
elif isumat == SuperconductorModel.DURHAM_REBCO:
# Durham Ginzburg-Landau critical surface model for REBCO
@@ -4829,10 +4835,7 @@ def superconpf(
t_c0=tc0m,
)
# A0 calculated for tape cross section already
- # j_crit_cable = j_crit_sc * non-copper fraction of conductor * conductor fraction of cable
- j_crit_cable = j_crit_sc * (1.0e0 - fcu) * (1.0e0 - fhe)
-
- # =================================================================
+ j_crit_cable = j_crit_cable_frac(j_crit_sc, fcu, fhe)
elif isumat == SuperconductorModel.HAZELTON_ZHAI_REBCO:
# Hazelton experimental data + Zhai conceptual model for REBCO
@@ -4848,8 +4851,7 @@ def superconpf(
dx_hts_tape_total=dx_hts_tape_total,
)
# A0 calculated for tape cross section already
- # j_crit_cable = j_crit_sc * non-copper fraction of conductor * conductor fraction of cable
- j_crit_cable = j_crit_sc * (1.0e0 - fcu) * (1.0e0 - fhe)
+ j_crit_cable = j_crit_cable_frac(j_crit_sc, fcu, fhe)
else:
# Error condition
@@ -4918,7 +4920,8 @@ def calculate_b_field_at_point(
r_test_point: float,
z_test_point: float,
) -> tuple[np.ndarray, float, float, float]:
- """Calculate the magnetic field and mutual inductance at a point due to currents in circular poloidal conductor loops.
+ """Calculate the magnetic field and mutual inductance at a point due to currents in
+ circular poloidal conductor loops.
Parameters
----------
@@ -4944,8 +4947,10 @@ def calculate_b_field_at_point(
Notes
-----
- - This routine calculates the magnetic field components and the poloidal flux at a given (R, Z) point,
- given the locations and currents of a set of conductor loops. The mutual inductances between the loops
+ This routine calculates the magnetic field components and the poloidal flux
+ at a given (R, Z) point, given the locations and currents of a set of
+ conductor loops.
+ The mutual inductances between the loops
and a poloidal filament at the (R, Z) point of interest are also computed.
"""
# Elliptic integral coefficients
diff --git a/process/models/physics/bootstrap_current.py b/process/models/physics/bootstrap_current.py
index acb7409f80..95f161a423 100644
--- a/process/models/physics/bootstrap_current.py
+++ b/process/models/physics/bootstrap_current.py
@@ -277,21 +277,23 @@ def get_bootstrap_current_fraction_value(
float
The bootstrap current fraction value.
"""
+ cd = self.data.current_drive
+ bs_cf_m = BootstrapCurrentFractionModel
model_map = {
- BootstrapCurrentFractionModel.USER_INPUT: self.data.current_drive.f_c_plasma_bootstrap,
- BootstrapCurrentFractionModel.ITER_89: self.data.current_drive.f_c_plasma_bootstrap_iter89,
- BootstrapCurrentFractionModel.NEVINS: self.data.current_drive.f_c_plasma_bootstrap_nevins,
- BootstrapCurrentFractionModel.WILSON: self.data.current_drive.f_c_plasma_bootstrap_wilson,
- BootstrapCurrentFractionModel.SAUTER: self.data.current_drive.f_c_plasma_bootstrap_sauter,
- BootstrapCurrentFractionModel.SAKAI: self.data.current_drive.f_c_plasma_bootstrap_sakai,
- BootstrapCurrentFractionModel.ARIES: self.data.current_drive.f_c_plasma_bootstrap_aries,
- BootstrapCurrentFractionModel.ANDRADE: self.data.current_drive.f_c_plasma_bootstrap_andrade,
- BootstrapCurrentFractionModel.HOANG: self.data.current_drive.f_c_plasma_bootstrap_hoang,
- BootstrapCurrentFractionModel.WONG: self.data.current_drive.f_c_plasma_bootstrap_wong,
- BootstrapCurrentFractionModel.GI_1: self.data.current_drive.bscf_gi_i,
- BootstrapCurrentFractionModel.GI_2: self.data.current_drive.bscf_gi_ii,
- BootstrapCurrentFractionModel.SUGIYAMA_L_MODE: self.data.current_drive.f_c_plasma_bootstrap_sugiyama_l,
- BootstrapCurrentFractionModel.SUGIYAMA_H_MODE: self.data.current_drive.f_c_plasma_bootstrap_sugiyama_h,
+ bs_cf_m.USER_INPUT: cd.f_c_plasma_bootstrap,
+ bs_cf_m.ITER_89: cd.f_c_plasma_bootstrap_iter89,
+ bs_cf_m.NEVINS: cd.f_c_plasma_bootstrap_nevins,
+ bs_cf_m.WILSON: cd.f_c_plasma_bootstrap_wilson,
+ bs_cf_m.SAUTER: cd.f_c_plasma_bootstrap_sauter,
+ bs_cf_m.SAKAI: cd.f_c_plasma_bootstrap_sakai,
+ bs_cf_m.ARIES: cd.f_c_plasma_bootstrap_aries,
+ bs_cf_m.ANDRADE: cd.f_c_plasma_bootstrap_andrade,
+ bs_cf_m.HOANG: cd.f_c_plasma_bootstrap_hoang,
+ bs_cf_m.WONG: cd.f_c_plasma_bootstrap_wong,
+ bs_cf_m.GI_1: cd.bscf_gi_i,
+ bs_cf_m.GI_2: cd.bscf_gi_ii,
+ bs_cf_m.SUGIYAMA_L_MODE: cd.f_c_plasma_bootstrap_sugiyama_l,
+ bs_cf_m.SUGIYAMA_H_MODE: cd.f_c_plasma_bootstrap_sugiyama_h,
}
return model_map[model]
@@ -1277,7 +1279,8 @@ def output(self):
)
po.ocmmnt(
self.outfile,
- f"Bootstrap current fraction model selected: {BootstrapCurrentFractionModel(self.data.physics.i_bootstrap_current).full_name} ",
+ "Bootstrap current fraction model selected: "
+ f"{BootstrapCurrentFractionModel(self.data.physics.i_bootstrap_current).full_name} ", # noqa: E501
)
po.oblnkl(self.outfile)
diff --git a/process/models/physics/confinement_time.py b/process/models/physics/confinement_time.py
index 60a629f44b..817d8c4b91 100644
--- a/process/models/physics/confinement_time.py
+++ b/process/models/physics/confinement_time.py
@@ -1404,7 +1404,8 @@ def output_confinement_comparison(self, istell: int):
po.ocmmnt(
self.outfile,
f"{'':>2}{scaling_name:<38}"
- f"{confinement_time_data.t_plasma_energy_confinement:<28.3f}{self.data.physics.hfac[i_confinement_time - 1]:.3f}",
+ f"{confinement_time_data.t_plasma_energy_confinement:<28.3f}"
+ f"{self.data.physics.hfac[i_confinement_time - 1]:.3f}",
)
po.oblnkl(self.outfile)
diff --git a/process/models/physics/current_drive.py b/process/models/physics/current_drive.py
index e6133c51bb..de9d2ded97 100644
--- a/process/models/physics/current_drive.py
+++ b/process/models/physics/current_drive.py
@@ -1804,14 +1804,14 @@ def current_drive(self):
# Calculate the normalised current drive efficieny for the primary
# heating method
- self.data.current_drive.eta_cd_norm_hcd_primary = self.calculate_normalised_current_drive_efficiency(
+ self.data.current_drive.eta_cd_norm_hcd_primary = self.calculate_normalised_current_drive_efficiency( # noqa: E501
eta_cd_hcd=self.data.current_drive.eta_cd_hcd_primary,
nd_plasma_electrons_vol_avg=self.data.physics.nd_plasma_electrons_vol_avg,
rmajor=self.data.physics.rmajor,
)
# Calculate the normalised current drive efficieny for the secondary
# heating method
- self.data.current_drive.eta_cd_norm_hcd_secondary = self.calculate_normalised_current_drive_efficiency(
+ self.data.current_drive.eta_cd_norm_hcd_secondary = self.calculate_normalised_current_drive_efficiency( # noqa: E501
eta_cd_hcd=self.data.current_drive.eta_cd_hcd_secondary,
nd_plasma_electrons_vol_avg=self.data.physics.nd_plasma_electrons_vol_avg,
rmajor=self.data.physics.rmajor,
@@ -1854,8 +1854,9 @@ def current_drive(self):
/ self.data.physics.plasma_current
)
- # Calculate the dimensionless current drive efficiency for the primary heating method (ζ)
- self.data.current_drive.eta_cd_dimensionless_hcd_primary = self.calculate_dimensionless_current_drive_efficiency(
+ # Calculate the dimensionless current drive efficiency for
+ # the primary heating method (ζ)
+ self.data.current_drive.eta_cd_dimensionless_hcd_primary = self.calculate_dimensionless_current_drive_efficiency( # noqa: E501
nd_plasma_electrons_vol_avg=self.data.physics.nd_plasma_electrons_vol_avg,
rmajor=self.data.physics.rmajor,
temp_plasma_electron_vol_avg_kev=self.data.physics.temp_plasma_electron_vol_avg_kev,
@@ -1866,7 +1867,7 @@ def current_drive(self):
if self.data.current_drive.p_hcd_secondary_injected_mw > 0.0:
# Calculate the dimensionless current drive efficiency for the secondary
# heating method (ζ)
- self.data.current_drive.eta_cd_dimensionless_hcd_secondary = self.calculate_dimensionless_current_drive_efficiency(
+ self.data.current_drive.eta_cd_dimensionless_hcd_secondary = self.calculate_dimensionless_current_drive_efficiency( # noqa: E501
nd_plasma_electrons_vol_avg=self.data.physics.nd_plasma_electrons_vol_avg,
rmajor=self.data.physics.rmajor,
temp_plasma_electron_vol_avg_kev=self.data.physics.temp_plasma_electron_vol_avg_kev,
diff --git a/process/models/physics/physics.py b/process/models/physics/physics.py
index 49995a5ed7..71874aef0e 100644
--- a/process/models/physics/physics.py
+++ b/process/models/physics/physics.py
@@ -812,8 +812,9 @@ def run(self):
self.data.physics.p_neutron_total_mw / self.data.physics.a_plasma_surface
)
- # KLUDGE: Ensure p_plasma_separatrix_mw is continuously positive (physical, rather than
- # negative potential power), as required by other models (e.g.
+ # KLUDGE: Ensure p_plasma_separatrix_mw is continuously positive
+ # (physical, rather than negative potential power),
+ # as required by other models (e.g.
# Physics.calculate_density_limit())
self.data.physics.p_plasma_separatrix_mw /= 1 - np.exp(
-self.data.physics.p_plasma_separatrix_mw
@@ -1065,7 +1066,9 @@ def run(self):
po.write(
self.outfile,
(
- f"reinke t and fz, physics = {self.data.physics.temp_plasma_separatrix_kev} , {self.data.reinke.fzmin}"
+ "reinke t and fz, physics = "
+ f"{self.data.physics.temp_plasma_separatrix_kev} , "
+ f"{self.data.reinke.fzmin}"
),
)
fgw = (
@@ -1095,7 +1098,7 @@ def run(self):
self.outfile,
(
f" 'fzactual, frac, impvardiv = {self.data.reinke.fzactual},"
- f" {self.data.impurity_radiation.f_nd_impurity_electron_array(self.data.reinke.impvardiv)},"
+ f" {self.data.impurity_radiation.f_nd_impurity_electron_array(self.data.reinke.impvardiv)}," # noqa: E501
f" {self.data.reinke.impvardiv}"
),
)
@@ -3284,7 +3287,7 @@ def get_beta_norm_max_value(
model_map = {
BetaNormMaxModel.USER_INPUT: physics_data.beta_norm_max,
BetaNormMaxModel.WESSON: physics_data.beta_norm_max_wesson,
- BetaNormMaxModel.ORIGINAL_SCALING: physics_data.beta_norm_max_original_scaling,
+ BetaNormMaxModel.ORIGINAL_SCALING: physics_data.beta_norm_max_original_scaling, # noqa: E501
BetaNormMaxModel.MENARD: physics_data.beta_norm_max_menard,
BetaNormMaxModel.THOLERUS: physics_data.beta_norm_max_tholerus,
BetaNormMaxModel.STAMBAUGH: physics_data.beta_norm_max_stambaugh,
@@ -4277,7 +4280,7 @@ def run(self):
self.calculate_internal_inductance_menard(kappa=self.data.physics.kappa)
)
- self.data.physics.ind_plasma_internal_norm_iter_3 = self.calculate_normalised_internal_inductance_iter_3(
+ self.data.physics.ind_plasma_internal_norm_iter_3 = self.calculate_normalised_internal_inductance_iter_3( # noqa: E501
b_plasma_poloidal_vol_avg=self.data.physics.b_plasma_surface_poloidal_average,
c_plasma=self.data.physics.plasma_current,
vol_plasma=self.data.physics.vol_plasma,
@@ -4307,8 +4310,8 @@ def get_ind_internal_norm_value(self, model: IndInternalNormModel) -> float:
"""
model_map = {
IndInternalNormModel.USER_INPUT: self.data.physics.ind_plasma_internal_norm,
- IndInternalNormModel.WESSON: self.data.physics.ind_plasma_internal_norm_wesson,
- IndInternalNormModel.MENARD: self.data.physics.ind_plasma_internal_norm_menard,
+ IndInternalNormModel.WESSON: self.data.physics.ind_plasma_internal_norm_wesson, # noqa: E501
+ IndInternalNormModel.MENARD: self.data.physics.ind_plasma_internal_norm_menard, # noqa: E501
}
return model_map[model]
@@ -4661,7 +4664,7 @@ def output_volt_second_information(self):
po.ocmmnt(
self.outfile,
f"Normalised internal inductance model selected: "
- f"{IndInternalNormModel(self.data.physics.i_ind_plasma_internal_norm).full_name} ",
+ f"{IndInternalNormModel(self.data.physics.i_ind_plasma_internal_norm).full_name} ", # noqa: E501
)
po.ovarre(
self.outfile,
@@ -4717,7 +4720,7 @@ def run(self):
# Debye length calculation
# ---------------------------
- self.data.physics.len_plasma_debye_electron_vol_avg = self.calculate_debye_length(
+ self.data.physics.len_plasma_debye_electron_vol_avg = self.calculate_debye_length( # noqa: E501
temp_plasma_species_kev=self.data.physics.temp_plasma_electron_vol_avg_kev,
nd_plasma_species=self.data.physics.nd_plasma_electrons_vol_avg,
)
@@ -4882,12 +4885,12 @@ def run(self):
# Upper hybrid frequencies
# ============================
- self.data.physics.freq_plasma_upper_hybrid_vol_avg = self.calculate_upper_hybrid_frequency(
+ self.data.physics.freq_plasma_upper_hybrid_vol_avg = self.calculate_upper_hybrid_frequency( # noqa: E501
freq_plasma=self.data.physics.freq_plasma_electron_vol_avg,
freq_larmor=self.data.physics.freq_plasma_larmor_toroidal_electron_vol_avg,
)
- self.data.physics.freq_plasma_upper_hybrid_profile = self.calculate_upper_hybrid_frequency(
+ self.data.physics.freq_plasma_upper_hybrid_profile = self.calculate_upper_hybrid_frequency( # noqa: E501
freq_plasma=np.concatenate([
self.data.physics.freq_plasma_electron_profile[::-1],
self.data.physics.freq_plasma_electron_profile,
@@ -4902,7 +4905,7 @@ def run(self):
# Since isotropic (v⟂)² = 2(v)² for a Maxwellian distribution,
# we can use the total velocity to calculate the Larmor radius for an isotropic
# profile
- self.data.physics.radius_plasma_deuteron_toroidal_larmor_isotropic_vol_avg = self.calculate_larmor_radius(
+ self.data.physics.radius_plasma_deuteron_toroidal_larmor_isotropic_vol_avg = self.calculate_larmor_radius( # noqa: E501
vel_perp=np.sqrt(2 * self.data.physics.vel_plasma_deuteron_vol_avg**2),
freq_larmor=self.data.physics.freq_plasma_larmor_toroidal_deuteron_vol_avg
* (2 * np.pi),
@@ -4911,7 +4914,7 @@ def run(self):
# Since isotropic (v⟂)² = 2(v)² for a Maxwellian distribution,
# we can use the total velocity to calculate the Larmor radius for an isotropic
# profile
- self.data.physics.radius_plasma_deuteron_toroidal_larmor_isotropic_profile = self.calculate_larmor_radius(
+ self.data.physics.radius_plasma_deuteron_toroidal_larmor_isotropic_profile = self.calculate_larmor_radius( # noqa: E501
vel_perp=np.sqrt(
2
* np.concatenate([
@@ -5201,7 +5204,7 @@ def run(self):
for i in range(len(self.data.physics.len_plasma_debye_electron_profile))
])
- self.data.physics.plasma_coulomb_log_electron_alpha_thermal_vol_avg = self.calculate_coulomb_log_from_impact(
+ self.data.physics.plasma_coulomb_log_electron_alpha_thermal_vol_avg = self.calculate_coulomb_log_from_impact( # noqa: E501
impact_param_max=self.data.physics.len_plasma_debye_electron_vol_avg,
impact_param_min=max(
self.calculate_classical_distance_of_closest_approach(
@@ -5268,19 +5271,19 @@ def run(self):
# Collision times
# ============================
- self.data.physics.t_plasma_electron_electron_collision_vol_avg = self.calculate_electron_electron_collision_time(
+ self.data.physics.t_plasma_electron_electron_collision_vol_avg = self.calculate_electron_electron_collision_time( # noqa: E501
temp_plasma_electron_kev=self.data.physics.temp_plasma_electron_vol_avg_kev,
nd_plasma_electrons=self.data.physics.nd_plasma_electrons_vol_avg,
plasma_coulomb_log_electron_electron=self.data.physics.plasma_coulomb_log_electron_electron_vol_avg,
)
- self.data.physics.t_plasma_electron_electron_collision_profile = self.calculate_electron_electron_collision_time(
+ self.data.physics.t_plasma_electron_electron_collision_profile = self.calculate_electron_electron_collision_time( # noqa: E501
temp_plasma_electron_kev=self.plasma_profile.teprofile.profile_y,
nd_plasma_electrons=self.plasma_profile.neprofile.profile_y,
plasma_coulomb_log_electron_electron=self.data.physics.plasma_coulomb_log_electron_electron_profile,
)
- self.data.physics.t_plasma_electron_deuteron_collision_vol_avg = self.calculate_electron_ion_collision_time(
+ self.data.physics.t_plasma_electron_deuteron_collision_vol_avg = self.calculate_electron_ion_collision_time( # noqa: E501
temp_plasma_electron_kev=self.data.physics.temp_plasma_electron_vol_avg_kev,
nd_plasma_ions=(
self.data.physics.nd_plasma_electrons_vol_avg
@@ -5294,7 +5297,7 @@ def run(self):
n_charge_ion=1,
)
- self.data.physics.t_plasma_electron_deuteron_collision_profile = self.calculate_electron_ion_collision_time(
+ self.data.physics.t_plasma_electron_deuteron_collision_profile = self.calculate_electron_ion_collision_time( # noqa: E501
temp_plasma_electron_kev=self.plasma_profile.teprofile.profile_y,
nd_plasma_ions=(
self.plasma_profile.neprofile.profile_y
@@ -5308,7 +5311,7 @@ def run(self):
n_charge_ion=1,
)
- self.data.physics.t_plasma_electron_triton_collision_vol_avg = self.calculate_electron_ion_collision_time(
+ self.data.physics.t_plasma_electron_triton_collision_vol_avg = self.calculate_electron_ion_collision_time( # noqa: E501
temp_plasma_electron_kev=self.data.physics.temp_plasma_electron_vol_avg_kev,
nd_plasma_ions=(
self.data.physics.nd_plasma_electrons_vol_avg
@@ -5322,7 +5325,7 @@ def run(self):
n_charge_ion=1,
)
- self.data.physics.t_plasma_electron_triton_collision_profile = self.calculate_electron_ion_collision_time(
+ self.data.physics.t_plasma_electron_triton_collision_profile = self.calculate_electron_ion_collision_time( # noqa: E501
temp_plasma_electron_kev=self.plasma_profile.teprofile.profile_y,
nd_plasma_ions=(
self.plasma_profile.neprofile.profile_y
@@ -5336,7 +5339,7 @@ def run(self):
n_charge_ion=1,
)
- self.data.physics.t_plasma_electron_alpha_thermal_collision_vol_avg = self.calculate_electron_ion_collision_time(
+ self.data.physics.t_plasma_electron_alpha_thermal_collision_vol_avg = self.calculate_electron_ion_collision_time( # noqa: E501
temp_plasma_electron_kev=self.data.physics.temp_plasma_electron_vol_avg_kev,
nd_plasma_ions=(
self.data.physics.nd_plasma_electrons_vol_avg
@@ -5349,7 +5352,7 @@ def run(self):
n_charge_ion=2,
)
- self.data.physics.t_plasma_electron_alpha_thermal_collision_profile = self.calculate_electron_ion_collision_time(
+ self.data.physics.t_plasma_electron_alpha_thermal_collision_profile = self.calculate_electron_ion_collision_time( # noqa: E501
temp_plasma_electron_kev=self.plasma_profile.teprofile.profile_y,
nd_plasma_ions=(
self.plasma_profile.neprofile.profile_y
@@ -5446,7 +5449,7 @@ def run(self):
# Spitzer slow down time
# ============================
- self.data.physics.t_plasma_electron_alpha_spitzer_slow_vol_avg = self.calculate_spitzer_ion_slowing_down_time(
+ self.data.physics.t_plasma_electron_alpha_spitzer_slow_vol_avg = self.calculate_spitzer_ion_slowing_down_time( # noqa: E501
m_ion=constants.ALPHA_MASS,
plasma_coulomb_log_electron_ion=self.data.physics.plasma_coulomb_log_electron_alpha_thermal_vol_avg,
temp_plasma_electrons_kev=self.data.physics.temp_plasma_electron_vol_avg_kev,
@@ -5454,7 +5457,7 @@ def run(self):
n_charge_ion=2,
)
- self.data.physics.t_plasma_electron_alpha_spitzer_slow_profile = self.calculate_spitzer_ion_slowing_down_time(
+ self.data.physics.t_plasma_electron_alpha_spitzer_slow_profile = self.calculate_spitzer_ion_slowing_down_time( # noqa: E501
m_ion=constants.ALPHA_MASS,
plasma_coulomb_log_electron_ion=self.data.physics.plasma_coulomb_log_electron_alpha_thermal_profile,
temp_plasma_electrons_kev=self.plasma_profile.teprofile.profile_y,
@@ -5466,13 +5469,13 @@ def run(self):
# Resistivites
# ============================
- self.data.physics.res_plasma_fuel_spitzer_vol_avg = self.calculate_spitzer_resistivity(
+ self.data.physics.res_plasma_fuel_spitzer_vol_avg = self.calculate_spitzer_resistivity( # noqa: E501
n_charge=1,
electron_ion_coulomb_log=self.data.physics.plasma_coulomb_log_electron_deuteron_vol_avg,
temp_plasma_electron_kev=self.data.physics.temp_plasma_electron_vol_avg_kev,
)
- self.data.physics.res_plasma_fuel_spitzer_profile = self.calculate_spitzer_resistivity(
+ self.data.physics.res_plasma_fuel_spitzer_profile = self.calculate_spitzer_resistivity( # noqa: E501
n_charge=1,
electron_ion_coulomb_log=self.data.physics.plasma_coulomb_log_electron_deuteron_profile,
temp_plasma_electron_kev=self.plasma_profile.teprofile.profile_y,
diff --git a/process/models/physics/plasma_geometry.py b/process/models/physics/plasma_geometry.py
index d54deb78dd..dd9c29cccc 100644
--- a/process/models/physics/plasma_geometry.py
+++ b/process/models/physics/plasma_geometry.py
@@ -421,9 +421,9 @@ def run(self):
== PlasmaGeometryModelType.MENARD_1997_X_POINT
):
# self.data.physics.triang is an input
- # self.data.physics.kappa found from self.data.physics.aspect ratio scaling from
- # J.E. Menard et al 1997 Nucl. Fusion 37 595 and assume max controllable kappa
- # and assume lᵢ(3) is held constant
+ # self.data.physics.kappa found from self.data.physics.aspect ratio scaling
+ # from J.E. Menard et al 1997 Nucl. Fusion 37 595 and
+ # assume max controllable kappa and assume lᵢ(3) is held constant
self.data.physics.kappa = (
2.93e0 * (1.8e0 / self.data.physics.aspect) ** 0.4e0
diff --git a/process/models/physics/profiles.py b/process/models/physics/profiles.py
index df083e82bb..b694f04769 100644
--- a/process/models/physics/profiles.py
+++ b/process/models/physics/profiles.py
@@ -282,7 +282,9 @@ def ncore(
return ncore
def set_pedestal_and_separatrix_values(self):
- """Sets the pedestal and separatrix density values based on the user input or greenwald fraction method."""
+ """Sets the pedestal and separatrix density values based on the user input
+ or greenwald fraction method.
+ """
i_nd_plasma_pedestal_separatrix = DensityProfilePedestalType(
self.data.physics.i_nd_plasma_pedestal_separatrix
)
diff --git a/process/models/stellarator/build.py b/process/models/stellarator/build.py
index 9f1f5601e2..a7a2edd46c 100644
--- a/process/models/stellarator/build.py
+++ b/process/models/stellarator/build.py
@@ -71,7 +71,8 @@ def st_build(stellarator, f_output: bool, data: DataStructure):
+ data.physics.rminor
)
- # Bc stellarators cannot scale data.physics.rminor reasonably well an additional constraint equation is required,
+ # Bc stellarators cannot scale data.physics.rminor reasonably well
+ # an additional constraint equation is required,
# that ensures that there is enough space between coils and plasma.
data.build.required_radial_space = (
data.build.dr_tf_inboard / 2.0e0
@@ -83,7 +84,8 @@ def st_build(stellarator, f_output: bool, data: DataStructure):
+ data.build.dr_fw_plasma_gap_inboard
)
- # derivative_min_LCFS_coils_dist for how strong the stellarator shape changes wrt to aspect ratio
+ # derivative_min_LCFS_coils_dist for how strong the stellarator shape
+ # changes wrt to aspect ratio
data.build.available_radial_space = (
data.stellarator.r_coil_minor * data.stellarator.f_coil_shape
- data.physics.rminor
diff --git a/process/models/stellarator/coils/calculate.py b/process/models/stellarator/coils/calculate.py
index 3bd26a9324..129ae460f2 100644
--- a/process/models/stellarator/coils/calculate.py
+++ b/process/models/stellarator/coils/calculate.py
@@ -38,7 +38,6 @@ def st_coil(stellarator, output: bool, data: DataStructure):
r_coil_major = data.stellarator.r_coil_major
r_coil_minor = data.stellarator.r_coil_minor
- #######################################################################################
calculate_winding_pack_geometry(data)
# Total coil current (MA)
@@ -48,17 +47,14 @@ def st_coil(stellarator, output: bool, data: DataStructure):
winding_pack_total_size(r_coil_major, r_coil_minor, coilcurrent, data)
)
- #######################################################################################
- # Casing calculations
+ # Casing calculations
calculate_casing(data)
- #######################################################################################
- # Port calculations
+ # Port calculations
calculate_vertical_ports(data)
calculate_horizontal_ports(data)
- #######################################################################################
- # General Coil Geometry values
+ # General Coil Geometry values
#
calculate_coil_toroidal_thickness(data)
calculate_coil_radial_thickness(data)
@@ -78,7 +74,7 @@ def st_coil(stellarator, output: bool, data: DataStructure):
inductance = calculate_inductance(r_coil_minor, data)
calculate_stored_magnetic_energy(r_coil_minor, data)
- # Coil dimensions
+ # Coil dimensions
data.build.z_tf_inside_half = (
0.5e0
* data.stellarator_config.stella_config_maximal_coil_height
@@ -113,16 +109,13 @@ def st_coil(stellarator, output: bool, data: DataStructure):
# End of general coil geometry values
- #######################################################################################
- # Coil_mases calculations
+ # Coil_mases calculations
calculate_coils_mass(a_tf_wp_with_insulation, a_tf_wp_no_insulation, data)
- #######################################################################################
# Quench protection:
f_vv_actual = calculate_quench_protection(coilcurrent, data)
#
- #######################################################################################
# Forces scaling #
forces.calculate_max_force_density(a_tf_wp_no_insulation, data)
forces.calculate_maximum_stress(data)
@@ -140,8 +133,6 @@ def st_coil(stellarator, output: bool, data: DataStructure):
centering_force_max_mn = forces.calculate_centering_force_max_mn(data)
centering_force_min_mn = forces.calculate_centering_force_min_mn(data)
centering_force_avg_mn = forces.calculate_centering_force_avg_mn(data)
- #
- ####################################
if output:
write(
@@ -222,7 +213,8 @@ def calculate_plasma_facing_coil_area(data: DataStructure):
* 0.5e0
* data.tfcoil.len_tf_coil
)
- # [m^2] Total surface area of coil side facing plasma: outboard region (same as inboard)
+ # [m^2] Total surface area of coil side facing plasma: outboard region
+ # (same as inboard)
data.tfcoil.tfsao = data.tfcoil.tfsai
@@ -287,7 +279,8 @@ def calculate_coils_summary_variables(
def calculate_inductance(r_coil_minor, data: DataStructure):
- """This uses the reference value for the inductance and scales it with a^2/R (toroid inductance scaling)
+ """This uses the reference value for the inductance and scales it with a^2/R
+ (toroid inductance scaling)
Parameters
----------
@@ -333,21 +326,26 @@ def calculate_winding_pack_geometry(data: DataStructure):
"""
# [m] Dimension of square cable space inside insulation
- # and case of the conduit of each turn
+ # and case of the conduit of each turn
dx_tf_turn_cable_space_average = data.tfcoil.dx_tf_turn_general - 2.0e0 * (
data.tfcoil.dx_tf_turn_steel + data.tfcoil.dx_tf_turn_insulation
) # dx_tf_turn_cable_space_average = t_w
if dx_tf_turn_cable_space_average < 0:
logger.warning(
- "Warning: Negative cable space dimension in TF coil winding pack. Check input parameters."
+ "Warning: Negative cable space dimension in TF coil winding pack. "
+ "Check input parameters."
)
logger.info(
- "dx_tf_turn_cable_space_average is negative. Check t_turn, data.tfcoil.dx_tf_turn_steel and dx_tf_turn_insulation."
+ "dx_tf_turn_cable_space_average is negative. "
+ "Check t_turn, data.tfcoil.dx_tf_turn_steel and dx_tf_turn_insulation."
)
# [m^2] Cross-sectional area of cable space per turn
- data.tfcoil.a_tf_turn_cable_space_no_void = (
- 0.9e0 * dx_tf_turn_cable_space_average**2
- ) # 0.9 to include some rounded corners. (data.tfcoil.a_tf_turn_cable_space_no_void = pi (dx_tf_turn_cable_space_average/2)**2 = pi/4 *dx_tf_turn_cable_space_average**2 for perfect round conductor). This factor depends on how round the corners are.
+ # 0.9 to include some rounded corners.
+ # (data.tfcoil.a_tf_turn_cable_space_no_void =
+ # pi (dx_tf_turn_cable_space_average/2)**2 =
+ # pi/4 *dx_tf_turn_cable_space_average**2 for perfect round conductor).
+ # This factor depends on how round the corners are.
+ data.tfcoil.a_tf_turn_cable_space_no_void = 0.9e0 * dx_tf_turn_cable_space_average**2
# [m^2] Cross-sectional area of conduit case per turn
data.tfcoil.a_tf_turn_steel = (
dx_tf_turn_cable_space_average + 2.0e0 * data.tfcoil.dx_tf_turn_steel
@@ -395,7 +393,7 @@ def winding_pack_total_size(
r_coil_minor / 1.0e0 - r_coil_minor / 150.0e0
)
- # B-field calculation
+ # B-field calculation
b_max_k[k] = bmax_from_awp(
wp_width_r[k],
coilcurrent,
@@ -450,7 +448,8 @@ def winding_pack_total_size(
r_coil_minor / 20.0e0
) ** 2 # If REBCO, : start at smaller winding pack ratios
- # Find the intersection between LHS and RHS (or: how much awp do I need to get to the desired coil current)
+ # Find the intersection between LHS and RHS
+ # (or: how much awp do I need to get to the desired coil current)
wp_width_r_min = intersect(wp_width_r, lhs, wp_width_r, rhs, wp_width_r_min)
# Maximum field at superconductor surface (T)
@@ -482,7 +481,7 @@ def winding_pack_total_size(
awp_rad # [m] radial thickness of winding pack
)
- # [m^2] winding-pack cross sectional area including insulation (not global)
+ # [m^2] winding-pack cross sectional area including insulation (not global)
a_tf_wp_with_insulation = (
data.tfcoil.dr_tf_wp_with_insulation + 2.0e0 * data.tfcoil.dx_tf_wp_insulation
) * (data.tfcoil.dx_tf_wp_primary_toroidal + 2.0e0 * data.tfcoil.dx_tf_wp_insulation)
@@ -547,9 +546,10 @@ def calculate_casing(data: DataStructure):
def calculate_vertical_ports(data: DataStructure):
- # Maximal toroidal port size (vertical ports) (m)
- # The maximal distance is correct but the vertical extension of this port is not clear#
- # This is simplified for now and can be made more accurate in the future#
+ # Maximal toroidal port size (vertical ports) (m)
+ # The maximal distance is correct
+ # but the vertical extension of this port is not clear
+ # This is simplified for now and can be made more accurate in the future#
data.stellarator.vporttmax = (
0.4e0
* data.stellarator_config.stella_config_max_portsize_width
@@ -557,15 +557,15 @@ def calculate_vertical_ports(data: DataStructure):
/ data.stellarator.f_st_n_coils
) # This is not accurate yet. Needs more insight#
- # Maximal poloidal port size (vertical ports) (m)
+ # Maximal poloidal port size (vertical ports) (m)
data.stellarator.vportpmax = 2.0 * data.stellarator.vporttmax # Simple approximation
- # Maximal vertical port clearance area (m2)
+ # Maximal vertical port clearance area (m2)
data.stellarator.vportamax = data.stellarator.vporttmax * data.stellarator.vportpmax
def calculate_horizontal_ports(data: DataStructure):
- # Maximal toroidal port size (horizontal ports) (m)
+ # Maximal toroidal port size (horizontal ports) (m)
data.stellarator.hporttmax = (
0.8e0
* data.stellarator_config.stella_config_max_portsize_width
@@ -573,10 +573,10 @@ def calculate_horizontal_ports(data: DataStructure):
/ data.stellarator.f_st_n_coils
) # Factor 0.8 to take the variation with height into account
- # Maximal poloidal port size (horizontal ports) (m)
+ # Maximal poloidal port size (horizontal ports) (m)
data.stellarator.hportpmax = (
2.0e0 * data.stellarator.hporttmax
) # Simple approximation
- # Maximal horizontal port clearance area (m2)
+ # Maximal horizontal port clearance area (m2)
data.stellarator.hportamax = data.stellarator.hporttmax * data.stellarator.hportpmax
diff --git a/process/models/stellarator/coils/coils.py b/process/models/stellarator/coils/coils.py
index 95076a46bb..5b16e1122c 100644
--- a/process/models/stellarator/coils/coils.py
+++ b/process/models/stellarator/coils/coils.py
@@ -9,6 +9,14 @@
logger = logging.getLogger(__name__)
+def j_crit_cable_from_fraction(j_crit_sc, f_tf_conductor_copper, f_he):
+ """j_crit_cable = (
+ j_crit_sc * non-copper fraction of conductor * conductor fraction of cable
+ )
+ """
+ return j_crit_sc * (1.0 - f_tf_conductor_copper) * (1.0e0 - f_he)
+
+
def jcrit_from_material(
b_max,
t_helium,
@@ -23,7 +31,9 @@ def jcrit_from_material(
j_wp,
):
strain = -0.005 # for now a small value
- f_he = f_a_tf_turn_cable_space_extra_void # this is helium fraction in the superconductor (set it to the fixed global variable here)
+ # this is helium fraction in the superconductor
+ # (set it to the fixed global variable here)
+ f_he = f_a_tf_turn_cable_space_extra_void
f_tf_conductor_copper = (
f_a_tf_turn_cable_copper # fcutfsu is a global variable. Is the copper fraction
@@ -45,8 +55,7 @@ def jcrit_from_material(
_tcrit,
) = superconductors.itersc(t_helium, b_max, strain, bc20m, tc0m)
- # j_crit_cable = j_crit_sc * non-copper fraction of conductor * conductor fraction of cable
- j_crit_cable = j_crit_sc * (1.0 - f_tf_conductor_copper) * (1.0e0 - f_he)
+ j_crit_cable = j_crit_cable_from_fraction(j_crit_sc, f_tf_conductor_copper, f_he)
# This is needed right now. Can we change it later?
j_crit_sc = max(1.0e-9, j_crit_sc)
@@ -87,9 +96,7 @@ def jcrit_from_material(
)
# I dont need tcrit here so dont use it.
- # j_crit_cable = j_crit_sc * non-copper fraction of conductor * conductor fraction of cable
- j_crit_cable = j_crit_sc * (1 - f_tf_conductor_copper) * (1 - f_he)
-
+ j_crit_cable = j_crit_cable_from_fraction(j_crit_sc, f_tf_conductor_copper, f_he)
# This is needed right now. Can we change it later?
j_crit_sc = max(1.0e-9, j_crit_sc)
j_crit_cable = max(1.0e-9, j_crit_cable)
@@ -99,8 +106,7 @@ def jcrit_from_material(
j_crit_sc, _bcrit, _tcrit = superconductors.itersc(
t_helium, b_max, strain, bc20m, tc0m
)
- # j_crit_cable = j_crit_sc * non-copper fraction of conductor * conductor fraction of cable
- j_crit_cable = j_crit_sc * (1 - f_tf_conductor_copper) * (1 - f_he)
+ j_crit_cable = j_crit_cable_from_fraction(j_crit_sc, f_tf_conductor_copper, f_he)
elif i_tf_sc_mat == 5: # WST Nb3Sn parameterisation
bc20m = 32.97
tc0m = 16.06
@@ -115,13 +121,12 @@ def jcrit_from_material(
bc20m,
tc0m,
)
- # j_crit_cable = j_crit_sc * non-copper fraction of conductor * conductor fraction of cable
- j_crit_cable = j_crit_sc * (1 - f_tf_conductor_copper) * (1 - f_he)
+ j_crit_cable = j_crit_cable_from_fraction(j_crit_sc, f_tf_conductor_copper, f_he)
+
elif i_tf_sc_mat == 6: # ! "REBCO" 2nd generation HTS superconductor in CrCo strand
j_crit_sc, _validity, _, _ = superconductors.jcrit_rebco(t_helium, b_max, 0)
j_crit_sc = max(1.0e-9, j_crit_sc)
- # j_crit_cable = j_crit_sc * non-copper fraction of conductor * conductor fraction of cable
- j_crit_cable = j_crit_sc * (1 - f_tf_conductor_copper) * (1 - f_he)
+ j_crit_cable = j_crit_cable_from_fraction(j_crit_sc, f_tf_conductor_copper, f_he)
elif i_tf_sc_mat == 7: # Durham Ginzburg-Landau Nb-Ti parameterisation
bc20m = b_crit_upper_nbti
@@ -129,8 +134,8 @@ def jcrit_from_material(
j_crit_sc, _bcrit, _tcrit = superconductors.gl_nbti(
t_helium, b_max, strain, bc20m, tc0m
)
- # j_crit_cable = j_crit_sc * non-copper fraction of conductor * conductor fraction of cable
- j_crit_cable = j_crit_sc * (1 - f_tf_conductor_copper) * (1 - f_he)
+ j_crit_cable = j_crit_cable_from_fraction(j_crit_sc, f_tf_conductor_copper, f_he)
+
elif i_tf_sc_mat == 8:
bc20m = 429
tc0m = 185
@@ -138,8 +143,8 @@ def jcrit_from_material(
t_helium, b_max, strain, bc20m, tc0m
)
# A0 calculated for tape cross section already
- # j_crit_cable = j_crit_sc * non-copper fraction of conductor * conductor fraction of cable
- j_crit_cable = j_crit_sc * (1 - f_tf_conductor_copper) * (1 - f_he)
+ j_crit_cable = j_crit_cable_from_fraction(j_crit_sc, f_tf_conductor_copper, f_he)
+
else:
raise ProcessValueError(
"Illegal value for i_pf_superconductor", i_tf_sc_mat=i_tf_sc_mat
diff --git a/process/models/stellarator/coils/forces.py b/process/models/stellarator/coils/forces.py
index 46901f3b16..d4775fe5c6 100644
--- a/process/models/stellarator/coils/forces.py
+++ b/process/models/stellarator/coils/forces.py
@@ -4,7 +4,8 @@
def calculate_max_force_density(a_tf_wp_no_insulation, data: DataStructure):
- """Calculate the maximum force density in the TF coil winding pack from scaling. [MN/m3]
+ """Calculate the maximum force density in the TF coil winding pack from scaling.
+ [MN/m3]
Parameters
----------
@@ -25,7 +26,9 @@ def calculate_max_force_density(a_tf_wp_no_insulation, data: DataStructure):
def calculate_max_force_density_mnm(data: DataStructure):
- """Calculate the maximum force per meter in the TF coil winding pack from scaling. [MN/m]"""
+ """Calculate the maximum force per meter in the TF coil winding pack from scaling.
+ [MN/m]
+ """
return (
data.stellarator_config.stella_config_max_force_density_mnm
* data.stellarator.f_st_i_total
@@ -36,14 +39,17 @@ def calculate_max_force_density_mnm(data: DataStructure):
def calculate_maximum_stress(data):
- """Approximate, very simple maxiumum stress (needed for limitation of icc 32), in Pa"""
+ """Approximate, very simple maxiumum stress (needed for limitation of icc 32),
+ in Pa
+ """
data.tfcoil.sig_tf_wp = (
data.tfcoil.max_force_density * data.tfcoil.dr_tf_wp_with_insulation * 1.0e6
)
def calculate_max_lateral_force_density(a_tf_wp_no_insulation, data: DataStructure):
- """Calculate the maximum lateral force density in the TF coil winding pack from scaling. [MN/m3]
+ """Calculate the maximum lateral force density in the TF coil winding pack
+ from scaling. [MN/m3]
Parameters
----------
@@ -64,7 +70,8 @@ def calculate_max_lateral_force_density(a_tf_wp_no_insulation, data: DataStructu
def calculate_max_radial_force_density(a_tf_wp_no_insulation, data):
- """Calculate the maximum radial force density in the TF coil winding pack from scaling. [MN/m3]
+ """Calculate the maximum radial force density in the TF coil winding pack
+ from scaling. [MN/m3]
Parameters
----------
diff --git a/process/models/stellarator/coils/mass.py b/process/models/stellarator/coils/mass.py
index 21b459edb5..bd9e486a73 100644
--- a/process/models/stellarator/coils/mass.py
+++ b/process/models/stellarator/coils/mass.py
@@ -7,10 +7,13 @@
def calculate_coils_mass(
a_tf_wp_with_insulation: float, a_tf_wp_no_insulation: float, data: DataStructure
):
- """Calculates the mass of stellarator coils by aggregating the masses of various coil components.
+ """Calculates the mass of stellarator coils by aggregating the masses of
+ various coil components.
- This function computes the masses of conductor constituents (casing, ground insulation, superconductor, copper),
- conduit masses (steel and insulation), and then calculates the total conductor and coil masses.
+ This function computes the masses of conductor constituents
+ (casing, ground insulation, superconductor, copper),
+ conduit masses (steel and insulation),
+ and then calculates the total conductor and coil masses.
Parameters
----------
@@ -39,7 +42,8 @@ def calculate_coils_mass(
def casing(data: DataStructure):
"""[kg] Mass of case
(no need for correction factors as is the case for tokamaks)
- This is only correct if the winding pack is 'thin' (len_tf_coil>>sqrt(data.tfcoil.a_tf_coil_inboard_case)).
+ This is only correct if the winding pack is 'thin'
+ (len_tf_coil>>sqrt(data.tfcoil.a_tf_coil_inboard_case)).
"""
data.tfcoil.m_tf_coil_case = (
@@ -104,12 +108,16 @@ def conduit_steel(data):
* data.tfcoil.a_tf_turn_steel
* data.fwbs.den_steel
)
- # if (i_tf_sc_mat==6) data.tfcoil.m_tf_wp_steel_conduit = fcondsteel * a_tf_wp_no_insulation *data.tfcoil.len_tf_coil* fwbs_variables.denstl
+ # if (i_tf_sc_mat==6)
+ # data.tfcoil.m_tf_wp_steel_conduit = (
+ # fcondsteel * a_tf_wp_no_insulation *data.tfcoil.len_tf_coil* fwbs_variables.denstl
+ # )
def conduit_insulation(data: DataStructure):
"""Conduit insulation mass [kg]
- (data.tfcoil.a_tf_coil_wp_turn_insulation already contains data.tfcoil.n_tf_coil_turns)
+ (data.tfcoil.a_tf_coil_wp_turn_insulation
+ already contains data.tfcoil.n_tf_coil_turns)
"""
data.tfcoil.m_tf_coil_wp_turn_insulation = (
diff --git a/process/models/stellarator/coils/quench.py b/process/models/stellarator/coils/quench.py
index a9830a6267..7ad8a1cc82 100644
--- a/process/models/stellarator/coils/quench.py
+++ b/process/models/stellarator/coils/quench.py
@@ -7,8 +7,8 @@
def calculate_quench_protection(coilcurrent, data: DataStructure):
"""Calculate quench protecion limits for stellarator coils
- Includes calculation of the vacuum vessel force density, quench protection current density
- and max dump voltage during quench
+ Includes calculation of the vacuum vessel force density,
+ quench protection current density and max dump voltage during quench
Parameters
----------
@@ -38,15 +38,17 @@ def calculate_quench_protection(coilcurrent, data: DataStructure):
+ data.build.dr_shld_outboard
)
- # Stellarator version is working on the W7-X scaling, so we should actual use vv r_major
- # plasma r_major is just an approximation, but exact calculations require 3D geometry
+ # Stellarator version is working on the W7-X scaling, so we should actual use vv
+ # r_major, plasma r_major is just an approximation,
+ # but exact calculations require 3D geometry
# Maybe it can be added to the stella_config file in the future
rad_vv = data.physics.rmajor
# MN/m^3
f_vv_actual = calculate_vv_max_force_density_from_W7X_scaling(rad_vv, data)
- # This approach merge stress model from tokamaks with induced force calculated from W7-X scaling
+ # This approach merge stress model from tokamaks with induced force calculated
+ # from W7-X scaling
a_vv = (rad_vv_out + rad_vv_in) / (rad_vv_out - rad_vv_in)
zeta = 1 + ((a_vv - 1) * np.log((a_vv + 1) / (a_vv - 1)) / (2 * a_vv))
@@ -160,8 +162,10 @@ def calculate_quench_protection_current_density(
Simplified 0-D adiabatic heat balance "hotspot criterion" model.
- This is slightly diffrent that tokamak version (also diffrent from the stellarator paper).
- We skip the superconduc6tor contribution (this should be more conservative in theory).
+ This is slightly diffrent that tokamak version
+ (also diffrent from the stellarator paper).
+ We skip the superconduc6tor contribution
+ (this should be more conservative in theory).
Parameters
----------
@@ -176,7 +180,8 @@ def calculate_quench_protection_current_density(
temp :
peak helium coolant temperature in TF coils and PF coils (K)
a_cable :
- Cable space area (per turn) [m2] (Includes the area of voids and central helium channel)
+ Cable space area (per turn) [m2]
+ (Includes the area of voids and central helium channel)
a_turn :
TF coil turn cross section area [m2]
"""
diff --git a/process/models/stellarator/denisty_limits.py b/process/models/stellarator/denisty_limits.py
index 8ca3f5b7eb..29ee05f33c 100644
--- a/process/models/stellarator/denisty_limits.py
+++ b/process/models/stellarator/denisty_limits.py
@@ -147,11 +147,14 @@ def st_d_limit_ecrh(gyro_frequency_max, bt_input, i_plasma_pedestal):
def power_at_ignition_point(stellarator, gyro_frequency_max, te0_available):
- """Routine to calculate if the plasma is ignitable with the current values for the B field. Assumes
- current ECRH achievable peak temperature (which is inaccurate as the cordey pass should be calculated)
+ """Calculate if the plasma is ignitable with the current values for the B field.
+
+ Assumes current ECRH achievable peak temperature
+ (which is inaccurate as the cordey pass should be calculated)
This routine calculates the density limit due to an ECRH heating scheme on axis
- Assumes current peak temperature (which is inaccurate as the cordey pass should be calculated)
+ Assumes current peak temperature
+ (which is inaccurate as the cordey pass should be calculated)
Maybe use this: https://doi.org/10.1088/0029-5515/49/8/085026
Parameters
@@ -196,10 +199,10 @@ def power_at_ignition_point(stellarator, gyro_frequency_max, te0_available):
bt_ecrh_max, proxy_stellarator.data.physics.b_plasma_toroidal_on_axis
)
+ # The second call seems to be necessary for all values to "converge"
+ # (and is sufficient)
+ proxy_stellarator.st_phys(False)
proxy_stellarator.st_phys(False)
- proxy_stellarator.st_phys(
- False
- ) # The second call seems to be necessary for all values to "converge" (and is sufficient)
powerht_out = max(
proxy_stellarator.data.physics.p_plasma_loss_mw, 0.00001e0
diff --git a/process/models/stellarator/divertor.py b/process/models/stellarator/divertor.py
index cb8f0988fb..42c86a2917 100644
--- a/process/models/stellarator/divertor.py
+++ b/process/models/stellarator/divertor.py
@@ -30,66 +30,67 @@ def st_div(stellarator, f_output: bool, data: DataStructure):
xi_p = data.divertor.xpertin
T_scrape = data.divertor.tdiv
- # Scrape-off temperature in Joules
+ # Scrape-off temperature in Joules
e = T_scrape * constants.ELECTRON_CHARGE
- # Sound speed of particles (m/s)
+ # Sound speed of particles (m/s)
c_s = np.sqrt(e / (data.physics.m_fuel_amu * constants.UMASS))
- # Island size (m)
+ # Island size (m)
w_r = 4.0e0 * np.sqrt(
data.stellarator.bmn * r / (data.stellarator.shear * data.stellarator.n_res)
)
- # Perpendicular (to plate) distance from X-point to divertor plate (m)
+ # Perpendicular (to plate) distance from X-point to divertor plate (m)
Delta = data.stellarator.f_w * w_r
- # Length 'along' plasma (m)
+ # Length 'along' plasma (m)
l_p = 2 * np.pi * r * (data.stellarator.m_res) / data.stellarator.n_res
- # Connection length from X-point to divertor plate (m)
+ # Connection length from X-point to divertor plate (m)
l_x_t = Delta / Theta
- # Power decay length (m)
+ # Power decay length (m)
l_q = np.sqrt(xi_p * (l_x_t / c_s))
- # Channel broadening length (m)
+ # Channel broadening length (m)
l_b = np.sqrt(xi_p * l_p / (c_s))
- # Channel broadening factor
+ # Channel broadening factor
f_x = 1.0e0 + (l_b / (l_p * Theta))
- # Length of a single divertor plate (m)
+ # Length of a single divertor plate (m)
l_d = f_x * l_p * (Theta / alpha)
- # Total length of divertor plates (m)
+ # Total length of divertor plates (m)
l_t = 2.0e0 * data.stellarator.n_res * l_d
- # Wetted area (m2)
+ # Wetted area (m2)
a_eff = l_t * l_q
- # Divertor plate width (m): assume total area is wetted area/data.stellarator.fdivwet
+ # Divertor plate width (m): assume total area is
+ # wetted area/data.stellarator.fdivwet
darea = a_eff / data.stellarator.fdivwet
l_w = darea / l_t
- # Divertor heat load (MW/m2)
+ # Divertor heat load (MW/m2)
q_div = data.stellarator.f_asym * (p_div / a_eff)
- # Transfer to global variables
+ # Transfer to global variables
data.divertor.pflux_div_heat_load_mw = q_div
data.divertor.a_div_surface_total = darea
@@ -101,12 +102,12 @@ def st_div(stellarator, f_output: bool, data: DataStructure):
def output(stellarator, a_eff, l_d, l_w, f_x, l_q, w_r, Delta, data: DataStructure):
- """Outputs a summary of divertor-related parameters and results to the stellartor object.
- stellarator: An object containing stellarator configuration and output handle.
+ """Outputs a summary of divertor-related stellarator parameters and results
- The function writes various physical and geometric parameters related to the divertor,
- including power, angles, heat transport coefficients, resonance numbers, field perturbations,
- and other relevant quantities, to the output file associated with the stellarator object.
+ The function writes various physical and geometric parameters related to
+ the divertor, including power, angles, heat transport coefficients,
+ resonance numbers, field perturbations, and other relevant quantities,
+ to the output file associated with the stellarator object.
Parameters
----------
diff --git a/process/models/stellarator/neoclassics.py b/process/models/stellarator/neoclassics.py
index 9eec4689f1..bd41fcaef4 100644
--- a/process/models/stellarator/neoclassics.py
+++ b/process/models/stellarator/neoclassics.py
@@ -277,7 +277,8 @@ def init_profile_values_from_PROCESS(self, rho):
def calc_neoclassics(self):
if self.data.stellarator_config.stella_config_epseff < 0:
logger.error(
- f"epseff value lower than 0: {self.data.stellarator_config.stella_config_epseff}"
+ "epseff value lower than 0: "
+ f"{self.data.stellarator_config.stella_config_epseff}"
)
self.init_neoclassics(
0.6,
@@ -442,7 +443,8 @@ def neoclassics_calc_nu(self):
z = np.array([-1.0, 1.0, 1.0, 2.0]) * constants.ELECTRON_CHARGE
# transform the temperature back in eV
- # Formula from L. Spitzer.Physics of fully ionized gases. Interscience, New York, 1962
+ # Formula from L. Spitzer.Physics of fully ionized gases.
+ # Interscience, New York, 1962
lnlambda = (
32.2
- 1.15 * np.log10(self.data.neoclassics.densities[0])
@@ -562,7 +564,8 @@ def neoclassics_calc_nu_star_fromT(self, iota):
z = np.array([-1.0, 1.0, 1.0, 2.0]) * constants.ELECTRON_CHARGE
# transform the temperature back in eV
- # Formula from L. Spitzer.Physics of fully ionized gases. Interscience, New York, 1962
+ # Formula from L. Spitzer.Physics of fully ionized gases.
+ # Interscience, New York, 1962
lnlambda = (
32.2
- 1.15 * np.log10(density[0])
diff --git a/process/models/stellarator/preset_config.py b/process/models/stellarator/preset_config.py
index 24a8c94413..e9d4438d1c 100644
--- a/process/models/stellarator/preset_config.py
+++ b/process/models/stellarator/preset_config.py
@@ -27,7 +27,8 @@
"coillength": 1680.0, # Central filament length of machine with outer radius 1m.
"I0": 13.06, # Coil Current needed to produce 1T on axis in [MA] at outer radius 1m
"inductance": 1655.76e-6, # inductance in muH
- "WP_ratio": 1.2, # The fit values in stellarator config class should be calculated using this value.
+ # The fit values in stellarator config class should be calculated using this value.
+ "WP_ratio": 1.2,
"max_force_density": 120.0, # [MN/m^3]
"max_force_density_mnm": 98.0, # [MN/m]
"max_lateral_force_density": 92.4, # [MN/m^3]
diff --git a/process/models/stellarator/stellarator.py b/process/models/stellarator/stellarator.py
index a56a1deb9f..72f5328c0a 100644
--- a/process/models/stellarator/stellarator.py
+++ b/process/models/stellarator/stellarator.py
@@ -55,23 +55,23 @@ class Stellarator(Model):
Parameters
----------
availability:
- A pointer to the availability model, allowing use of availability's variables/methods
+ The availability model
buildings:
- A pointer to the buildings model, allowing use of buildings's variables/methods
- Vacuum:
- A pointer to the vacuum model, allowing use of vacuum's variables/methods
+ The buildings model
+ vacuum:
+ The vacuum model
costs:
- A pointer to the costs model, allowing use of costs' variables/methods
+ The costs model
plasma_profile:
- A pointer to the plasma_profile model, allowing use of plasma_profile's variables/methods
+ The plasma_profile model
hcpb:
- A pointer to the ccfe_hcpb model, allowing use of ccfe_hcpb's variables/methods
+ The ccfe_hcpb model
current_drive:
- A pointer to the CurrentDrive model, allowing use of CurrentDrives's variables/methods
+ The CurrentDrive model
physics:
- A pointer to the Physics model, allowing use of Physics's variables/methods
+ The Physics model
neoclassics:
- A pointer to the Neoclassics model, allowing use of neoclassics's variables/methods
+ The Neoclassics model
"""
def __init__(
@@ -195,7 +195,8 @@ def st_new_config(self):
It overwrites rminor with rmajor and aspect ratio e.g.
To clarify the coils scaling factor:
- Coil aspect ratio factor can be described with the reversed equation (so if we would know r_coil_minor)
+ Coil aspect ratio factor can be described with the reversed equation
+ (so if we would know r_coil_minor)
f_coil_aspect = (
(self.data.physics.rmajor / self.data.stellarator.r_coil_minor) /
(self.data.stellarator_config.stella_config_rmajor_ref /
@@ -209,7 +210,8 @@ def st_new_config(self):
self.data,
)
- # If self.data.physics.aspect ratio is not in self.data.numerics.ixc set it to default value
+ # If self.data.physics.aspect ratio is not in self.data.numerics.ixc
+ # set it to default value
# Or when you call it the first time
if 1 not in self.data.numerics.ixc:
self.data.physics.aspect = (
@@ -247,7 +249,8 @@ def st_new_config(self):
/ self.data.stellarator_config.stella_config_bt_ref
) # B-field scaling factor
- # Coil aspect ratio factor to the reference calculation (we use it to scale the coil minor radius)
+ # Coil aspect ratio factor to the reference calculation
+ # (we use it to scale the coil minor radius)
f_coil_aspect = self.data.stellarator.f_st_coil_aspect
# Coil major radius, scaled with respect to the reference calculation
@@ -303,9 +306,10 @@ def st_geom(self):
np.pi * self.data.physics.rminor * self.data.physics.rminor
) # average, could be calculated for every toroidal angle if desired
- # self.data.physics.a_plasma_surface_outboard is retained only for obsolescent fispact calculation...
+ # self.data.physics.a_plasma_surface_outboard is retained
+ # only for obsolescent fispact calculation...
- # Cross-sectional area, averaged over toroidal angle
+ # Cross-sectional area, averaged over toroidal angle
self.data.physics.a_plasma_surface_outboard = (
0.5e0 * self.data.physics.a_plasma_surface
) # Used only in the divertor model; approximate as for tokamaks
@@ -326,17 +330,17 @@ def st_strc(self, output):
"""
self.data.structure.fncmass = 0.0e0
- # Reactor core gravity support mass
+ # Reactor core gravity support mass
self.data.structure.gsmass = 0.0e0 # ? Not sure about this.
# This is the previous scaling law for intercoil structure
# We keep is here as a reference to the new model, which
# we do not really trust yet.
- # Mass of support structure (includes casing) (tonnes)
- # Scaling for required structure mass (Steel) from:
- # F.C. Moon, J. Appl. Phys. 53(12) (1982) 9112
+ # Mass of support structure (includes casing) (tonnes)
+ # Scaling for required structure mass (Steel) from:
+ # F.C. Moon, J. Appl. Phys. 53(12) (1982) 9112
#
- # Values based on regression analysis by Greifswald, March 2014
+ # Values based on regression analysis by Greifswald, March 2014
m_struc = (
1.3483e0
* (1000.0e0 * self.data.tfcoil.e_tf_magnetic_stored_total_gj) ** 0.7821e0
@@ -359,8 +363,10 @@ def st_strc(self, output):
* self.data.tfcoil.n_tf_coils
)
- # This 0.18 m is an effective thickness which is scaled with empirial 1.5 law. 5.6 T is reference point of Helias
- # The thickness 0.18m was obtained as a measured value from Schauer, F. and Bykov, V. design of Helias 5-B. (Nucl Fus. 2013)
+ # This 0.18 m is an effective thickness which is scaled with empirial 1.5 law.
+ # 5.6 T is reference point of Helias
+ # The thickness 0.18m was obtained as a measured value from Schauer,
+ # F. and Bykov, V. design of Helias 5-B. (Nucl Fus. 2013)
self.data.structure.aintmass = (
0.18e0
* (self.data.physics.b_plasma_toroidal_on_axis / 5.6) ** 2
@@ -371,16 +377,17 @@ def st_strc(self, output):
self.data.structure.clgsmass = (
0.2e0 * self.data.structure.aintmass
) # Very simple approximation for the gravity support.
- # This fits for the Helias 5b reactor design point ( F. and Bykov, V. design of Helias 5-B. (nucl Fus. 2013)).
+ # This fits for the Helias 5b reactor design point
+ # (F. and Bykov, V. design of Helias 5-B. (nucl Fus. 2013)).
- # Total mass of cooled components
+ # Total mass of cooled components
self.data.structure.coldmass = (
self.data.tfcoil.m_tf_coils_total
+ self.data.structure.aintmass
+ self.data.fwbs.dewmkg
)
- # Output section
+ # Output section
if output:
po.oheadr(self.outfile, "Support Structure")
@@ -501,13 +508,13 @@ def st_fwbs(self, output: bool):
self.data.costs.life_plant,
)
- # First wall inboard, outboard areas (assume 50% of total each)
+ # First wall inboard, outboard areas (assume 50% of total each)
self.data.first_wall.a_fw_inboard = 0.5e0 * self.data.first_wall.a_fw_total
self.data.first_wall.a_fw_outboard = 0.5e0 * self.data.first_wall.a_fw_total
- # Blanket volume; assume that its surface area is scaled directly from the
- # plasma surface area.
- # Uses self.data.fwbs.fhole etc. to take account of gaps due to ports etc.
+ # Blanket volume; assume that its surface area is scaled directly from the
+ # plasma surface area.
+ # Uses self.data.fwbs.fhole etc. to take account of gaps due to ports etc.
r1 = self.data.physics.rminor + 0.5e0 * (
self.data.build.dr_fw_plasma_gap_inboard
@@ -552,8 +559,8 @@ def st_fwbs(self, output: bool):
self.data.fwbs.vol_blkt_inboard + self.data.fwbs.vol_blkt_outboard
)
- # Shield volume
- # Uses fvolsi, self.data.fwbs.fvolso as area coverage factors
+ # Shield volume
+ # Uses fvolsi, self.data.fwbs.fvolso as area coverage factors
r1 += 0.5e0 * (
self.data.build.dr_blkt_inboard + self.data.build.dr_blkt_outboard
@@ -576,8 +583,8 @@ def st_fwbs(self, output: bool):
)
self.data.fwbs.vol_shld_total = vol_shld_inboard + vol_shld_outboard
- # Neutron power lost through holes in first wall (eventually absorbed by
- # shield)
+ # Neutron power lost through holes in first wall (eventually absorbed by
+ # shield)
self.data.fwbs.pnucloss = (
self.data.physics.p_neutron_total_mw * self.data.fwbs.fhole
@@ -588,7 +595,7 @@ def st_fwbs(self, output: bool):
self.data.stellarator_config.stella_config_neutron_peakfactor
)
- # Blanket neutronics calculations
+ # Blanket neutronics calculations
if self.data.fwbs.blktmodel == 1:
self.blanket_neutronics()
@@ -650,8 +657,8 @@ def st_fwbs(self, output: bool):
)
)
- # Void fraction in first wall / breeding zone,
- # for use in self.data.fwbs.m_fw_total and coolvol calculation below
+ # Void fraction in first wall / breeding zone,
+ # for use in self.data.fwbs.m_fw_total and coolvol calculation below
f_a_fw_coolant_inboard = (
1.0e0
@@ -665,7 +672,7 @@ def st_fwbs(self, output: bool):
self.data.fwbs.pnuc_cp = 0.0e0
if self.data.heat_transport.ipowerflow == 0:
- # Energy-multiplied neutron power
+ # Energy-multiplied neutron power
pneut2 = (
self.data.physics.p_neutron_total_mw
@@ -679,7 +686,7 @@ def st_fwbs(self, output: bool):
- self.data.fwbs.pnuc_cp
)
- # Nuclear heating in the blanket
+ # Nuclear heating in the blanket
decaybl = 0.075e0 / (
1.0e0
@@ -692,12 +699,12 @@ def st_fwbs(self, output: bool):
1.0e0 - np.exp(-self.data.build.dr_blkt_outboard / decaybl)
)
- # Nuclear heating in the shield
+ # Nuclear heating in the shield
self.data.fwbs.p_shld_nuclear_heat_mw = (
pneut2 - self.data.fwbs.p_blkt_nuclear_heat_total_mw
)
- # Superconducting coil shielding calculations
+ # Superconducting coil shielding calculations
(
coilhtmx,
dpacop,
@@ -712,21 +719,21 @@ def st_fwbs(self, output: bool):
) = self.sc_tf_coil_nuclear_heating_iter90()
else: # self.data.heat_transport.ipowerflow == 1
- # Neutron power incident on divertor (MW)
+ # Neutron power incident on divertor (MW)
self.data.fwbs.p_div_nuclear_heat_total_mw = (
self.data.physics.p_neutron_total_mw
* self.data.fwbs.f_ster_div_single
)
- # Neutron power incident on HCD apparatus (MW)
+ # Neutron power incident on HCD apparatus (MW)
self.data.fwbs.p_fw_hcd_nuclear_heat_mw = (
self.data.physics.p_neutron_total_mw
* self.data.fwbs.f_a_fw_outboard_hcd
)
- # Neutron power deposited in first wall, blanket and shield (MW)
+ # Neutron power deposited in first wall, blanket and shield (MW)
pnucfwbs = (
self.data.physics.p_neutron_total_mw
@@ -736,7 +743,7 @@ def st_fwbs(self, output: bool):
- self.data.fwbs.p_fw_hcd_nuclear_heat_mw
)
- # Split between inboard and outboard by first wall area fractions
+ # Split between inboard and outboard by first wall area fractions
pnucfwbsi = (
pnucfwbs
@@ -749,27 +756,27 @@ def st_fwbs(self, output: bool):
/ self.data.first_wall.a_fw_total
)
- # Radiation power incident on divertor (MW)
+ # Radiation power incident on divertor (MW)
self.data.fwbs.p_fw_hcd_rad_total_mw = (
self.data.physics.p_plasma_rad_mw
* self.data.fwbs.f_a_fw_outboard_hcd
)
- # Radiation power incident on HCD apparatus (MW)
+ # Radiation power incident on HCD apparatus (MW)
self.data.fwbs.p_fw_hcd_rad_total_mw = (
self.data.physics.p_plasma_rad_mw
* self.data.fwbs.f_a_fw_outboard_hcd
)
- # Radiation power lost through holes (eventually hits shield) (MW)
+ # Radiation power lost through holes (eventually hits shield) (MW)
self.data.fwbs.pradloss = (
self.data.physics.p_plasma_rad_mw * self.data.fwbs.fhole
)
- # Radiation power incident on first wall (MW)
+ # Radiation power incident on first wall (MW)
self.data.fwbs.p_fw_rad_total_mw = (
self.data.physics.p_plasma_rad_mw
@@ -778,11 +785,11 @@ def st_fwbs(self, output: bool):
- self.data.fwbs.p_fw_hcd_rad_total_mw
)
- # Calculate the power deposited in the first wall, blanket and shield,
- # and the required coolant pumping power
+ # Calculate the power deposited in the first wall, blanket and shield,
+ # and the required coolant pumping power
- # If we have chosen pressurised water as the coolant, set the
- # coolant outlet temperature as 20 deg C below the boiling point
+ # If we have chosen pressurised water as the coolant, set the
+ # coolant outlet temperature as 20 deg C below the boiling point
if self.data.fwbs.i_blkt_coolant_type == CoolantType.WATER:
if self.data.fwbs.irefprop:
@@ -820,12 +827,13 @@ def st_fwbs(self, output: bool):
/ (bfwo * bfwo)
) # outboard FW coolant void fraction
- # First wall decay length (m) - improved calculation required
+ # First wall decay length (m) - improved calculation required
decayfwi = self.data.fwbs.declfw
decayfwo = self.data.fwbs.declfw
- # Surface heat flux on first wall (MW) (sum = self.data.fwbs.p_fw_rad_total_mw)
+ # Surface heat flux on first wall (MW)
+ # (sum = self.data.fwbs.p_fw_rad_total_mw)
psurffwi = (
self.data.fwbs.p_fw_rad_total_mw
@@ -838,14 +846,15 @@ def st_fwbs(self, output: bool):
/ self.data.first_wall.a_fw_total
)
- # Simple blanket model (self.data.fwbs.i_p_coolant_pumping = 0 or 1) is assumed for stellarators
+ # Simple blanket model (self.data.fwbs.i_p_coolant_pumping = 0 or 1) is
+ # assumed for stellarators
- # The power deposited in the first wall, breeder zone and shield is
- # calculated according to their dimensions and materials assuming
- # an exponential attenuation of nuclear heating with increasing
- # radial distance. The pumping power for the coolant is calculated
- # as a fraction of the total thermal power deposited in the
- # coolant.
+ # The power deposited in the first wall, breeder zone and shield is
+ # calculated according to their dimensions and materials assuming
+ # an exponential attenuation of nuclear heating with increasing
+ # radial distance. The pumping power for the coolant is calculated
+ # as a fraction of the total thermal power deposited in the
+ # coolant.
p_fw_inboard_nuclear_heat_mw = pnucfwbsi * (
1.0e0 - np.exp(-2.0e0 * bfwi / decayfwi)
@@ -854,17 +863,17 @@ def st_fwbs(self, output: bool):
1.0e0 - np.exp(-2.0e0 * bfwo / decayfwo)
)
- # Neutron power reaching blanket and shield (MW)
+ # Neutron power reaching blanket and shield (MW)
pnucbsi = pnucfwbsi - p_fw_inboard_nuclear_heat_mw
pnucbso = pnucfwbso - p_fw_outboard_nuclear_heat_mw
- # Blanket decay length (m) - improved calculation required
+ # Blanket decay length (m) - improved calculation required
decaybzi = self.data.fwbs.declblkt
decaybzo = self.data.fwbs.declblkt
- # Neutron power deposited in breeder zone (MW)
+ # Neutron power deposited in breeder zone (MW)
pnucbzi = pnucbsi * (
1.0e0 - np.exp(-self.data.build.dr_blkt_inboard / decaybzi)
@@ -873,18 +882,18 @@ def st_fwbs(self, output: bool):
1.0e0 - np.exp(-self.data.build.dr_blkt_outboard / decaybzo)
)
- # Calculate coolant pumping powers from input fraction.
- # The pumping power is assumed to be a fraction, fpump, of the
- # incident thermal power to each component so that
- # htpmw_i = fpump_i*C, where C is the non-pumping thermal power
- # deposited in the coolant
+ # Calculate coolant pumping powers from input fraction.
+ # The pumping power is assumed to be a fraction, fpump, of the
+ # incident thermal power to each component so that
+ # htpmw_i = fpump_i*C, where C is the non-pumping thermal power
+ # deposited in the coolant
- # First wall and Blanket pumping power (MW)
+ # First wall and Blanket pumping power (MW)
i_p_coolant_pumping = PumpingPowerModelTypes(
self.data.fwbs.i_p_coolant_pumping
)
if i_p_coolant_pumping == PumpingPowerModelTypes.USER_INPUT:
- # Use input
+ # Use input
pass
elif i_p_coolant_pumping == PumpingPowerModelTypes.FRACTION_OF_HEAT:
self.data.heat_transport.p_fw_coolant_pump_mw = (
@@ -915,13 +924,13 @@ def st_fwbs(self, output: bool):
* (self.data.fwbs.f_p_blkt_multiplication - 1.0e0)
)
- # Total nuclear heating of first wall (MW)
+ # Total nuclear heating of first wall (MW)
self.data.fwbs.p_fw_nuclear_heat_total_mw = (
p_fw_inboard_nuclear_heat_mw + p_fw_outboard_nuclear_heat_mw
)
- # Total nuclear heating of blanket (MW)
+ # Total nuclear heating of blanket (MW)
self.data.fwbs.p_blkt_nuclear_heat_total_mw = (
pnucbzi + pnucbzo
@@ -931,14 +940,16 @@ def st_fwbs(self, output: bool):
self.data.fwbs.f_p_blkt_multiplication - 1.0e0
)
- # Calculation of shield and divertor powers
- # Shield and divertor powers and pumping powers are calculated using the same
- # simplified method as the first wall and breeder zone when self.data.fwbs.i_p_coolant_pumping = 1.
- # i.e. the pumping power is a fraction of the total thermal power deposited in the
- # coolant.
+ # Calculation of shield and divertor powers
+ # Shield and divertor powers and pumping powers are calculated using
+ # the same simplified method as the first wall and breeder zone when
+ # self.data.fwbs.i_p_coolant_pumping = 1.
+ # i.e. the pumping power is a fraction of the total thermal power
+ # deposited in the coolant.
- # Neutron power reaching the shield (MW)
- # The power lost from the self.data.fwbs.fhole area fraction is assumed to be incident upon the shield
+ # Neutron power reaching the shield (MW)
+ # The power lost from the self.data.fwbs.fhole area fraction is assumed
+ # to be incident upon the shield
pnucsi = (
pnucbsi
@@ -955,12 +966,12 @@ def st_fwbs(self, output: bool):
/ self.data.first_wall.a_fw_total
)
- # Improved calculation of shield power decay lengths required
+ # Improved calculation of shield power decay lengths required
decayshldi = self.data.fwbs.declshld
decayshldo = self.data.fwbs.declshld
- # Neutron power deposited in the shield (MW)
+ # Neutron power deposited in the shield (MW)
pnucshldi = pnucsi * (
1.0e0 - np.exp(-self.data.build.dr_shld_inboard / decayshldi)
@@ -971,20 +982,20 @@ def st_fwbs(self, output: bool):
self.data.fwbs.p_shld_nuclear_heat_mw = pnucshldi + pnucshldo
- # Calculate coolant pumping powers from input fraction.
- # The pumping power is assumed to be a fraction, fpump, of the incident
- # thermal power to each component so that,
- # htpmw_i = fpump_i*C
- # where C is the non-pumping thermal power deposited in the coolant
+ # Calculate coolant pumping powers from input fraction.
+ # The pumping power is assumed to be a fraction, fpump, of the incident
+ # thermal power to each component so that,
+ # htpmw_i = fpump_i*C
+ # where C is the non-pumping thermal power deposited in the coolant
if i_p_coolant_pumping == PumpingPowerModelTypes.FRACTION_OF_HEAT:
- # Shield pumping power (MW)
+ # Shield pumping power (MW)
self.data.heat_transport.p_shld_coolant_pump_mw = (
self.data.heat_transport.f_p_shld_coolant_pump_total_heat
* (pnucshldi + pnucshldo)
)
- # Divertor pumping power (MW)
+ # Divertor pumping power (MW)
self.data.heat_transport.p_div_coolant_pump_mw = (
self.data.heat_transport.f_p_div_coolant_pump_total_heat
* (
@@ -994,9 +1005,9 @@ def st_fwbs(self, output: bool):
)
)
- # Remaining neutron power to coils and else:where. This is assumed
- # (for superconducting coils at least) to be absorbed by the
- # coils, and so contributes to the cryogenic load
+ # Remaining neutron power to coils and else:where. This is assumed
+ # (for superconducting coils at least) to be absorbed by the
+ # coils, and so contributes to the cryogenic load
if (
self.data.tfcoil.i_tf_sup == TFConductorModel.SUPERCONDUCTING
@@ -1007,9 +1018,9 @@ def st_fwbs(self, output: bool):
else: # resistive coils
self.data.fwbs.p_tf_nuclear_heat_mw = 0.0e0
- # Divertor mass
- # N.B. self.data.divertor.a_div_surface_total is calculated in stdiv after this point, so will
- # be zero on first lap, hence the initial approximation
+ # Divertor mass
+ # N.B. self.data.divertor.a_div_surface_total is calculated in stdiv after this
+ # point, so will be zero on first lap, hence the initial approximation
if self.first_call_stfwbs:
self.data.divertor.a_div_surface_total = 50.0e0
@@ -1022,8 +1033,8 @@ def st_fwbs(self, output: bool):
* self.data.divertor.dx_div_plate
)
- # Start adding components of the coolant mass:
- # Divertor coolant volume (m3)
+ # Start adding components of the coolant mass:
+ # Divertor coolant volume (m3)
coolvol = (
self.data.divertor.a_div_surface_total
@@ -1031,7 +1042,7 @@ def st_fwbs(self, output: bool):
* self.data.divertor.dx_div_plate
)
- # Blanket mass, excluding coolant
+ # Blanket mass, excluding coolant
if self.data.fwbs.blktmodel == 0:
if self.data.fwbs.blkttype in {1, 2}: # liquid breeder (WCLL or HCLL)
@@ -1160,11 +1171,12 @@ def st_fwbs(self, output: bool):
)
)
- # When self.data.fwbs.blktmodel > 0, although the blanket is by definition helium-cooled
- # in this case, the shield etc. are assumed to be water-cooled, and since
- # water is heavier the calculation for self.data.fwbs.m_fw_blkt_div_coolant_total is better done with
- # i_blkt_coolant_type=2 if self.data.fwbs.blktmodel > 0; thus we can ignore the helium coolant mass
- # in the blanket.
+ # When self.data.fwbs.blktmodel > 0, although the blanket is by definition
+ # helium-cooled in this case, the shield etc. are assumed to be water-cooled,
+ # and since water is heavier the calculation for
+ # self.data.fwbs.m_fw_blkt_div_coolant_total is better done with
+ # i_blkt_coolant_type=2 if self.data.fwbs.blktmodel > 0;
+ # thus we can ignore the helium coolant mass in the blanket.
if self.data.fwbs.blktmodel == 0:
coolvol += (
@@ -1180,13 +1192,13 @@ def st_fwbs(self, output: bool):
coolvol += self.data.fwbs.vol_shld_total * self.data.fwbs.vfshld
- # Penetration shield (set = internal shield)
+ # Penetration shield (set = internal shield)
self.data.fwbs.wpenshld = self.data.fwbs.whtshld
if self.data.heat_transport.ipowerflow == 0:
- # First wall mass
- # (first wall area is calculated else:where)
+ # First wall mass
+ # (first wall area is calculated else:where)
self.data.fwbs.m_fw_total = (
self.data.first_wall.a_fw_total
@@ -1196,7 +1208,7 @@ def st_fwbs(self, output: bool):
* (1.0e0 - self.data.fwbs.fwclfr)
)
- # Surface areas adjacent to plasma
+ # Surface areas adjacent to plasma
coolvol += (
self.data.first_wall.a_fw_total
@@ -1224,8 +1236,8 @@ def st_fwbs(self, output: bool):
* f_a_fw_coolant_outboard
)
- # Average first wall coolant fraction, only used by old routines
- # in fispact.f90, safety.f90
+ # Average first wall coolant fraction, only used by old routines
+ # in fispact.f90, safety.f90
self.data.fwbs.fwclfr = (
self.data.first_wall.a_fw_inboard
@@ -1240,10 +1252,10 @@ def st_fwbs(self, output: bool):
* (self.data.build.dr_fw_inboard + self.data.build.dr_fw_outboard)
)
- # Mass of coolant = volume * density at typical coolant
- # temperatures and pressures
- # N.B. for self.data.fwbs.blktmodel > 0, mass of *water* coolant in the non-blanket
- # structures is used (see comment above)
+ # Mass of coolant = volume * density at typical coolant
+ # temperatures and pressures
+ # N.B. for self.data.fwbs.blktmodel > 0, mass of *water* coolant in the
+ # non-blanket structures is used (see comment above)
if (self.data.fwbs.blktmodel > 0) or (
self.data.fwbs.i_blkt_coolant_type == CoolantType.WATER
@@ -1252,11 +1264,11 @@ def st_fwbs(self, output: bool):
else: # gaseous helium coolant
self.data.fwbs.m_fw_blkt_div_coolant_total = coolvol * 1.517e0
- # Assume external cryostat is a torus with circular cross-section,
- # centred on plasma major radius.
- # N.B. No check made to see if coils etc. lie wholly within cryostat...
+ # Assume external cryostat is a torus with circular cross-section,
+ # centred on plasma major radius.
+ # N.B. No check made to see if coils etc. lie wholly within cryostat...
- # External cryostat outboard major radius (m)
+ # External cryostat outboard major radius (m)
self.data.fwbs.r_cryostat_inboard = (
self.data.build.r_tf_outboard_mid
@@ -1265,7 +1277,7 @@ def st_fwbs(self, output: bool):
)
adewex = self.data.fwbs.r_cryostat_inboard - self.data.physics.rmajor
- # External cryostat volume
+ # External cryostat volume
self.data.fwbs.vol_cryostat = (
4.0e0
@@ -1275,8 +1287,8 @@ def st_fwbs(self, output: bool):
* self.data.build.dr_cryostat
)
- # Internal vacuum vessel volume
- # self.data.fwbs.fvoldw accounts for ports, support, etc. additions
+ # Internal vacuum vessel volume
+ # self.data.fwbs.fvoldw accounts for ports, support, etc. additions
r1 = self.data.physics.rminor + 0.5e0 * (
self.data.build.dr_fw_plasma_gap_inboard
@@ -1297,18 +1309,18 @@ def st_fwbs(self, output: bool):
* self.data.fwbs.fvoldw
)
- # Vacuum vessel mass
+ # Vacuum vessel mass
self.data.fwbs.m_vv = self.data.fwbs.vol_vv * self.data.fwbs.den_steel
- # Sum of internal vacuum vessel and external cryostat masses
+ # Sum of internal vacuum vessel and external cryostat masses
self.data.fwbs.dewmkg = (
self.data.fwbs.vol_vv + self.data.fwbs.vol_cryostat
) * self.data.fwbs.den_steel
if output:
- # Output section
+ # Output section
po.oheadr(self.outfile, "First Wall / Blanket / Shield")
po.ovarre(
@@ -1878,7 +1890,7 @@ def st_phys(self, output):
"""
# ###############################################
- # Calculate plasma composition
+ # Calculate plasma composition
# Issue #261 Remove old radiation model
self.physics.plasma_composition()
@@ -1886,7 +1898,7 @@ def st_phys(self, output):
# Calculate density and temperature profile quantities
self.plasma_profile.run()
- # Total field
+ # Total field
self.data.physics.b_plasma_total = np.sqrt(
self.data.physics.b_plasma_toroidal_on_axis**2
+ self.data.physics.b_plasma_surface_poloidal_average**2
@@ -1895,11 +1907,12 @@ def st_phys(self, output):
# Check if self.data.physics.beta (iteration variable 5) is an iteration variable
if 5 in self.data.numerics.ixc:
raise ProcessValueError(
- "Beta should not be in ixc if istell>0. Use Constraints 24 and 84 instead"
+ "Beta should not be in ixc if istell>0. "
+ "Use Constraints 24 and 84 instead"
)
- # Set self.data.physics.beta as a consequence:
- # This replaces constraint equation 1 as it is just an equality.
+ # Set self.data.physics.beta as a consequence:
+ # This replaces constraint equation 1 as it is just an equality.
self.data.physics.beta_total_vol_avg = (
self.data.physics.beta_fast_alpha
+ self.data.physics.beta_beam
@@ -1940,7 +1953,7 @@ def st_phys(self, output):
* self.data.physics.rmajor
)
- # Calculate poloidal field using rotation transform
+ # Calculate poloidal field using rotation transform
self.data.physics.b_plasma_surface_poloidal_average = (
self.data.physics.rminor
* self.data.physics.b_plasma_toroidal_on_axis
@@ -1948,11 +1961,11 @@ def st_phys(self, output):
* self.data.stellarator.iotabar
)
- # Perform auxiliary power calculations
+ # Perform auxiliary power calculations
st_heat(self, False, self.data)
- # Calculate fusion power
+ # Calculate fusion power
fusion_reactions = reactions.FusionReactionRate(self.plasma_profile, self.data)
fusion_reactions.deuterium_branching(
@@ -1961,7 +1974,8 @@ def st_phys(self, output):
fusion_reactions.calculate_fusion_rates()
fusion_reactions.set_physics_variables()
- # D-T power density is named differently to differentiate it from the beam given component
+ # D-T power density is named differently to differentiate it from the beam given
+ # component
self.data.physics.p_plasma_dt_mw = (
self.data.physics.dt_power_density_plasma * self.data.physics.vol_plasma
)
@@ -1972,8 +1986,8 @@ def st_phys(self, output):
self.data.physics.dd_power_density * self.data.physics.vol_plasma
)
- # Calculate neutral beam slowing down effects
- # If ignited, then ignore beam fusion effects
+ # Calculate neutral beam slowing down effects
+ # If ignited, then ignore beam fusion effects
if (self.data.current_drive.p_hcd_beam_injected_total_mw != 0.0e0) and ( # noqa: RUF069
PlasmaIgnitionModel(self.data.physics.i_plasma_ignited)
@@ -2018,7 +2032,8 @@ def st_phys(self, output):
+ 5.0e0 * self.data.physics.p_beam_alpha_mw
)
else:
- # If no beams present then the total alpha rates and power are the same as the plasma values
+ # If no beams present then the total alpha rates and power are the same as
+ # the plasma values
self.data.physics.fusden_total = self.data.physics.fusden_plasma
self.data.physics.fusden_alpha_total = self.data.physics.fusden_plasma_alpha
self.data.physics.p_dt_total_mw = self.data.physics.p_plasma_dt_mw
@@ -2061,7 +2076,7 @@ def st_phys(self, output):
self.data.physics.f_plasma_fuel_deuterium,
)
- # Neutron wall load
+ # Neutron wall load
if self.data.physics.i_pflux_fw_neutron == 1:
self.data.physics.pflux_fw_neutron_mw = (
@@ -2087,7 +2102,7 @@ def st_phys(self, output):
/ self.data.first_wall.a_fw_total
)
- # Calculate ion/electron equilibration power
+ # Calculate ion/electron equilibration power
self.data.physics.pden_ion_electron_equilibration_mw = rether(
self.data.physics.alphan,
@@ -2099,7 +2114,7 @@ def st_phys(self, output):
self.data.physics.n_charge_plasma_effective_mass_weighted_vol_avg,
)
- # Calculate radiation power
+ # Calculate radiation power
radpwr_data = physics_funcs.calculate_radiation_powers(
self.plasma_profile,
self.data.physics.nd_plasma_electron_on_axis,
@@ -2139,9 +2154,9 @@ def st_phys(self, output):
self.data.physics.pden_plasma_rad_mw * self.data.physics.vol_plasma
)
- # Heating power to plasma (= Psol in divertor model)
- # Ohmic power is zero in a stellarator
- # self.data.physics.p_plasma_rad_mw here is core + edge (no SOL)
+ # Heating power to plasma (= Psol in divertor model)
+ # Ohmic power is zero in a stellarator
+ # self.data.physics.p_plasma_rad_mw here is core + edge (no SOL)
powht = (
self.data.physics.f_p_alpha_plasma_deposited
@@ -2161,27 +2176,30 @@ def st_phys(self, output):
# if not ignited add the auxiliary power
powht += self.data.current_drive.p_hcd_injected_total_mw
- # Here the implementation sometimes leaves the accessible regime when p_plasma_rad_mw> powht which is unphysical and
- # is not taken care of by the rad module. We restrict the radiation power here by the heating power:
+ # Here the implementation sometimes leaves the accessible regime
+ # when p_plasma_rad_mw> powht which is unphysical and
+ # is not taken care of by the rad module.
+ # We restrict the radiation power here by the heating power:
self.data.physics.p_plasma_rad_mw = max(0.0e0, self.data.physics.p_plasma_rad_mw)
- # Power to divertor, = (1-self.data.stellarator.f_rad)*Psol
+ # Power to divertor, = (1-self.data.stellarator.f_rad)*Psol
- # The SOL radiation needs to be smaller than the self.data.physics.p_plasma_rad_mw
+ # The SOL radiation needs to be smaller than the
+ # self.data.physics.p_plasma_rad_mw
self.data.physics.psolradmw = self.data.stellarator.f_rad * powht
self.data.physics.p_plasma_separatrix_mw = powht - self.data.physics.psolradmw
# Add SOL Radiation to total
self.data.physics.p_plasma_rad_mw += self.data.physics.psolradmw
- # The following line is unphysical, but prevents -ve sqrt argument
- # Should be obsolete if constraint eqn 17 is turned on (but beware -
- # this may not be quite correct for stellarators)
+ # The following line is unphysical, but prevents -ve sqrt argument
+ # Should be obsolete if constraint eqn 17 is turned on (but beware -
+ # this may not be quite correct for stellarators)
self.data.physics.p_plasma_separatrix_mw = max(
0.001e0, self.data.physics.p_plasma_separatrix_mw
)
- # Power transported to the first wall by escaped alpha particles
+ # Power transported to the first wall by escaped alpha particles
self.data.physics.p_fw_alpha_mw = self.data.physics.p_alpha_total_mw * (
1.0e0 - self.data.physics.f_p_alpha_plasma_deposited
@@ -2224,9 +2242,10 @@ def st_phys(self, output):
+ self.data.current_drive.p_hcd_injected_total_mw
)
- # Calculate transport losses and energy confinement time using the
- # chosen scaling law
- # N.B. self.data.stellarator.iotabar replaces tokamak self.data.physics.q95 in argument list
+ # Calculate transport losses and energy confinement time using the
+ # chosen scaling law
+ # N.B. self.data.stellarator.iotabar replaces tokamak self.data.physics.q95
+ # in argument list
(
self.data.physics.eden_plasma_electrons_thermal_vol_avg,
@@ -2339,8 +2358,8 @@ def st_phys(self, output):
)
)
- # Calculate auxiliary physics related information
- # for the rest of the code
+ # Calculate auxiliary physics related information
+ # for the rest of the code
sbar = 1.0e0
(
diff --git a/process/models/superconductors.py b/process/models/superconductors.py
index fe6a6b1574..2db882efad 100644
--- a/process/models/superconductors.py
+++ b/process/models/superconductors.py
@@ -181,11 +181,16 @@ def jcrit_rebco(
-------
tuple[float, bool, float, float]
A tuple containing:
- - j_critical: Critical current density in the superconductor (A/m²).
- - validity: A boolean indicating whether the input parameters are within the
- valid range.
- - b_c20max: Upper critical field (T) for the superconductor at zero temperature and strain.
- - temp_c0max: Critical temperature (K) at zero field and strain.
+ - j_critical:
+ Critical current density in the superconductor (A/m²).
+ - validity:
+ A boolean indicating whether the input parameters are within the
+ valid range.
+ - b_c20max:
+ Upper critical field (T) for the superconductor
+ at zero temperature and strain.
+ - temp_c0max:
+ Critical temperature (K) at zero field and strain.
Notes
-----
diff --git a/process/models/tfcoil/base.py b/process/models/tfcoil/base.py
index d51140192b..60bb77f222 100644
--- a/process/models/tfcoil/base.py
+++ b/process/models/tfcoil/base.py
@@ -401,7 +401,8 @@ def tf_current(
magnet [T].
- **c_tf_total** (*float*): Total current in TF coils [A].
- **c_tf_coil** (*float*): Current per TF coil [A].
- - **j_tf_coil_full_area** (*float*): Global inboard leg average current density in TF coils [A/m²].
+ - **j_tf_coil_full_area** (*float*):
+ Global inboard leg average current density in TF coils [A/m²].
"""
# Calculation of the maximum B field on the magnet [T]
b_tf_inboard_peak_symmetric = (
@@ -646,7 +647,8 @@ def output_general_tf_info(self) -> None:
)
po.ocmmnt(
self.outfile,
- f"TF conductor model selected: {TFConductorModel(self.data.tfcoil.i_tf_sup).name}",
+ "TF conductor model selected: "
+ f"{TFConductorModel(self.data.tfcoil.i_tf_sup).name}",
)
po.oblnkl(self.outfile)
po.ocmmnt(self.outfile, "----------------------------")
@@ -664,7 +666,8 @@ def output_general_tf_info(self) -> None:
po.ocmmnt(self.outfile, "D-shape coil, inner surface shape approximated by")
po.ocmmnt(
self.outfile,
- "by a straight segment and elliptical arcs between the following points:",
+ "by a straight segment and elliptical arcs between the "
+ "following points:",
)
po.oblnkl(self.outfile)
elif self.data.tfcoil.i_tf_shape == TFCoilShapeModel.PICTURE_FRAME:
@@ -679,7 +682,8 @@ def output_general_tf_info(self) -> None:
for ii in range(5):
po.write(
self.outfile,
- f" {ii} {self.data.tfcoil.r_tf_arc[ii]:.6e} {self.data.tfcoil.z_tf_arc[ii]:.6e}",
+ f" {ii} {self.data.tfcoil.r_tf_arc[ii]:.6e} "
+ f"{self.data.tfcoil.z_tf_arc[ii]:.6e}",
)
po.ovarre(
constants.MFILE,
diff --git a/process/models/tfcoil/resistive.py b/process/models/tfcoil/resistive.py
index da5954a625..f881369029 100644
--- a/process/models/tfcoil/resistive.py
+++ b/process/models/tfcoil/resistive.py
@@ -1043,7 +1043,8 @@ def output_general_resistive_tf_info(self) -> None:
< 10.0e0 * np.finfo(float(radius)).eps
):
logger.error(
- "TF coil dimensions are not consistent. Radius of plasma-facing side of inner leg should be "
+ "TF coil dimensions are not consistent. "
+ "Radius of plasma-facing side of inner leg should be "
f"{self.data.build.r_tf_inboard_in + self.data.build.dr_tf_inboard}m"
)
diff --git a/process/models/tfcoil/superconducting.py b/process/models/tfcoil/superconducting.py
index fd6c83df33..a36fff7c1c 100644
--- a/process/models/tfcoil/superconducting.py
+++ b/process/models/tfcoil/superconducting.py
@@ -15,7 +15,6 @@
from process.models import superconductors
from process.models.superconductors import (
N_CROCO_STRANDS_TURN,
- CroCoCableGeometry,
SuperconductorMaterial,
SuperconductorModel,
calculate_croco_cable_geometry,
@@ -35,7 +34,8 @@ class SuperconductingTFTurnType(IntEnum):
CROSS_CONDUCTOR = (2, "CroCo", "Cross Conductor")
def __new__(cls, value: int, abbreviation: str, full_name: str):
- """Create a new SuperconductingTFTurnType enum member with abbreviation and full name.
+ """Create a new SuperconductingTFTurnType enum member
+ with abbreviation and full name.
Args:
value: The integer value of the enum member.
@@ -132,6 +132,7 @@ def run_base_superconducting_tf(self):
# Set up TF values share by all coil types
self.run_base_tf()
+ d_sc_tf = self.data.superconducting_tfcoil
# Calculating the WP / ground insulation areas
wp_geometry = TFWPGeometry
@@ -140,67 +141,49 @@ def run_base_superconducting_tf(self):
r_tf_inboard_in=self.data.build.r_tf_inboard_in,
dr_tf_nose_case=self.data.tfcoil.dr_tf_nose_case,
dr_tf_wp_with_insulation=self.data.tfcoil.dr_tf_wp_with_insulation,
- tan_theta_coil=self.data.superconducting_tfcoil.tan_theta_coil,
+ tan_theta_coil=d_sc_tf.tan_theta_coil,
dx_tf_side_case_min=self.data.tfcoil.dx_tf_side_case_min,
dx_tf_wp_insulation=self.data.tfcoil.dx_tf_wp_insulation,
dx_tf_wp_insertion_gap=self.data.tfcoil.dx_tf_wp_insertion_gap,
)
- self.data.superconducting_tfcoil.r_tf_wp_inboard_inner = (
- wp_geometry.r_tf_wp_inboard_inner
- )
- self.data.superconducting_tfcoil.r_tf_wp_inboard_outer = (
- wp_geometry.r_tf_wp_inboard_outer
- )
- self.data.superconducting_tfcoil.r_tf_wp_inboard_centre = (
- wp_geometry.r_tf_wp_inboard_centre
- )
- self.data.superconducting_tfcoil.dx_tf_wp_toroidal_min = (
- wp_geometry.dx_tf_wp_toroidal_min
- )
- self.data.superconducting_tfcoil.dr_tf_wp_no_insulation = (
- wp_geometry.dr_tf_wp_no_insulation
- )
+ d_sc_tf.r_tf_wp_inboard_inner = wp_geometry.r_tf_wp_inboard_inner
+ d_sc_tf.r_tf_wp_inboard_outer = wp_geometry.r_tf_wp_inboard_outer
+ d_sc_tf.r_tf_wp_inboard_centre = wp_geometry.r_tf_wp_inboard_centre
+ d_sc_tf.dx_tf_wp_toroidal_min = wp_geometry.dx_tf_wp_toroidal_min
+ d_sc_tf.dr_tf_wp_no_insulation = wp_geometry.dr_tf_wp_no_insulation
self.data.tfcoil.dx_tf_wp_primary_toroidal = (
wp_geometry.dx_tf_wp_primary_toroidal
)
self.data.tfcoil.dx_tf_wp_secondary_toroidal = (
wp_geometry.dx_tf_wp_secondary_toroidal
)
- self.data.superconducting_tfcoil.dx_tf_wp_toroidal_average = (
- wp_geometry.dx_tf_wp_toroidal_average
- )
- self.data.superconducting_tfcoil.a_tf_wp_with_insulation = (
- wp_geometry.a_tf_wp_with_insulation
- )
- self.data.superconducting_tfcoil.a_tf_wp_no_insulation = (
- wp_geometry.a_tf_wp_no_insulation
- )
- self.data.superconducting_tfcoil.a_tf_wp_ground_insulation = (
- wp_geometry.a_tf_wp_ground_insulation
- )
+ d_sc_tf.dx_tf_wp_toroidal_average = wp_geometry.dx_tf_wp_toroidal_average
+ d_sc_tf.a_tf_wp_with_insulation = wp_geometry.a_tf_wp_with_insulation
+ d_sc_tf.a_tf_wp_no_insulation = wp_geometry.a_tf_wp_no_insulation
+ d_sc_tf.a_tf_wp_ground_insulation = wp_geometry.a_tf_wp_ground_insulation
# Calculating the TF steel casing areas
(
self.data.tfcoil.a_tf_coil_inboard_case,
self.data.tfcoil.a_tf_coil_outboard_case,
- self.data.superconducting_tfcoil.a_tf_plasma_case,
- self.data.superconducting_tfcoil.a_tf_coil_nose_case,
- self.data.superconducting_tfcoil.dx_tf_side_case_average,
+ d_sc_tf.a_tf_plasma_case,
+ d_sc_tf.a_tf_coil_nose_case,
+ d_sc_tf.dx_tf_side_case_average,
self.data.tfcoil.dx_tf_side_case_peak,
) = self.superconducting_tf_case_geometry(
i_tf_case_geom=self.data.tfcoil.i_tf_case_geom,
i_tf_wp_geom=self.data.tfcoil.i_tf_wp_geom,
a_tf_inboard_total=self.data.tfcoil.a_tf_inboard_total,
n_tf_coils=self.data.tfcoil.n_tf_coils,
- a_tf_wp_with_insulation=self.data.superconducting_tfcoil.a_tf_wp_with_insulation,
+ a_tf_wp_with_insulation=d_sc_tf.a_tf_wp_with_insulation,
a_tf_leg_outboard=self.data.tfcoil.a_tf_leg_outboard,
- rad_tf_coil_inboard_toroidal_half=self.data.superconducting_tfcoil.rad_tf_coil_inboard_toroidal_half,
+ rad_tf_coil_inboard_toroidal_half=d_sc_tf.rad_tf_coil_inboard_toroidal_half,
r_tf_inboard_out=self.data.build.r_tf_inboard_out,
- tan_theta_coil=self.data.superconducting_tfcoil.tan_theta_coil,
- r_tf_wp_inboard_outer=self.data.superconducting_tfcoil.r_tf_wp_inboard_outer,
+ tan_theta_coil=d_sc_tf.tan_theta_coil,
+ r_tf_wp_inboard_outer=d_sc_tf.r_tf_wp_inboard_outer,
dr_tf_plasma_case=self.data.tfcoil.dr_tf_plasma_case,
- r_tf_wp_inboard_inner=self.data.superconducting_tfcoil.r_tf_wp_inboard_inner,
+ r_tf_wp_inboard_inner=d_sc_tf.r_tf_wp_inboard_inner,
r_tf_inboard_in=self.data.build.r_tf_inboard_in,
dx_tf_side_case_min=self.data.tfcoil.dx_tf_side_case_min,
dr_tf_wp_with_insulation=self.data.tfcoil.dr_tf_wp_with_insulation,
@@ -235,13 +218,13 @@ def run_base_superconducting_tf(self):
self.data.tfcoil.cforce,
self.data.tfcoil.vforce,
self.data.tfcoil.vforce_outboard,
- self.data.superconducting_tfcoil.vforce_inboard_tot,
+ d_sc_tf.vforce_inboard_tot,
self.data.tfcoil.f_vforce_inboard,
) = self.tf_field_and_force(
i_tf_sup=self.data.tfcoil.i_tf_sup,
- r_tf_wp_inboard_outer=self.data.superconducting_tfcoil.r_tf_wp_inboard_outer,
- r_tf_wp_inboard_inner=self.data.superconducting_tfcoil.r_tf_wp_inboard_inner,
- r_tf_outboard_in=self.data.superconducting_tfcoil.r_tf_outboard_in,
+ r_tf_wp_inboard_outer=d_sc_tf.r_tf_wp_inboard_outer,
+ r_tf_wp_inboard_inner=d_sc_tf.r_tf_wp_inboard_inner,
+ r_tf_outboard_in=d_sc_tf.r_tf_outboard_in,
dx_tf_wp_insulation=self.data.tfcoil.dx_tf_wp_insulation,
dx_tf_wp_insertion_gap=self.data.tfcoil.dx_tf_wp_insertion_gap,
b_tf_inboard_peak_symmetric=self.data.tfcoil.b_tf_inboard_peak_symmetric,
@@ -259,12 +242,14 @@ def run_base_superconducting_tf(self):
# ======================================================
# Peak inboard toroidal field including ripple
- self.data.tfcoil.b_tf_inboard_peak_with_ripple = self.peak_b_tf_inboard_with_ripple(
- n_tf_coils=self.data.tfcoil.n_tf_coils,
- dx_tf_wp_primary_toroidal=self.data.tfcoil.dx_tf_wp_primary_toroidal,
- dr_tf_wp_no_insulation=self.data.superconducting_tfcoil.dr_tf_wp_no_insulation,
- r_tf_wp_inboard_centre=self.data.superconducting_tfcoil.r_tf_wp_inboard_centre,
- b_tf_inboard_peak_symmetric=self.data.tfcoil.b_tf_inboard_peak_symmetric,
+ self.data.tfcoil.b_tf_inboard_peak_with_ripple = (
+ self.peak_b_tf_inboard_with_ripple(
+ n_tf_coils=self.data.tfcoil.n_tf_coils,
+ dx_tf_wp_primary_toroidal=self.data.tfcoil.dx_tf_wp_primary_toroidal,
+ dr_tf_wp_no_insulation=d_sc_tf.dr_tf_wp_no_insulation,
+ r_tf_wp_inboard_centre=d_sc_tf.r_tf_wp_inboard_centre,
+ b_tf_inboard_peak_symmetric=self.data.tfcoil.b_tf_inboard_peak_symmetric,
+ )
)
# ======================================================
@@ -275,6 +260,8 @@ def output_general_superconducting_tf_info(self) -> None:
base `TFCoil` class, which is relevant for all TF coil types.
"""
+ d_sc_tf = self.data.superconducting_tfcoil
+
po.oheadr(self.outfile, "General Superconducting TF Coil Parameters ")
# Turn/WP geometry
@@ -282,12 +269,13 @@ def output_general_superconducting_tf_info(self) -> None:
self.outfile,
"Superconducting TF coil turn type",
"(i_tf_turn_type)",
- self.data.superconducting_tfcoil.i_tf_turn_type,
+ d_sc_tf.i_tf_turn_type,
)
po.ocmmnt(
self.outfile,
- f"Turn geometry selected: {SuperconductingTFTurnType(self.data.superconducting_tfcoil.i_tf_turn_type).full_name}",
+ "Turn geometry selected: "
+ f"{SuperconductingTFTurnType(d_sc_tf.i_tf_turn_type).full_name}",
)
po.oblnkl(self.outfile)
@@ -300,27 +288,25 @@ def output_general_superconducting_tf_info(self) -> None:
self.outfile,
"Total steel cross-section (m²)",
"(a_tf_coil_inboard_steel*n_tf_coils)",
- self.data.superconducting_tfcoil.a_tf_coil_inboard_steel
- * self.data.tfcoil.n_tf_coils,
+ d_sc_tf.a_tf_coil_inboard_steel * self.data.tfcoil.n_tf_coils,
)
po.ovarre(
self.outfile,
"Total steel TF fraction",
"(f_a_tf_coil_inboard_steel)",
- self.data.superconducting_tfcoil.f_a_tf_coil_inboard_steel,
+ d_sc_tf.f_a_tf_coil_inboard_steel,
)
po.ovarre(
self.outfile,
"Total Insulation cross-section (total) (m²)",
"(a_tf_coil_inboard_insulation*n_tf_coils)",
- self.data.superconducting_tfcoil.a_tf_coil_inboard_insulation
- * self.data.tfcoil.n_tf_coils,
+ d_sc_tf.a_tf_coil_inboard_insulation * self.data.tfcoil.n_tf_coils,
)
po.ovarre(
self.outfile,
"Total Insulation fraction",
"(f_a_tf_coil_inboard_insulation)",
- self.data.superconducting_tfcoil.f_a_tf_coil_inboard_insulation,
+ d_sc_tf.f_a_tf_coil_inboard_insulation,
)
po.oblnkl(self.outfile)
@@ -339,21 +325,21 @@ def output_general_superconducting_tf_info(self) -> None:
self.outfile,
"Inboard leg plasma case area (m²)",
"(a_tf_plasma_case)",
- self.data.superconducting_tfcoil.a_tf_plasma_case,
+ d_sc_tf.a_tf_plasma_case,
)
po.ovarre(
self.outfile,
'Inboard leg case inboard "nose" area (m²)',
"(a_tf_coil_nose_case)",
- self.data.superconducting_tfcoil.a_tf_coil_nose_case,
+ d_sc_tf.a_tf_coil_nose_case,
)
po.ovarre(
self.outfile,
"Inboard leg case sidewall average thickness (m)",
"(dx_tf_side_case_average)",
- self.data.superconducting_tfcoil.dx_tf_side_case_average,
+ d_sc_tf.dx_tf_side_case_average,
)
po.ovarre(
self.outfile,
@@ -383,7 +369,8 @@ def output_general_superconducting_tf_info(self) -> None:
)
po.ocmmnt(
self.outfile,
- f"Winding pack shape selected: {SuperconductingTFWPShapeType(self.data.tfcoil.i_tf_wp_geom).full_name}",
+ "Winding pack shape selected: "
+ f"{SuperconductingTFWPShapeType(self.data.tfcoil.i_tf_wp_geom).full_name}",
)
po.oblnkl(self.outfile)
@@ -392,13 +379,13 @@ def output_general_superconducting_tf_info(self) -> None:
self.outfile,
"WP cross section area with insulation and insertion (per coil) (m²)",
"(a_tf_wp_with_insulation)",
- self.data.superconducting_tfcoil.a_tf_wp_with_insulation,
+ d_sc_tf.a_tf_wp_with_insulation,
)
po.ovarre(
self.outfile,
"WP cross section area with no insulation and insertion (per coil) (m²)",
"(a_tf_wp_no_insulation)",
- self.data.superconducting_tfcoil.a_tf_wp_no_insulation,
+ d_sc_tf.a_tf_wp_no_insulation,
)
po.ovarre(
self.outfile,
@@ -410,7 +397,7 @@ def output_general_superconducting_tf_info(self) -> None:
self.outfile,
"Ground wall insulation area (m²)",
"(a_tf_wp_ground_insulation)",
- self.data.superconducting_tfcoil.a_tf_wp_ground_insulation,
+ d_sc_tf.a_tf_wp_ground_insulation,
)
po.oblnkl(self.outfile)
@@ -425,7 +412,7 @@ def output_general_superconducting_tf_info(self) -> None:
self.outfile,
"Minimum toroidal thickness of winding pack (m)",
"(dx_tf_wp_toroidal_min)",
- self.data.superconducting_tfcoil.dx_tf_wp_toroidal_min,
+ d_sc_tf.dx_tf_wp_toroidal_min,
"OP ",
)
@@ -482,26 +469,25 @@ def output_general_superconducting_tf_info(self) -> None:
self.outfile,
"Steel WP fraction",
"(a_tf_wp_steel/a_tf_wp_with_insulation)",
- self.data.tfcoil.a_tf_wp_steel
- / self.data.superconducting_tfcoil.a_tf_wp_with_insulation,
+ self.data.tfcoil.a_tf_wp_steel / d_sc_tf.a_tf_wp_with_insulation,
)
po.ovarre(
self.outfile,
"Insulation WP fraction",
"(a_tf_coil_wp_turn_insulation/a_tf_wp_with_insulation)",
self.data.tfcoil.a_tf_coil_wp_turn_insulation
- / self.data.superconducting_tfcoil.a_tf_wp_with_insulation,
+ / d_sc_tf.a_tf_wp_with_insulation,
)
po.ovarre(
self.outfile,
"Cable WP fraction",
"((a_tf_wp_with_insulation-a_tf_wp_steel-a_tf_coil_wp_turn_insulation)/a_tf_wp_with_insulation)",
(
- self.data.superconducting_tfcoil.a_tf_wp_with_insulation
+ d_sc_tf.a_tf_wp_with_insulation
- self.data.tfcoil.a_tf_wp_steel
- self.data.tfcoil.a_tf_coil_wp_turn_insulation
)
- / self.data.superconducting_tfcoil.a_tf_wp_with_insulation,
+ / d_sc_tf.a_tf_wp_with_insulation,
)
po.oblnkl(self.outfile)
@@ -548,45 +534,45 @@ def output_general_superconducting_tf_info(self) -> None:
self.outfile,
"Radial width of turn (m)",
"(dr_tf_turn)",
- self.data.superconducting_tfcoil.dr_tf_turn,
+ d_sc_tf.dr_tf_turn,
)
po.ovarre(
self.outfile,
"Toroidal width of turn (m)",
"(dx_tf_turn)",
- self.data.superconducting_tfcoil.dx_tf_turn,
+ d_sc_tf.dx_tf_turn,
)
po.ovarre(
self.outfile,
"Radial width of conductor (m)",
"(t_conductor_radial)",
- self.data.superconducting_tfcoil.t_conductor_radial,
+ d_sc_tf.t_conductor_radial,
"OP ",
)
po.ovarre(
self.outfile,
"Toroidal width of conductor (m)",
"(t_conductor_toroidal)",
- self.data.superconducting_tfcoil.t_conductor_toroidal,
+ d_sc_tf.t_conductor_toroidal,
"OP ",
)
po.ovarre(
self.outfile,
"Radial width of cable space",
"(dr_tf_turn_cable_space)",
- self.data.superconducting_tfcoil.dr_tf_turn_cable_space,
+ d_sc_tf.dr_tf_turn_cable_space,
)
po.ovarre(
self.outfile,
"Toroidal width of cable space",
"(dx_tf_turn_cable_space)",
- self.data.superconducting_tfcoil.dx_tf_turn_cable_space,
+ d_sc_tf.dx_tf_turn_cable_space,
)
po.ovarre(
self.outfile,
"Radius of turn cable space rounded corners (m)",
"(radius_tf_turn_cable_space_corners)",
- self.data.superconducting_tfcoil.radius_tf_turn_cable_space_corners,
+ d_sc_tf.radius_tf_turn_cable_space_corners,
)
else:
po.ovarre(
@@ -607,14 +593,14 @@ def output_general_superconducting_tf_info(self) -> None:
self.outfile,
"Width of space inside conductor (m)",
"(dx_tf_turn_cable_space_average)",
- self.data.superconducting_tfcoil.dx_tf_turn_cable_space_average,
+ d_sc_tf.dx_tf_turn_cable_space_average,
"OP ",
)
po.ovarre(
self.outfile,
"Radius of turn cable space rounded corners (m)",
"(radius_tf_turn_cable_space_corners)",
- self.data.superconducting_tfcoil.radius_tf_turn_cable_space_corners,
+ d_sc_tf.radius_tf_turn_cable_space_corners,
)
po.ovarre(
@@ -818,7 +804,8 @@ def output_general_superconducting_tf_info(self) -> None:
< 10.0e0 * np.finfo(float(radius)).eps
):
logger.error(
- "TF coil dimensions are not consistent. Radius of plasma-facing side of inner leg should be "
+ "TF coil dimensions are not consistent. "
+ "Radius of plasma-facing side of inner leg should be "
f"{self.data.build.r_tf_inboard_in + self.data.build.dr_tf_inboard}m"
)
@@ -840,6 +827,8 @@ def output_general_superconducting_tf_info(self) -> None:
def output_tf_superconductor_info(self):
"""Output TF superconductor information"""
+ d_sc_tf = self.data.superconducting_tfcoil
+
po.oheadr(self.outfile, "TF Coils Superconductor Information")
po.ovarre(
self.outfile,
@@ -859,13 +848,13 @@ def output_tf_superconductor_info(self):
self.outfile,
"Critical field at zero temperature and strain (T)",
"(b_tf_superconductor_critical_zero_temp_strain)",
- self.data.superconducting_tfcoil.b_tf_superconductor_critical_zero_temp_strain,
+ d_sc_tf.b_tf_superconductor_critical_zero_temp_strain,
)
po.ovarre(
self.outfile,
"Critical temperature at zero field and strain (K)",
"(temp_tf_superconductor_critical_zero_field_strain)",
- self.data.superconducting_tfcoil.temp_tf_superconductor_critical_zero_field_strain,
+ d_sc_tf.temp_tf_superconductor_critical_zero_field_strain,
)
po.oblnkl(self.outfile)
@@ -879,7 +868,7 @@ def output_tf_superconductor_info(self):
self.outfile,
"Total cooling area fraction inside cable space",
"(f_a_tf_turn_cable_space_cooling)",
- self.data.superconducting_tfcoil.f_a_tf_turn_cable_space_cooling,
+ d_sc_tf.f_a_tf_turn_cable_space_cooling,
"OP ",
)
po.ovarre(
@@ -905,14 +894,14 @@ def output_tf_superconductor_info(self):
self.outfile,
"Critical current density in superconductor (A/m²)",
"(j_tf_superconductor_critical)",
- self.data.superconducting_tfcoil.j_tf_superconductor_critical,
+ d_sc_tf.j_tf_superconductor_critical,
"OP ",
)
po.ovarre(
self.outfile,
"Current density in superconductor (A/m²)",
"(j_tf_superconductor)",
- self.data.superconducting_tfcoil.j_tf_superconductor,
+ d_sc_tf.j_tf_superconductor,
"OP ",
)
po.ovarre(
@@ -933,7 +922,7 @@ def output_tf_superconductor_info(self):
self.outfile,
"Current density in TF coil turn (A/m²)",
"(j_tf_coil_turn)",
- self.data.superconducting_tfcoil.j_tf_coil_turn,
+ d_sc_tf.j_tf_coil_turn,
"OP ",
)
po.oblnkl(self.outfile)
@@ -943,7 +932,7 @@ def output_tf_superconductor_info(self):
self.outfile,
"Critical current (A)",
"(c_turn_cables_critical)",
- self.data.superconducting_tfcoil.c_tf_turn_cables_critical,
+ d_sc_tf.c_tf_turn_cables_critical,
"OP ",
)
po.ovarre(
@@ -957,10 +946,10 @@ def output_tf_superconductor_info(self):
self.outfile,
"Actual current / critical current",
"(f_c_tf_turn_operating_critical)",
- self.data.superconducting_tfcoil.f_c_tf_turn_operating_critical,
+ d_sc_tf.f_c_tf_turn_operating_critical,
"OP ",
)
- if self.data.superconducting_tfcoil.f_c_tf_turn_operating_critical > 0.7:
+ if d_sc_tf.f_c_tf_turn_operating_critical > 0.7:
logger.error(
"f_c_tf_turn_operating_critical shouldn't be above 0.7 for engineering "
"reliability"
@@ -1000,14 +989,14 @@ def output_tf_superconductor_info(self):
self.outfile,
"Maximum permitted TF coil current / copper area (A/m2)",
"(copperA_m2_max)",
- self.data.superconducting_tfcoil.tf_coppera_m2_max,
+ d_sc_tf.tf_coppera_m2_max,
)
po.ovarre(
self.outfile,
"Actual TF coil current / copper area (A/m2)",
"(copperA_m2)",
- self.data.superconducting_tfcoil.tf_coppera_m2,
+ d_sc_tf.tf_coppera_m2,
)
po.ovarre(
@@ -1027,7 +1016,7 @@ def output_tf_superconductor_info(self):
self.outfile,
"Vacuum Vessel stress on quench (Pa)",
"(vv_stress_quench)",
- self.data.superconducting_tfcoil.vv_stress_quench,
+ d_sc_tf.vv_stress_quench,
"OP ",
)
po.ovarre(
@@ -1126,15 +1115,8 @@ def calculate_superconductor_temperature_margin(
if i_tf_superconductor == 2:
# Bi-2212: temperature margin already calculated elsewhere
temp_tf_superconductor_margin = 0.0
- elif i_tf_superconductor in {
- 1,
- 3,
- 4,
- 5,
- 7,
- 8,
- 9,
- }: # Find temperature at which current density margin = 0
+ # Find temperature at which current density margin = 0
+ elif i_tf_superconductor in {1, 3, 4, 5, 7, 8, 9}:
if i_tf_superconductor == 3:
arguments = (
i_tf_superconductor,
@@ -1321,8 +1303,9 @@ def vv_stress_on_quench(self):
# that of the plasma facing radii of the two structures
tf_vv_frac = self.data.build.r_tf_inboard_out / self.data.build.r_vv_inboard_out
rm_vv = self.data.build.r_vv_inboard_out + (self.data.tfcoil.tfa[0] * tf_vv_frac)
+ d_sc_tf = self.data.superconducting_tfcoil
- self.data.superconducting_tfcoil.vv_stress_quench = vv_stress_on_quench(
+ d_sc_tf.vv_stress_quench = vv_stress_on_quench(
# TF shape
H_coil=H_coil,
ri_coil=ri_coil,
@@ -1341,16 +1324,13 @@ def vv_stress_on_quench(self):
n_tf_coil_turns=self.data.tfcoil.n_tf_coil_turns,
# Area of the radial plate taken to be the area of steel in the WP
# TODO: value clipped due to #1883
- s_rp=np.clip(
- self.data.superconducting_tfcoil.a_tf_coil_inboard_steel, 0, None
- ),
- s_cc=self.data.superconducting_tfcoil.a_tf_plasma_case
- + self.data.superconducting_tfcoil.a_tf_coil_nose_case
- + 2.0 * self.data.superconducting_tfcoil.dx_tf_side_case_average,
+ s_rp=np.clip(d_sc_tf.a_tf_coil_inboard_steel, 0, None),
+ s_cc=d_sc_tf.a_tf_plasma_case
+ + d_sc_tf.a_tf_coil_nose_case
+ + 2.0 * d_sc_tf.dx_tf_side_case_average,
taud=self.data.tfcoil.t_tf_superconductor_quench,
# TODO: is this the correct current?
- i_op=self.data.superconducting_tfcoil.c_tf_coil
- / self.data.tfcoil.n_tf_coil_turns,
+ i_op=d_sc_tf.c_tf_coil / self.data.tfcoil.n_tf_coil_turns,
# VV properties
d_vv=self.data.build.dr_vv_shells,
)
@@ -1430,25 +1410,18 @@ def peak_b_tf_inboard_with_ripple(
) * np.tan(np.pi / n_tf_coils)
# Dimensionless winding pack width
+ d_sc_tf = self.data.superconducting_tfcoil
- self.data.superconducting_tfcoil.tf_fit_t = (
- dx_tf_wp_primary_toroidal / dx_tf_wp_toroidal_max
- )
- if (self.data.superconducting_tfcoil.tf_fit_t < 0.3e0) or (
- self.data.superconducting_tfcoil.tf_fit_t > 1.1e0
- ):
+ d_sc_tf.tf_fit_t = dx_tf_wp_primary_toroidal / dx_tf_wp_toroidal_max
+ if (d_sc_tf.tf_fit_t < 0.3e0) or (d_sc_tf.tf_fit_t > 1.1e0):
logger.warning(
"(TF coil peak field calculation) Winding pack width out of fitted range"
)
# Dimensionless winding pack radial thickness
- self.data.superconducting_tfcoil.tf_fit_z = (
- dr_tf_wp_no_insulation / dx_tf_wp_toroidal_max
- )
- if (self.data.superconducting_tfcoil.tf_fit_z < 0.26e0) or (
- self.data.superconducting_tfcoil.tf_fit_z > 0.7e0
- ):
+ d_sc_tf.tf_fit_z = dr_tf_wp_no_insulation / dx_tf_wp_toroidal_max
+ if (d_sc_tf.tf_fit_z < 0.26e0) or (d_sc_tf.tf_fit_z > 0.7e0):
# write(*,*) 'PEAK_TF_WITH_RIPPLE: fitting problem; z = ',z
logger.warning(
"(TF coil peak field calculation) Winding pack radial thickness out of "
@@ -1457,19 +1430,14 @@ def peak_b_tf_inboard_with_ripple(
# Ratio of peak field with ripple to nominal axisymmetric peak field
- self.data.superconducting_tfcoil.f_b_tf_inboard_peak_ripple_symmetric = (
+ d_sc_tf.f_b_tf_inboard_peak_ripple_symmetric = (
a[0]
- + a[1] * np.exp(-self.data.superconducting_tfcoil.tf_fit_t)
- + a[2] * self.data.superconducting_tfcoil.tf_fit_z
- + a[3]
- * self.data.superconducting_tfcoil.tf_fit_z
- * self.data.superconducting_tfcoil.tf_fit_t
+ + a[1] * np.exp(-d_sc_tf.tf_fit_t)
+ + a[2] * d_sc_tf.tf_fit_z
+ + a[3] * d_sc_tf.tf_fit_z * d_sc_tf.tf_fit_t
)
- return (
- self.data.superconducting_tfcoil.f_b_tf_inboard_peak_ripple_symmetric
- * b_tf_inboard_peak_symmetric
- )
+ return d_sc_tf.f_b_tf_inboard_peak_ripple_symmetric * b_tf_inboard_peak_symmetric
@staticmethod
def superconducting_tf_wp_geometry(
@@ -1592,13 +1560,13 @@ def superconducting_tf_wp_geometry(
# ---------------------
elif i_tf_wp_geom == SuperconductingTFWPShapeType.DOUBLE_RECTANGULAR:
# Thickness of winding pack section at R >
- # self.data.superconducting_tfcoil.r_tf_wp_inboard_centre [m]
+ # d_sc_tf.r_tf_wp_inboard_centre [m]
dx_tf_wp_primary_toroidal = 2.0e0 * (
r_tf_wp_inboard_centre * tan_theta_coil - dx_tf_side_case_min
)
# Thickness of winding pack section at R <
- # self.data.superconducting_tfcoil.r_tf_wp_inboard_centre [m]
+ # d_sc_tf.r_tf_wp_inboard_centre [m]
dx_tf_wp_secondary_toroidal = 2.0e0 * (
r_tf_wp_inboard_inner * tan_theta_coil - dx_tf_side_case_min
)
@@ -1908,12 +1876,11 @@ def superconducting_tf_coil_areas_and_masses(self):
# Mass of ground-wall insulation [kg]
# (assumed to be same density/material as turn insulation)
+ d_sc_tf = self.data.superconducting_tfcoil
+
self.data.tfcoil.m_tf_coil_wp_insulation = (
self.data.tfcoil.len_tf_coil
- * (
- self.data.superconducting_tfcoil.a_tf_wp_with_insulation
- - self.data.superconducting_tfcoil.a_tf_wp_no_insulation
- )
+ * (d_sc_tf.a_tf_wp_with_insulation - d_sc_tf.a_tf_wp_no_insulation)
* self.data.tfcoil.den_tf_wp_turn_insulation
)
@@ -2021,8 +1988,12 @@ def superconducting_tf_coil_areas_and_masses(self):
)
def run_and_output_stress(self) -> None:
- """Run the superconducting TF coil model and print the results of the stress calculations."""
+ """
+ Run the superconducting TF coil model and
+ print the results of the stress calculations.
+ """
self.data.tfcoil.n_rad_per_layer = 500
+ d_sc_tf = self.data.superconducting_tfcoil
try: # noqa: PLW0717
(
@@ -2092,28 +2063,28 @@ def run_and_output_stress(self) -> None:
poisson_copper=self.data.tfcoil.poisson_copper,
i_tf_sup=self.data.tfcoil.i_tf_sup,
eyoung_res_tf_buck=self.data.tfcoil.eyoung_res_tf_buck,
- r_tf_wp_inboard_inner=self.data.superconducting_tfcoil.r_tf_wp_inboard_inner,
- tan_theta_coil=self.data.superconducting_tfcoil.tan_theta_coil,
- rad_tf_coil_inboard_toroidal_half=self.data.superconducting_tfcoil.rad_tf_coil_inboard_toroidal_half,
- r_tf_wp_inboard_outer=self.data.superconducting_tfcoil.r_tf_wp_inboard_outer,
- a_tf_coil_inboard_steel=self.data.superconducting_tfcoil.a_tf_coil_inboard_steel,
- a_tf_plasma_case=self.data.superconducting_tfcoil.a_tf_plasma_case,
- a_tf_coil_nose_case=self.data.superconducting_tfcoil.a_tf_coil_nose_case,
+ r_tf_wp_inboard_inner=d_sc_tf.r_tf_wp_inboard_inner,
+ tan_theta_coil=d_sc_tf.tan_theta_coil,
+ rad_tf_coil_inboard_toroidal_half=d_sc_tf.rad_tf_coil_inboard_toroidal_half,
+ r_tf_wp_inboard_outer=d_sc_tf.r_tf_wp_inboard_outer,
+ a_tf_coil_inboard_steel=d_sc_tf.a_tf_coil_inboard_steel,
+ a_tf_plasma_case=d_sc_tf.a_tf_plasma_case,
+ a_tf_coil_nose_case=d_sc_tf.a_tf_coil_nose_case,
dx_tf_wp_insertion_gap=self.data.tfcoil.dx_tf_wp_insertion_gap,
dx_tf_wp_insulation=self.data.tfcoil.dx_tf_wp_insulation,
n_tf_coil_turns=self.data.tfcoil.n_tf_coil_turns,
i_tf_turns_integer=int(self.data.tfcoil.i_tf_turns_integer),
- dx_tf_turn_cable_space_average=self.data.superconducting_tfcoil.dx_tf_turn_cable_space_average,
- dr_tf_turn_cable_space=self.data.superconducting_tfcoil.dr_tf_turn_cable_space,
+ dx_tf_turn_cable_space_average=d_sc_tf.dx_tf_turn_cable_space_average,
+ dr_tf_turn_cable_space=d_sc_tf.dr_tf_turn_cable_space,
dia_tf_turn_coolant_channel=self.data.tfcoil.dia_tf_turn_coolant_channel,
f_a_tf_turn_cable_copper=self.data.tfcoil.f_a_tf_turn_cable_copper,
dx_tf_turn_steel=self.data.tfcoil.dx_tf_turn_steel,
- dx_tf_side_case_average=self.data.superconducting_tfcoil.dx_tf_side_case_average,
- dx_tf_wp_toroidal_average=self.data.superconducting_tfcoil.dx_tf_wp_toroidal_average,
- a_tf_coil_inboard_insulation=self.data.superconducting_tfcoil.a_tf_coil_inboard_insulation,
+ dx_tf_side_case_average=d_sc_tf.dx_tf_side_case_average,
+ dx_tf_wp_toroidal_average=d_sc_tf.dx_tf_wp_toroidal_average,
+ a_tf_coil_inboard_insulation=d_sc_tf.a_tf_coil_inboard_insulation,
a_tf_wp_steel=self.data.tfcoil.a_tf_wp_steel,
a_tf_wp_conductor=self.data.tfcoil.a_tf_wp_conductor,
- a_tf_wp_with_insulation=self.data.superconducting_tfcoil.a_tf_wp_with_insulation,
+ a_tf_wp_with_insulation=d_sc_tf.a_tf_wp_with_insulation,
eyoung_al=self.data.tfcoil.eyoung_al,
poisson_al=self.data.tfcoil.poisson_al,
fcoolcp=self.data.tfcoil.fcoolcp,
@@ -2121,7 +2092,7 @@ def run_and_output_stress(self) -> None:
c_tf_total=self.data.tfcoil.c_tf_total,
dr_tf_plasma_case=self.data.tfcoil.dr_tf_plasma_case,
i_tf_stress_model=self.data.tfcoil.i_tf_stress_model,
- vforce_inboard_tot=self.data.superconducting_tfcoil.vforce_inboard_tot,
+ vforce_inboard_tot=d_sc_tf.vforce_inboard_tot,
i_tf_tresca=self.data.tfcoil.i_tf_tresca,
a_tf_coil_inboard_case=self.data.tfcoil.a_tf_coil_inboard_case,
vforce=self.data.tfcoil.vforce,
@@ -2247,10 +2218,12 @@ def run(self, output: bool = False):
"""
self.run_base_superconducting_tf()
+ d_sc_tf = self.data.superconducting_tfcoil
+
# Setting the WP turn geometry / areas
if self.data.tfcoil.i_tf_turns_integer == 0:
# Non-ingeger number of turns
- avg_turn_geometry: CICCAveragedTurnGeometry = self.tf_cable_in_conduit_averaged_turn_geometry(
+ avg_turn_geometry = self.tf_cable_in_conduit_averaged_turn_geometry(
j_tf_wp=self.data.tfcoil.j_tf_wp,
dx_tf_turn_steel=self.data.tfcoil.dx_tf_turn_steel,
dx_tf_turn_insulation=self.data.tfcoil.dx_tf_turn_insulation,
@@ -2260,7 +2233,7 @@ def run(self, output: bool = False):
i_dx_tf_turn_cable_space_general_input=self.data.tfcoil.i_dx_tf_turn_cable_space_general_input,
dx_tf_turn_cable_space_general=self.data.tfcoil.dx_tf_turn_cable_space_general,
layer_ins=self.data.tfcoil.layer_ins,
- a_tf_wp_no_insulation=self.data.superconducting_tfcoil.a_tf_wp_no_insulation,
+ a_tf_wp_no_insulation=d_sc_tf.a_tf_wp_no_insulation,
dia_tf_turn_coolant_channel=self.data.tfcoil.dia_tf_turn_coolant_channel,
f_a_tf_turn_cable_space_extra_void=self.data.tfcoil.f_a_tf_turn_cable_space_extra_void,
)
@@ -2276,42 +2249,42 @@ def run(self, output: bool = False):
self.data.tfcoil.dx_tf_turn_general = avg_turn_geometry.dx_tf_turn_general
self.data.tfcoil.c_tf_turn = avg_turn_geometry.c_tf_turn
self.data.tfcoil.dx_tf_turn_general = avg_turn_geometry.dx_tf_turn_general
- self.data.superconducting_tfcoil.dr_tf_turn = avg_turn_geometry.dr_tf_turn
- self.data.superconducting_tfcoil.dx_tf_turn = avg_turn_geometry.dx_tf_turn
+ d_sc_tf.dr_tf_turn = avg_turn_geometry.dr_tf_turn
+ d_sc_tf.dx_tf_turn = avg_turn_geometry.dx_tf_turn
self.data.tfcoil.t_conductor = avg_turn_geometry.t_conductor
- self.data.superconducting_tfcoil.radius_tf_turn_cable_space_corners = (
+ d_sc_tf.radius_tf_turn_cable_space_corners = (
avg_turn_geometry.radius_tf_turn_cable_space_corners
)
- self.data.superconducting_tfcoil.dx_tf_turn_cable_space_average = (
+ d_sc_tf.dx_tf_turn_cable_space_average = (
avg_turn_geometry.dx_tf_turn_cable_space_average
)
- self.data.superconducting_tfcoil.a_tf_turn_cable_space_effective = (
+ d_sc_tf.a_tf_turn_cable_space_effective = (
avg_turn_geometry.a_tf_turn_cable_space_effective
)
- self.data.superconducting_tfcoil.f_a_tf_turn_cable_space_cooling = (
+ d_sc_tf.f_a_tf_turn_cable_space_cooling = (
avg_turn_geometry.f_a_tf_turn_cable_space_cooling
)
else:
# Integer number of turns
- int_turn_geometry: CICCIntegerTurnGeometry = self.tf_cable_in_conduit_integer_turn_geometry(
+ int_turn_geometry = self.tf_cable_in_conduit_integer_turn_geometry(
dr_tf_wp_with_insulation=self.data.tfcoil.dr_tf_wp_with_insulation,
dx_tf_wp_insulation=self.data.tfcoil.dx_tf_wp_insulation,
dx_tf_wp_insertion_gap=self.data.tfcoil.dx_tf_wp_insertion_gap,
n_tf_wp_layers=self.data.tfcoil.n_tf_wp_layers,
- dx_tf_wp_toroidal_min=self.data.superconducting_tfcoil.dx_tf_wp_toroidal_min,
+ dx_tf_wp_toroidal_min=d_sc_tf.dx_tf_wp_toroidal_min,
n_tf_wp_pancakes=self.data.tfcoil.n_tf_wp_pancakes,
- c_tf_coil=self.data.superconducting_tfcoil.c_tf_coil,
+ c_tf_coil=d_sc_tf.c_tf_coil,
dx_tf_turn_steel=self.data.tfcoil.dx_tf_turn_steel,
dx_tf_turn_insulation=self.data.tfcoil.dx_tf_turn_insulation,
data=self.data,
)
- self.data.superconducting_tfcoil.radius_tf_turn_cable_space_corners = (
+ d_sc_tf.radius_tf_turn_cable_space_corners = (
int_turn_geometry.radius_tf_turn_cable_space_corners
)
- self.data.superconducting_tfcoil.dr_tf_turn = int_turn_geometry.dr_tf_turn
- self.data.superconducting_tfcoil.dx_tf_turn = int_turn_geometry.dx_tf_turn
+ d_sc_tf.dr_tf_turn = int_turn_geometry.dr_tf_turn
+ d_sc_tf.dx_tf_turn = int_turn_geometry.dx_tf_turn
self.data.tfcoil.a_tf_turn_cable_space_no_void = (
int_turn_geometry.a_tf_turn_cable_space_no_void
)
@@ -2321,39 +2294,33 @@ def run(self, output: bool = False):
)
self.data.tfcoil.c_tf_turn = int_turn_geometry.c_tf_turn
self.data.tfcoil.n_tf_coil_turns = int_turn_geometry.n_tf_coil_turns
- self.data.superconducting_tfcoil.t_conductor_radial = (
- int_turn_geometry.t_conductor_radial
- )
- self.data.superconducting_tfcoil.t_conductor_toroidal = (
- int_turn_geometry.t_conductor_toroidal
- )
+ d_sc_tf.t_conductor_radial = int_turn_geometry.t_conductor_radial
+ d_sc_tf.t_conductor_toroidal = int_turn_geometry.t_conductor_toroidal
self.data.tfcoil.t_conductor = int_turn_geometry.t_conductor
- self.data.superconducting_tfcoil.dr_tf_turn_cable_space = (
- int_turn_geometry.dr_tf_turn_cable_space
- )
- self.data.superconducting_tfcoil.dx_tf_turn_cable_space = (
- int_turn_geometry.dx_tf_turn_cable_space
- )
- self.data.superconducting_tfcoil.dx_tf_turn_cable_space_average = (
+ d_sc_tf.dr_tf_turn_cable_space = int_turn_geometry.dr_tf_turn_cable_space
+ d_sc_tf.dx_tf_turn_cable_space = int_turn_geometry.dx_tf_turn_cable_space
+ d_sc_tf.dx_tf_turn_cable_space_average = (
int_turn_geometry.dx_tf_turn_cable_space_average
)
# Calculate number of cables in turn if CICC conductor
# ---------------------------------------------------
- self.data.superconducting_tfcoil.n_tf_turn_superconducting_cables = self.calculate_cable_in_conduit_strand_count(
- a_cable_space=self.data.superconducting_tfcoil.a_tf_turn_cable_space_effective,
- dia_superconductor_strand=self.data.superconducting_tfcoil.dia_tf_turn_superconducting_cable,
+ d_sc_tf.n_tf_turn_superconducting_cables = (
+ self.calculate_cable_in_conduit_strand_count(
+ a_cable_space=d_sc_tf.a_tf_turn_cable_space_effective,
+ dia_superconductor_strand=d_sc_tf.dia_tf_turn_superconducting_cable,
+ )
)
(
- self.data.superconducting_tfcoil.len_tf_coil_superconductor,
- self.data.superconducting_tfcoil.len_tf_superconductor_total,
+ d_sc_tf.len_tf_coil_superconductor,
+ d_sc_tf.len_tf_superconductor_total,
) = self.calculate_cable_in_conduit_superconductor_length(
n_tf_coils=self.data.tfcoil.n_tf_coils,
n_tf_coil_turns=self.data.tfcoil.n_tf_coil_turns,
len_tf_coil=self.data.tfcoil.len_tf_coil,
- n_tf_turn_superconducting_cables=self.data.superconducting_tfcoil.n_tf_turn_superconducting_cables,
+ n_tf_turn_superconducting_cables=d_sc_tf.n_tf_turn_superconducting_cables,
)
# Areas and fractions
@@ -2393,27 +2360,27 @@ def run(self, output: bool = False):
)
# Inboard coil steel area [m2]
- self.data.superconducting_tfcoil.a_tf_coil_inboard_steel = (
+ d_sc_tf.a_tf_coil_inboard_steel = (
self.data.tfcoil.a_tf_coil_inboard_case + self.data.tfcoil.a_tf_wp_steel
)
# Inboard coil steel fraction [-]
- self.data.superconducting_tfcoil.f_a_tf_coil_inboard_steel = (
+ d_sc_tf.f_a_tf_coil_inboard_steel = (
self.data.tfcoil.n_tf_coils
- * self.data.superconducting_tfcoil.a_tf_coil_inboard_steel
+ * d_sc_tf.a_tf_coil_inboard_steel
/ self.data.tfcoil.a_tf_inboard_total
)
# Inboard coil insulation cross-section [m2]
- self.data.superconducting_tfcoil.a_tf_coil_inboard_insulation = (
+ d_sc_tf.a_tf_coil_inboard_insulation = (
self.data.tfcoil.a_tf_coil_wp_turn_insulation
- + self.data.superconducting_tfcoil.a_tf_wp_ground_insulation
+ + d_sc_tf.a_tf_wp_ground_insulation
)
# Inboard coil insulation fraction [-]
- self.data.superconducting_tfcoil.f_a_tf_coil_inboard_insulation = (
+ d_sc_tf.f_a_tf_coil_inboard_insulation = (
self.data.tfcoil.n_tf_coils
- * self.data.superconducting_tfcoil.a_tf_coil_inboard_insulation
+ * d_sc_tf.a_tf_coil_inboard_insulation
/ self.data.tfcoil.a_tf_inboard_total
)
@@ -2423,10 +2390,10 @@ def run(self, output: bool = False):
or self.data.tfcoil.a_tf_wp_extra_void <= 0.0e0
or self.data.tfcoil.a_tf_coil_wp_turn_insulation <= 0.0e0
or self.data.tfcoil.a_tf_wp_steel <= 0.0e0
- or self.data.superconducting_tfcoil.a_tf_coil_inboard_steel <= 0.0e0
- or self.data.superconducting_tfcoil.f_a_tf_coil_inboard_steel <= 0.0e0
- or self.data.superconducting_tfcoil.a_tf_coil_inboard_insulation <= 0.0e0
- or self.data.superconducting_tfcoil.f_a_tf_coil_inboard_insulation <= 0.0e0
+ or d_sc_tf.a_tf_coil_inboard_steel <= 0.0e0
+ or d_sc_tf.f_a_tf_coil_inboard_steel <= 0.0e0
+ or d_sc_tf.a_tf_coil_inboard_insulation <= 0.0e0
+ or d_sc_tf.f_a_tf_coil_inboard_insulation <= 0.0e0
):
logger.error(
"One of the areas or fractions is negative in the internal SC TF "
@@ -2435,10 +2402,10 @@ def run(self, output: bool = False):
f"{self.data.tfcoil.a_tf_wp_extra_void=} "
f"{self.data.tfcoil.a_tf_coil_wp_turn_insulation=} "
f"{self.data.tfcoil.a_tf_wp_steel=} "
- f"{self.data.superconducting_tfcoil.a_tf_coil_inboard_steel=} "
- f"{self.data.superconducting_tfcoil.f_a_tf_coil_inboard_steel=} "
- f"{self.data.superconducting_tfcoil.a_tf_coil_inboard_insulation=} "
- f"{self.data.superconducting_tfcoil.f_a_tf_coil_inboard_insulation=}"
+ f"{d_sc_tf.a_tf_coil_inboard_steel=} "
+ f"{d_sc_tf.f_a_tf_coil_inboard_steel=} "
+ f"{d_sc_tf.a_tf_coil_inboard_insulation=} "
+ f"{d_sc_tf.f_a_tf_coil_inboard_insulation=}"
)
# Calculate TF coil areas and masses
@@ -2517,28 +2484,28 @@ def run(self, output: bool = False):
poisson_copper=self.data.tfcoil.poisson_copper,
i_tf_sup=self.data.tfcoil.i_tf_sup,
eyoung_res_tf_buck=self.data.tfcoil.eyoung_res_tf_buck,
- r_tf_wp_inboard_inner=self.data.superconducting_tfcoil.r_tf_wp_inboard_inner,
- tan_theta_coil=self.data.superconducting_tfcoil.tan_theta_coil,
- rad_tf_coil_inboard_toroidal_half=self.data.superconducting_tfcoil.rad_tf_coil_inboard_toroidal_half,
- r_tf_wp_inboard_outer=self.data.superconducting_tfcoil.r_tf_wp_inboard_outer,
- a_tf_coil_inboard_steel=self.data.superconducting_tfcoil.a_tf_coil_inboard_steel,
- a_tf_plasma_case=self.data.superconducting_tfcoil.a_tf_plasma_case,
- a_tf_coil_nose_case=self.data.superconducting_tfcoil.a_tf_coil_nose_case,
+ r_tf_wp_inboard_inner=d_sc_tf.r_tf_wp_inboard_inner,
+ tan_theta_coil=d_sc_tf.tan_theta_coil,
+ rad_tf_coil_inboard_toroidal_half=d_sc_tf.rad_tf_coil_inboard_toroidal_half,
+ r_tf_wp_inboard_outer=d_sc_tf.r_tf_wp_inboard_outer,
+ a_tf_coil_inboard_steel=d_sc_tf.a_tf_coil_inboard_steel,
+ a_tf_plasma_case=d_sc_tf.a_tf_plasma_case,
+ a_tf_coil_nose_case=d_sc_tf.a_tf_coil_nose_case,
dx_tf_wp_insertion_gap=self.data.tfcoil.dx_tf_wp_insertion_gap,
dx_tf_wp_insulation=self.data.tfcoil.dx_tf_wp_insulation,
n_tf_coil_turns=self.data.tfcoil.n_tf_coil_turns,
i_tf_turns_integer=int(self.data.tfcoil.i_tf_turns_integer),
- dx_tf_turn_cable_space_average=self.data.superconducting_tfcoil.dx_tf_turn_cable_space_average,
- dr_tf_turn_cable_space=self.data.superconducting_tfcoil.dr_tf_turn_cable_space,
+ dx_tf_turn_cable_space_average=d_sc_tf.dx_tf_turn_cable_space_average,
+ dr_tf_turn_cable_space=d_sc_tf.dr_tf_turn_cable_space,
dia_tf_turn_coolant_channel=self.data.tfcoil.dia_tf_turn_coolant_channel,
f_a_tf_turn_cable_copper=self.data.tfcoil.f_a_tf_turn_cable_copper,
dx_tf_turn_steel=self.data.tfcoil.dx_tf_turn_steel,
- dx_tf_side_case_average=self.data.superconducting_tfcoil.dx_tf_side_case_average,
- dx_tf_wp_toroidal_average=self.data.superconducting_tfcoil.dx_tf_wp_toroidal_average,
- a_tf_coil_inboard_insulation=self.data.superconducting_tfcoil.a_tf_coil_inboard_insulation,
+ dx_tf_side_case_average=d_sc_tf.dx_tf_side_case_average,
+ dx_tf_wp_toroidal_average=d_sc_tf.dx_tf_wp_toroidal_average,
+ a_tf_coil_inboard_insulation=d_sc_tf.a_tf_coil_inboard_insulation,
a_tf_wp_steel=self.data.tfcoil.a_tf_wp_steel,
a_tf_wp_conductor=self.data.tfcoil.a_tf_wp_conductor,
- a_tf_wp_with_insulation=self.data.superconducting_tfcoil.a_tf_wp_with_insulation,
+ a_tf_wp_with_insulation=d_sc_tf.a_tf_wp_with_insulation,
eyoung_al=self.data.tfcoil.eyoung_al,
poisson_al=self.data.tfcoil.poisson_al,
fcoolcp=self.data.tfcoil.fcoolcp,
@@ -2546,7 +2513,7 @@ def run(self, output: bool = False):
c_tf_total=self.data.tfcoil.c_tf_total,
dr_tf_plasma_case=self.data.tfcoil.dr_tf_plasma_case,
i_tf_stress_model=self.data.tfcoil.i_tf_stress_model,
- vforce_inboard_tot=self.data.superconducting_tfcoil.vforce_inboard_tot,
+ vforce_inboard_tot=d_sc_tf.vforce_inboard_tot,
i_tf_tresca=self.data.tfcoil.i_tf_tresca,
a_tf_coil_inboard_case=self.data.tfcoil.a_tf_coil_inboard_case,
vforce=self.data.tfcoil.vforce,
@@ -2629,39 +2596,41 @@ def run(self, output: bool = False):
* self.data.tfcoil.n_tf_coil_turns
)
- critical_superconductor_info: TFSuperconductorLimits = self.tf_cable_in_conduit_superconductor_properties(
- a_tf_turn_cable_space=self.data.tfcoil.a_tf_turn_cable_space_no_void,
- a_tf_turn=self.data.tfcoil.a_tf_turn,
- a_tf_turn_cable_space_effective=self.data.superconducting_tfcoil.a_tf_turn_cable_space_effective,
- f_a_tf_turn_cable_space_cooling=self.data.superconducting_tfcoil.f_a_tf_turn_cable_space_cooling,
- b_tf_inboard_peak=self.data.tfcoil.b_tf_inboard_peak_with_ripple,
- f_a_tf_turn_cable_copper=self.data.tfcoil.f_a_tf_turn_cable_copper,
- c_tf_turn=self.data.tfcoil.c_tf_turn,
- j_tf_wp=self.data.tfcoil.j_tf_wp,
- i_tf_superconductor=self.data.tfcoil.i_tf_sc_mat,
- f_strain_scale=self.data.tfcoil.fhts,
- temp_tf_coolant_peak_field=self.data.tfcoil.tftmp,
- bcritsc=self.data.tfcoil.bcritsc,
- tcritsc=self.data.tfcoil.tcritsc,
- data=self.data,
+ critical_superconductor_info = (
+ self.tf_cable_in_conduit_superconductor_properties(
+ a_tf_turn_cable_space=self.data.tfcoil.a_tf_turn_cable_space_no_void,
+ a_tf_turn=self.data.tfcoil.a_tf_turn,
+ a_tf_turn_cable_space_effective=d_sc_tf.a_tf_turn_cable_space_effective,
+ f_a_tf_turn_cable_space_cooling=d_sc_tf.f_a_tf_turn_cable_space_cooling,
+ b_tf_inboard_peak=self.data.tfcoil.b_tf_inboard_peak_with_ripple,
+ f_a_tf_turn_cable_copper=self.data.tfcoil.f_a_tf_turn_cable_copper,
+ c_tf_turn=self.data.tfcoil.c_tf_turn,
+ j_tf_wp=self.data.tfcoil.j_tf_wp,
+ i_tf_superconductor=self.data.tfcoil.i_tf_sc_mat,
+ f_strain_scale=self.data.tfcoil.fhts,
+ temp_tf_coolant_peak_field=self.data.tfcoil.tftmp,
+ bcritsc=self.data.tfcoil.bcritsc,
+ tcritsc=self.data.tfcoil.tcritsc,
+ data=self.data,
+ )
)
self.data.tfcoil.j_tf_wp_critical = critical_superconductor_info.j_tf_wp_critical
- self.data.superconducting_tfcoil.j_tf_superconductor_critical = (
+ d_sc_tf.j_tf_superconductor_critical = (
critical_superconductor_info.j_superconductor_critical
)
- self.data.superconducting_tfcoil.f_c_tf_turn_operating_critical = (
+ d_sc_tf.f_c_tf_turn_operating_critical = (
critical_superconductor_info.f_c_tf_turn_operating_critical
)
- self.data.superconducting_tfcoil.j_tf_superconductor = (
- critical_superconductor_info.j_superconductor
+ d_sc_tf.j_tf_superconductor = critical_superconductor_info.j_superconductor
+ d_sc_tf.j_tf_coil_turn = critical_superconductor_info.j_tf_coil_turn
+ d_sc_tf.b_tf_superconductor_critical_zero_temp_strain = (
+ critical_superconductor_info.bc20m
)
- self.data.superconducting_tfcoil.j_tf_coil_turn = (
- critical_superconductor_info.j_tf_coil_turn
+ d_sc_tf.temp_tf_superconductor_critical_zero_field_strain = (
+ critical_superconductor_info.tc0m
)
- self.data.superconducting_tfcoil.b_tf_superconductor_critical_zero_temp_strain = critical_superconductor_info.bc20m
- self.data.superconducting_tfcoil.temp_tf_superconductor_critical_zero_field_strain = critical_superconductor_info.tc0m
- self.data.superconducting_tfcoil.c_tf_turn_cables_critical = (
+ d_sc_tf.c_tf_turn_cables_critical = (
critical_superconductor_info.c_turn_cables_critical
)
@@ -2670,16 +2639,18 @@ def run(self, output: bool = False):
else:
strain = self.data.tfcoil.str_wp
- self.data.tfcoil.temp_tf_superconductor_margin = self.calculate_superconductor_temperature_margin(
- i_tf_superconductor=self.data.tfcoil.i_tf_sc_mat,
- j_superconductor=self.data.superconducting_tfcoil.j_tf_superconductor,
- b_tf_inboard_peak=self.data.tfcoil.b_tf_inboard_peak_with_ripple,
- strain=strain,
- bc20m=self.data.superconducting_tfcoil.b_tf_superconductor_critical_zero_temp_strain,
- tc0m=self.data.superconducting_tfcoil.temp_tf_superconductor_critical_zero_field_strain,
- c0=1.0e10,
- temp_tf_coolant_peak_field=self.data.tfcoil.tftmp,
- data=self.data,
+ self.data.tfcoil.temp_tf_superconductor_margin = (
+ self.calculate_superconductor_temperature_margin(
+ i_tf_superconductor=self.data.tfcoil.i_tf_sc_mat,
+ j_superconductor=d_sc_tf.j_tf_superconductor,
+ b_tf_inboard_peak=self.data.tfcoil.b_tf_inboard_peak_with_ripple,
+ strain=strain,
+ bc20m=d_sc_tf.b_tf_superconductor_critical_zero_temp_strain,
+ tc0m=d_sc_tf.temp_tf_superconductor_critical_zero_field_strain,
+ c0=1.0e10,
+ temp_tf_coolant_peak_field=self.data.tfcoil.tftmp,
+ data=self.data,
+ )
)
# Do current density protection calculation
@@ -2702,7 +2673,7 @@ def run(self, output: bool = False):
a_tf_turn=self.data.tfcoil.a_tf_turn,
t_tf_quench_dump=self.data.tfcoil.t_tf_superconductor_quench,
f_a_tf_turn_cable_copper=self.data.tfcoil.f_a_tf_turn_cable_copper,
- f_a_tf_turn_cable_space_cooling=self.data.superconducting_tfcoil.f_a_tf_turn_cable_space_cooling,
+ f_a_tf_turn_cable_space_cooling=d_sc_tf.f_a_tf_turn_cable_space_cooling,
temp_tf_coolant_peak_field=self.data.tfcoil.tftmp,
temp_tf_conductor_quench_max=self.data.tfcoil.temp_tf_conductor_quench_max,
b_tf_inboard_peak=self.data.tfcoil.b_tf_inboard_peak_with_ripple,
@@ -2785,15 +2756,8 @@ def tf_cable_in_conduit_superconductor_properties(
Returns
-------
- TFSuperconductorLimits
- - j_tf_wp_critical (float): Critical winding pack current density (A/m²).
- - j_superconductor_critical (float): Critical current density in superconductor (A/m²).
- - f_c_tf_turn_operating_critical (float): Ratio of operating / critical current.
- - j_superconductor_turn (float): Actual current density in superconductor (A/m²).
- - j_tf_coil_turn (float): Actual current density in superconductor (A/m²).
- - b_tf_superconductor_critical_zero_temp_strain (float): Critical field at zero temperature and strain (T).
- - temp_tf_superconductor_critical_zero_field_strain (float): Critical temperature at zero field and strain (K).
- - c_tf_turn_cables_critical (float): Critical current in cable (A).
+ :
+ Superconcting TF coil limits dataclass
Notes
-----
@@ -3305,24 +3269,8 @@ def tf_cable_in_conduit_averaged_turn_geometry(
Returns
-------
- CICCAveragedTurnGeometry
- A dataclass containing the calculated geometry of the TF turn, including:
- - a_tf_turn: Area of the TF turn (in square meters).
- - dx_tf_turn: Dimension of the TF turn (in meters).
- - dr_tf_turn: Dimension of the TF turn (in meters).
- - t_conductor: Thickness of the conductor in the TF turn (in meters).
- - n_tf_coil_turns: Number of turns in the TF coil
- (not necessarily an integer).
- - a_tf_turn_insulation: Area of the insulation in the TF turn
- (in square meters).
- - a_tf_turn_cable_space_no_void: Area of the cable space in the TF turn
- without voids (in square meters).
- - a_tf_turn_steel: Area of the steel in the TF turn (in square meters).
- - a_tf_turn_cable_space_effective: Effective area of the cable space in
- the TF turn after accounting for cooling channels and voids
- (in square meters).
- - f_a_tf_turn_cable_space_cooling: Fraction of the cable space used
- for cooling.
+ :
+ CICC Average Turn Geometry
"""
# Turn dimension is a an input
@@ -3481,28 +3429,8 @@ def tf_cable_in_conduit_integer_turn_geometry(
Returns
-------
- CICCIntegerTurnGeometry
- A dataclass containing the calculated geometry of the TF turn, including:
- - radius_tf_turn_cable_space_corners: Radius of rounded corners in the cable
- space (in meters).
- - dr_tf_turn: Radial dimension of the TF turn (in meters).
- - dx_tf_turn: Toroidal dimension of the TF turn (in meters).
- - a_tf_turn_cable_space_no_void: Area of the cable space in the TF turn
- without voids (in square meters).
- - a_tf_turn_steel: Area of the steel in the TF turn (in square meters).
- - a_tf_turn_insulation: Area of the insulation in the TF turn
- (in square meters).
- - n_tf_coil_turns: Number of turns in the TF coil
- (not necessarily an integer).
- - t_conductor: Thickness of the conductor in the TF turn (in meters).
- - dx_tf_turn_cable_space_average: Average dimension of the cable space in
- the TF turn (in meters).
- - a_tf_turn_cable_space_effective: Effective area of the cable space in the
- TF turn after accounting for cooling channels and
- voids (in square meters).
- - f_a_tf_turn_cable_space_cooling: Fraction of the cable space used
- for cooling.
-
+ :
+ CICC Integer turn geometry
"""
# Radius of rounded corners in the cable space [m]
radius_tf_turn_cable_space_corners = dx_tf_turn_steel * 0.75e0
@@ -3630,7 +3558,12 @@ def tf_cable_in_conduit_integer_turn_geometry(
# -------------
def output_cable_in_conduit_cable_info(self) -> None:
- """Outputs the calculated cable in condutit cable space geometry information for the TF coil."""
+ """
+ Outputs the calculated cable in condutit cable space geometry information
+ for the TF coil.
+ """
+ d_sc_tf = self.data.superconducting_tfcoil
+
po.oheadr(self.outfile, "TF CICC Cable Space Information")
po.ovarre(
self.outfile,
@@ -3642,25 +3575,25 @@ def output_cable_in_conduit_cable_info(self) -> None:
self.outfile,
"Diameter of superconducting cable",
"(dia_tf_turn_superconducting_cable)",
- self.data.superconducting_tfcoil.dia_tf_turn_superconducting_cable,
+ d_sc_tf.dia_tf_turn_superconducting_cable,
)
po.ovarre(
self.outfile,
"Number of superconducting cables per turn",
"(n_tf_turn_superconducting_cables)",
- self.data.superconducting_tfcoil.n_tf_turn_superconducting_cables,
+ d_sc_tf.n_tf_turn_superconducting_cables,
)
po.ovarre(
self.outfile,
"Length of superconductor in TF coil (m)",
"(len_tf_coil_superconductor)",
- self.data.superconducting_tfcoil.len_tf_coil_superconductor,
+ d_sc_tf.len_tf_coil_superconductor,
)
po.ovarre(
self.outfile,
"Total length of superconductor in all TF coils (m)",
"(len_tf_superconductor_total)",
- self.data.superconducting_tfcoil.len_tf_superconductor_total,
+ d_sc_tf.len_tf_superconductor_total,
)
po.ocmmnt(self.outfile, "Fractions by area")
po.ovarre(
@@ -3673,7 +3606,7 @@ def output_cable_in_conduit_cable_info(self) -> None:
self.outfile,
"True area of turn cable space with gaps and channels removed",
"(a_tf_turn_cable_space_effective)",
- self.data.superconducting_tfcoil.a_tf_turn_cable_space_effective,
+ d_sc_tf.a_tf_turn_cable_space_effective,
)
po.ovarre(
@@ -3698,13 +3631,13 @@ def output_cable_in_conduit_cable_info(self) -> None:
self.outfile,
"Total insulation area in TF coil (turn and WP)",
"(a_tf_coil_inboard_insulation)",
- self.data.superconducting_tfcoil.a_tf_coil_inboard_insulation,
+ d_sc_tf.a_tf_coil_inboard_insulation,
)
po.ovarre(
self.outfile,
"Total steel area in inboard TF coil (turn and case)",
"(a_tf_coil_inboard_steel)",
- self.data.superconducting_tfcoil.a_tf_coil_inboard_steel,
+ d_sc_tf.a_tf_coil_inboard_steel,
)
po.ovarre(
self.outfile,
@@ -3839,11 +3772,13 @@ def run(self, output: bool = False):
"""
self.run_base_superconducting_tf()
+ d_sc_tf = self.data.superconducting_tfcoil
+
# Setting the WP turn geometry / areas
if self.data.tfcoil.i_tf_turns_integer == 0:
# Non-ingeger number of turns
- avg_turn_geometry: CROCOAveragedTurnGeometry = self.tf_croco_averaged_turn_geometry(
+ avg_turn_geometry = self.tf_croco_averaged_turn_geometry(
j_tf_wp=self.data.tfcoil.j_tf_wp,
dx_tf_turn_steel=self.data.tfcoil.dx_tf_turn_steel,
dx_tf_turn_insulation=self.data.tfcoil.dx_tf_turn_insulation,
@@ -3853,7 +3788,7 @@ def run(self, output: bool = False):
i_dx_tf_turn_cable_space_general_input=self.data.tfcoil.i_dx_tf_turn_cable_space_general_input,
dx_tf_turn_cable_space_general=self.data.tfcoil.dx_tf_turn_cable_space_general,
layer_ins=self.data.tfcoil.layer_ins,
- a_tf_wp_no_insulation=self.data.superconducting_tfcoil.a_tf_wp_no_insulation,
+ a_tf_wp_no_insulation=d_sc_tf.a_tf_wp_no_insulation,
)
self.data.tfcoil.a_tf_turn_cable_space_no_void = (
@@ -3867,10 +3802,10 @@ def run(self, output: bool = False):
self.data.tfcoil.dx_tf_turn_general = avg_turn_geometry.dx_tf_turn_general
self.data.tfcoil.c_tf_turn = avg_turn_geometry.c_tf_turn
self.data.tfcoil.dx_tf_turn_general = avg_turn_geometry.dx_tf_turn_general
- self.data.superconducting_tfcoil.dr_tf_turn = avg_turn_geometry.dr_tf_turn
- self.data.superconducting_tfcoil.dx_tf_turn = avg_turn_geometry.dx_tf_turn
+ d_sc_tf.dr_tf_turn = avg_turn_geometry.dr_tf_turn
+ d_sc_tf.dx_tf_turn = avg_turn_geometry.dx_tf_turn
self.data.tfcoil.t_conductor = avg_turn_geometry.t_conductor
- self.data.superconducting_tfcoil.dx_tf_turn_cable_space_average = (
+ d_sc_tf.dx_tf_turn_cable_space_average = (
avg_turn_geometry.dx_tf_turn_cable_space_average
)
@@ -3912,161 +3847,122 @@ def run(self, output: bool = False):
)
# Inboard coil steel area [m²]
- self.data.superconducting_tfcoil.a_tf_coil_inboard_steel = (
+ d_sc_tf.a_tf_coil_inboard_steel = (
self.data.tfcoil.a_tf_coil_inboard_case + self.data.tfcoil.a_tf_wp_steel
)
# Inboard coil steel fraction [-]
- self.data.superconducting_tfcoil.f_a_tf_coil_inboard_steel = (
+ d_sc_tf.f_a_tf_coil_inboard_steel = (
self.data.tfcoil.n_tf_coils
- * self.data.superconducting_tfcoil.a_tf_coil_inboard_steel
+ * d_sc_tf.a_tf_coil_inboard_steel
/ self.data.tfcoil.a_tf_inboard_total
)
# Inboard coil insulation cross-section [m²]
- self.data.superconducting_tfcoil.a_tf_coil_inboard_insulation = (
+ d_sc_tf.a_tf_coil_inboard_insulation = (
self.data.tfcoil.a_tf_coil_wp_turn_insulation
- + self.data.superconducting_tfcoil.a_tf_wp_ground_insulation
+ + d_sc_tf.a_tf_wp_ground_insulation
)
# Inboard coil insulation fraction [-]
- self.data.superconducting_tfcoil.f_a_tf_coil_inboard_insulation = (
+ d_sc_tf.f_a_tf_coil_inboard_insulation = (
self.data.tfcoil.n_tf_coils
- * self.data.superconducting_tfcoil.a_tf_coil_inboard_insulation
+ * d_sc_tf.a_tf_coil_inboard_insulation
/ self.data.tfcoil.a_tf_inboard_total
)
- croco_cable_space_geometry: CroCoCableSpaceGeometry = (
- self.tf_turn_croco_cable_space_properties(
- t_conductor=self.data.tfcoil.t_conductor,
- dx_tf_turn_steel=self.data.tfcoil.dx_tf_turn_steel,
- )
+ croco_cable_space_geometry = self.tf_turn_croco_cable_space_properties(
+ t_conductor=self.data.tfcoil.t_conductor,
+ dx_tf_turn_steel=self.data.tfcoil.dx_tf_turn_steel,
)
- self.data.superconducting_tfcoil.dia_tf_turn_croco_cable = (
+ d_sc_tf.dia_tf_turn_croco_cable = (
croco_cable_space_geometry.dia_tf_turn_croco_cable
)
self.data.tfcoil.a_tf_turn_cable_space_no_void = (
croco_cable_space_geometry.a_tf_turn_cable_space_no_void
)
- self.data.superconducting_tfcoil.a_tf_turn_cable_space_effective = (
+ d_sc_tf.a_tf_turn_cable_space_effective = (
croco_cable_space_geometry.a_tf_turn_cable_space_effective
)
self.data.tfcoil.a_tf_turn_steel = croco_cable_space_geometry.a_tf_turn_steel
- self.data.superconducting_tfcoil.conductor_area = (
- croco_cable_space_geometry.conductor_area
- )
- self.data.superconducting_tfcoil.conductor_jacket_area = (
- croco_cable_space_geometry.conductor_jacket_area
- )
- self.data.superconducting_tfcoil.conductor_jacket_fraction = (
+ d_sc_tf.conductor_area = croco_cable_space_geometry.conductor_area
+ d_sc_tf.conductor_jacket_area = croco_cable_space_geometry.conductor_jacket_area
+ d_sc_tf.conductor_jacket_fraction = (
croco_cable_space_geometry.conductor_jacket_fraction
)
- croco_cable_geometry: CroCoCableGeometry = calculate_croco_cable_geometry(
- dia_croco_strand=self.data.superconducting_tfcoil.dia_tf_turn_croco_cable,
- dx_croco_strand_copper=self.data.superconducting_tfcoil.dx_tf_croco_strand_copper,
- dx_hts_tape_rebco=self.data.superconducting_tfcoil.dx_tf_hts_tape_rebco,
- dx_hts_tape_copper=self.data.superconducting_tfcoil.dx_tf_hts_tape_copper,
- dx_hts_tape_hastelloy=self.data.superconducting_tfcoil.dx_tf_hts_tape_hastelloy,
+ croco_cable_geometry = calculate_croco_cable_geometry(
+ dia_croco_strand=d_sc_tf.dia_tf_turn_croco_cable,
+ dx_croco_strand_copper=d_sc_tf.dx_tf_croco_strand_copper,
+ dx_hts_tape_rebco=d_sc_tf.dx_tf_hts_tape_rebco,
+ dx_hts_tape_copper=d_sc_tf.dx_tf_hts_tape_copper,
+ dx_hts_tape_hastelloy=d_sc_tf.dx_tf_hts_tape_hastelloy,
)
- self.data.superconducting_tfcoil.dia_tf_croco_strand_tape_region = (
+ d_sc_tf.dia_tf_croco_strand_tape_region = (
croco_cable_geometry.dia_croco_strand_tape_region
)
- self.data.superconducting_tfcoil.n_tf_croco_strand_hts_tapes = (
+ d_sc_tf.n_tf_croco_strand_hts_tapes = (
croco_cable_geometry.n_croco_strand_hts_tapes
)
- self.data.superconducting_tfcoil.a_tf_croco_strand_copper_total = (
+ d_sc_tf.a_tf_croco_strand_copper_total = (
croco_cable_geometry.a_croco_strand_copper_total
)
- self.data.superconducting_tfcoil.a_tf_croco_strand_hastelloy = (
+ d_sc_tf.a_tf_croco_strand_hastelloy = (
croco_cable_geometry.a_croco_strand_hastelloy
)
- self.data.superconducting_tfcoil.a_tf_croco_strand_solder = (
- croco_cable_geometry.a_croco_strand_solder
- )
- self.data.superconducting_tfcoil.a_tf_croco_strand_rebco = (
- croco_cable_geometry.a_croco_strand_rebco
- )
- self.data.superconducting_tfcoil.a_tf_croco_strand = (
- croco_cable_geometry.a_croco_strand
- )
- self.data.superconducting_tfcoil.dr_tf_hts_tape = (
- croco_cable_geometry.dr_hts_tape
- )
- self.data.superconducting_tfcoil.dx_tf_hts_tape_total = (
- croco_cable_geometry.dx_hts_tape_total
- )
- self.data.superconducting_tfcoil.dx_tf_croco_strand_tape_stack = (
+ d_sc_tf.a_tf_croco_strand_solder = croco_cable_geometry.a_croco_strand_solder
+ d_sc_tf.a_tf_croco_strand_rebco = croco_cable_geometry.a_croco_strand_rebco
+ d_sc_tf.a_tf_croco_strand = croco_cable_geometry.a_croco_strand
+ d_sc_tf.dr_tf_hts_tape = croco_cable_geometry.dr_hts_tape
+ d_sc_tf.dx_tf_hts_tape_total = croco_cable_geometry.dx_hts_tape_total
+ d_sc_tf.dx_tf_croco_strand_tape_stack = (
croco_cable_geometry.dx_croco_strand_tape_stack
)
- self.data.superconducting_tfcoil.a_tf_croco_strand_copper_total = (
- self.data.superconducting_tfcoil.a_tf_croco_strand_copper_total
- )
- self.data.superconducting_tfcoil.a_tf_croco_strand_hastelloy = (
- self.data.superconducting_tfcoil.a_tf_croco_strand_hastelloy
- )
- self.data.superconducting_tfcoil.a_tf_croco_strand_solder = (
- self.data.superconducting_tfcoil.a_tf_croco_strand_solder
- )
- self.data.superconducting_tfcoil.a_tf_croco_strand_rebco = (
- self.data.superconducting_tfcoil.a_tf_croco_strand_rebco
- )
- self.data.superconducting_tfcoil.a_tf_croco_strand = (
- self.data.superconducting_tfcoil.a_tf_croco_strand
- )
+ d_sc_tf.a_tf_croco_strand_copper_total = d_sc_tf.a_tf_croco_strand_copper_total
+ d_sc_tf.a_tf_croco_strand_hastelloy = d_sc_tf.a_tf_croco_strand_hastelloy
+ d_sc_tf.a_tf_croco_strand_solder = d_sc_tf.a_tf_croco_strand_solder
+ d_sc_tf.a_tf_croco_strand_rebco = d_sc_tf.a_tf_croco_strand_rebco
+ d_sc_tf.a_tf_croco_strand = d_sc_tf.a_tf_croco_strand
# Area of core = area of strand
- self.data.superconducting_tfcoil.a_tf_turn_croco_copper_bar = (
- self.data.superconducting_tfcoil.a_tf_croco_strand
- )
- self.data.superconducting_tfcoil.a_tf_turn_croco_cable_space_copper = (
- self.data.superconducting_tfcoil.a_tf_croco_strand_copper_total
- * N_CROCO_STRANDS_TURN
- + self.data.superconducting_tfcoil.a_tf_turn_croco_copper_bar
+ d_sc_tf.a_tf_turn_croco_copper_bar = d_sc_tf.a_tf_croco_strand
+ d_sc_tf.a_tf_turn_croco_cable_space_copper = (
+ d_sc_tf.a_tf_croco_strand_copper_total * N_CROCO_STRANDS_TURN
+ + d_sc_tf.a_tf_turn_croco_copper_bar
)
- self.data.superconducting_tfcoil.conductor_copper_fraction = (
- self.data.superconducting_tfcoil.a_tf_turn_croco_cable_space_copper
- / self.data.superconducting_tfcoil.conductor_area
+ d_sc_tf.conductor_copper_fraction = (
+ d_sc_tf.a_tf_turn_croco_cable_space_copper / d_sc_tf.conductor_area
)
# Helium area is set by the user.
- # conductor_helium_area = cable_helium_fraction * self.data.tfcoil.a_tf_turn_cable_space_no_void
- self.data.superconducting_tfcoil.conductor_helium_area = (
- np.pi / 2.0 * self.data.superconducting_tfcoil.dia_tf_turn_croco_cable**2
- )
- self.data.superconducting_tfcoil.conductor_helium_fraction = (
- self.data.superconducting_tfcoil.conductor_helium_area
- / self.data.superconducting_tfcoil.conductor_area
+ # conductor_helium_area = cable_helium_fraction * self.data.tfcoil.a_tf_turn_cable_space_no_void # noqa: E501
+ d_sc_tf.conductor_helium_area = np.pi / 2.0 * d_sc_tf.dia_tf_turn_croco_cable**2
+ d_sc_tf.conductor_helium_fraction = (
+ d_sc_tf.conductor_helium_area / d_sc_tf.conductor_area
)
- self.data.superconducting_tfcoil.a_tf_turn_croco_hastelloy = (
- self.data.superconducting_tfcoil.a_tf_croco_strand_hastelloy
- * N_CROCO_STRANDS_TURN
+ d_sc_tf.a_tf_turn_croco_hastelloy = (
+ d_sc_tf.a_tf_croco_strand_hastelloy * N_CROCO_STRANDS_TURN
)
- self.data.superconducting_tfcoil.conductor_hastelloy_fraction = (
- self.data.superconducting_tfcoil.a_tf_turn_croco_hastelloy
- / self.data.superconducting_tfcoil.conductor_area
+ d_sc_tf.conductor_hastelloy_fraction = (
+ d_sc_tf.a_tf_turn_croco_hastelloy / d_sc_tf.conductor_area
)
- self.data.superconducting_tfcoil.conductor_solder_area = (
- self.data.superconducting_tfcoil.a_tf_croco_strand_solder
- * N_CROCO_STRANDS_TURN
+ d_sc_tf.conductor_solder_area = (
+ d_sc_tf.a_tf_croco_strand_solder * N_CROCO_STRANDS_TURN
)
- self.data.superconducting_tfcoil.conductor_solder_fraction = (
- self.data.superconducting_tfcoil.conductor_solder_area
- / self.data.superconducting_tfcoil.conductor_area
+ d_sc_tf.conductor_solder_fraction = (
+ d_sc_tf.conductor_solder_area / d_sc_tf.conductor_area
)
- self.data.superconducting_tfcoil.conductor_rebco_area = (
- self.data.superconducting_tfcoil.a_tf_croco_strand_rebco
- * N_CROCO_STRANDS_TURN
+ d_sc_tf.conductor_rebco_area = (
+ d_sc_tf.a_tf_croco_strand_rebco * N_CROCO_STRANDS_TURN
)
- self.data.superconducting_tfcoil.conductor_rebco_fraction = (
- self.data.superconducting_tfcoil.conductor_rebco_area
- / self.data.superconducting_tfcoil.conductor_area
+ d_sc_tf.conductor_rebco_fraction = (
+ d_sc_tf.conductor_rebco_area / d_sc_tf.conductor_area
)
# Cross-sectional area per turn
@@ -4080,34 +3976,34 @@ def run(self, output: bool = False):
SuperconductorModel(self.data.tfcoil.i_tf_sc_mat)
== SuperconductorModel.CROCO_REBCO
):
- superconductor_critical_properties: TFSuperconductorLimits = (
- self.tf_croco_superconductor_properties(
- a_tf_turn=self.data.tfcoil.a_tf_turn,
- b_tf_inboard_peak=self.data.tfcoil.b_tf_inboard_peak_with_ripple,
- cur_tf_turn=self.data.tfcoil.c_tf_turn,
- temp_tf_peak=self.data.tfcoil.tftmp,
- )
+ superconductor_critical_properties = self.tf_croco_superconductor_properties(
+ a_tf_turn=self.data.tfcoil.a_tf_turn,
+ b_tf_inboard_peak=self.data.tfcoil.b_tf_inboard_peak_with_ripple,
+ cur_tf_turn=self.data.tfcoil.c_tf_turn,
+ temp_tf_peak=self.data.tfcoil.tftmp,
)
self.data.tfcoil.j_tf_wp_critical = (
superconductor_critical_properties.j_tf_wp_critical
)
- self.data.superconducting_tfcoil.j_tf_superconductor_critical = (
+ d_sc_tf.j_tf_superconductor_critical = (
superconductor_critical_properties.j_superconductor_critical
)
- self.data.superconducting_tfcoil.f_c_tf_turn_operating_critical = (
+ d_sc_tf.f_c_tf_turn_operating_critical = (
superconductor_critical_properties.f_c_tf_turn_operating_critical
)
- self.data.superconducting_tfcoil.j_tf_superconductor = (
+ d_sc_tf.j_tf_superconductor = (
superconductor_critical_properties.j_superconductor
)
- self.data.superconducting_tfcoil.j_tf_coil_turn = (
- superconductor_critical_properties.j_tf_coil_turn
- )
+ d_sc_tf.j_tf_coil_turn = superconductor_critical_properties.j_tf_coil_turn
- self.data.superconducting_tfcoil.b_tf_superconductor_critical_zero_temp_strain = superconductor_critical_properties.bc20m
- self.data.superconducting_tfcoil.temp_tf_superconductor_critical_zero_field_strain = superconductor_critical_properties.tc0m
- self.data.superconducting_tfcoil.c_tf_turn_cables_critical = (
+ d_sc_tf.b_tf_superconductor_critical_zero_temp_strain = (
+ superconductor_critical_properties.bc20m
+ )
+ d_sc_tf.temp_tf_superconductor_critical_zero_field_strain = (
+ superconductor_critical_properties.tc0m
+ )
+ d_sc_tf.c_tf_turn_cables_critical = (
superconductor_critical_properties.c_turn_cables_critical
)
@@ -4121,10 +4017,10 @@ def run(self, output: bool = False):
or self.data.tfcoil.a_tf_wp_extra_void <= 0.0e0
or self.data.tfcoil.a_tf_coil_wp_turn_insulation <= 0.0e0
or self.data.tfcoil.a_tf_wp_steel <= 0.0e0
- or self.data.superconducting_tfcoil.a_tf_coil_inboard_steel <= 0.0e0
- or self.data.superconducting_tfcoil.f_a_tf_coil_inboard_steel <= 0.0e0
- or self.data.superconducting_tfcoil.a_tf_coil_inboard_insulation <= 0.0e0
- or self.data.superconducting_tfcoil.f_a_tf_coil_inboard_insulation <= 0.0e0
+ or d_sc_tf.a_tf_coil_inboard_steel <= 0.0e0
+ or d_sc_tf.f_a_tf_coil_inboard_steel <= 0.0e0
+ or d_sc_tf.a_tf_coil_inboard_insulation <= 0.0e0
+ or d_sc_tf.f_a_tf_coil_inboard_insulation <= 0.0e0
):
logger.error(
"One of the areas or fractions is negative in the internal SC TF "
@@ -4133,10 +4029,10 @@ def run(self, output: bool = False):
f"{self.data.tfcoil.a_tf_wp_extra_void=} "
f"{self.data.tfcoil.a_tf_coil_wp_turn_insulation=} "
f"{self.data.tfcoil.a_tf_wp_steel=} "
- f"{self.data.superconducting_tfcoil.a_tf_coil_inboard_steel=} "
- f"{self.data.superconducting_tfcoil.f_a_tf_coil_inboard_steel=} "
- f"{self.data.superconducting_tfcoil.a_tf_coil_inboard_insulation=} "
- f"{self.data.superconducting_tfcoil.f_a_tf_coil_inboard_insulation=}"
+ f"{d_sc_tf.a_tf_coil_inboard_steel=} "
+ f"{d_sc_tf.f_a_tf_coil_inboard_steel=} "
+ f"{d_sc_tf.a_tf_coil_inboard_insulation=} "
+ f"{d_sc_tf.f_a_tf_coil_inboard_insulation=}"
)
# Calculate TF coil areas and masses
@@ -4215,28 +4111,28 @@ def run(self, output: bool = False):
poisson_copper=self.data.tfcoil.poisson_copper,
i_tf_sup=self.data.tfcoil.i_tf_sup,
eyoung_res_tf_buck=self.data.tfcoil.eyoung_res_tf_buck,
- r_tf_wp_inboard_inner=self.data.superconducting_tfcoil.r_tf_wp_inboard_inner,
- tan_theta_coil=self.data.superconducting_tfcoil.tan_theta_coil,
- rad_tf_coil_inboard_toroidal_half=self.data.superconducting_tfcoil.rad_tf_coil_inboard_toroidal_half,
- r_tf_wp_inboard_outer=self.data.superconducting_tfcoil.r_tf_wp_inboard_outer,
- a_tf_coil_inboard_steel=self.data.superconducting_tfcoil.a_tf_coil_inboard_steel,
- a_tf_plasma_case=self.data.superconducting_tfcoil.a_tf_plasma_case,
- a_tf_coil_nose_case=self.data.superconducting_tfcoil.a_tf_coil_nose_case,
+ r_tf_wp_inboard_inner=d_sc_tf.r_tf_wp_inboard_inner,
+ tan_theta_coil=d_sc_tf.tan_theta_coil,
+ rad_tf_coil_inboard_toroidal_half=d_sc_tf.rad_tf_coil_inboard_toroidal_half,
+ r_tf_wp_inboard_outer=d_sc_tf.r_tf_wp_inboard_outer,
+ a_tf_coil_inboard_steel=d_sc_tf.a_tf_coil_inboard_steel,
+ a_tf_plasma_case=d_sc_tf.a_tf_plasma_case,
+ a_tf_coil_nose_case=d_sc_tf.a_tf_coil_nose_case,
dx_tf_wp_insertion_gap=self.data.tfcoil.dx_tf_wp_insertion_gap,
dx_tf_wp_insulation=self.data.tfcoil.dx_tf_wp_insulation,
n_tf_coil_turns=self.data.tfcoil.n_tf_coil_turns,
i_tf_turns_integer=int(self.data.tfcoil.i_tf_turns_integer),
- dx_tf_turn_cable_space_average=self.data.superconducting_tfcoil.dx_tf_turn_cable_space_average,
- dr_tf_turn_cable_space=self.data.superconducting_tfcoil.dr_tf_turn_cable_space,
+ dx_tf_turn_cable_space_average=d_sc_tf.dx_tf_turn_cable_space_average,
+ dr_tf_turn_cable_space=d_sc_tf.dr_tf_turn_cable_space,
dia_tf_turn_coolant_channel=self.data.tfcoil.dia_tf_turn_coolant_channel,
f_a_tf_turn_cable_copper=self.data.tfcoil.f_a_tf_turn_cable_copper,
dx_tf_turn_steel=self.data.tfcoil.dx_tf_turn_steel,
- dx_tf_side_case_average=self.data.superconducting_tfcoil.dx_tf_side_case_average,
- dx_tf_wp_toroidal_average=self.data.superconducting_tfcoil.dx_tf_wp_toroidal_average,
- a_tf_coil_inboard_insulation=self.data.superconducting_tfcoil.a_tf_coil_inboard_insulation,
+ dx_tf_side_case_average=d_sc_tf.dx_tf_side_case_average,
+ dx_tf_wp_toroidal_average=d_sc_tf.dx_tf_wp_toroidal_average,
+ a_tf_coil_inboard_insulation=d_sc_tf.a_tf_coil_inboard_insulation,
a_tf_wp_steel=self.data.tfcoil.a_tf_wp_steel,
a_tf_wp_conductor=self.data.tfcoil.a_tf_wp_conductor,
- a_tf_wp_with_insulation=self.data.superconducting_tfcoil.a_tf_wp_with_insulation,
+ a_tf_wp_with_insulation=d_sc_tf.a_tf_wp_with_insulation,
eyoung_al=self.data.tfcoil.eyoung_al,
poisson_al=self.data.tfcoil.poisson_al,
fcoolcp=self.data.tfcoil.fcoolcp,
@@ -4244,7 +4140,7 @@ def run(self, output: bool = False):
c_tf_total=self.data.tfcoil.c_tf_total,
dr_tf_plasma_case=self.data.tfcoil.dr_tf_plasma_case,
i_tf_stress_model=self.data.tfcoil.i_tf_stress_model,
- vforce_inboard_tot=self.data.superconducting_tfcoil.vforce_inboard_tot,
+ vforce_inboard_tot=d_sc_tf.vforce_inboard_tot,
i_tf_tresca=self.data.tfcoil.i_tf_tresca,
a_tf_coil_inboard_case=self.data.tfcoil.a_tf_coil_inboard_case,
vforce=self.data.tfcoil.vforce,
@@ -4338,7 +4234,7 @@ def run(self, output: bool = False):
a_tf_turn_cable_space=self.data.tfcoil.a_tf_turn_cable_space_no_void,
a_tf_turn=self.data.tfcoil.a_tf_turn,
t_tf_quench_dump=self.data.tfcoil.t_tf_superconductor_quench,
- f_a_tf_turn_cable_space_cooling=self.data.superconducting_tfcoil.f_a_tf_turn_cable_space_cooling,
+ f_a_tf_turn_cable_space_cooling=d_sc_tf.f_a_tf_turn_cable_space_cooling,
f_a_tf_turn_cable_copper=self.data.tfcoil.f_a_tf_turn_cable_copper,
temp_tf_coolant_peak_field=self.data.tfcoil.tftmp,
temp_tf_conductor_quench_max=self.data.tfcoil.temp_tf_conductor_quench_max,
@@ -4358,7 +4254,9 @@ def run(self, output: bool = False):
self.output_croco_info()
def output(self) -> None:
- """Output the results of the superconducting TF coil model for a CroCo conductor."""
+ """
+ Output the results of the superconducting TF coil model for a CroCo conductor.
+ """
self.output_general_tf_info()
self.output_general_superconducting_tf_info()
self.output_croco_info()
@@ -4438,7 +4336,8 @@ def tf_croco_averaged_turn_geometry(
# Area of turn including conduit and inter-layer insulation
a_tf_turn = c_tf_turn / j_tf_wp
- # Dimension of square cross-section of each turn including inter-turn insulation [m]
+ # Dimension of square cross-section of each turn
+ # including inter-turn insulation [m]
dx_tf_turn_general = np.sqrt(a_tf_turn)
# Square turn assumption
@@ -4500,22 +4399,18 @@ def tf_croco_superconductor_properties(
temp_conductor=temp_tf_peak, b_conductor=b_tf_inboard_peak
)
- self.data.superconducting_tfcoil.cur_tf_turn_croco_strand_critical = (
- j_crit_sc * self.data.superconducting_tfcoil.a_tf_croco_strand
- )
+ d_sc_tf = self.data.superconducting_tfcoil
+
+ d_sc_tf.cur_tf_turn_croco_strand_critical = j_crit_sc * d_sc_tf.a_tf_croco_strand
# Conductor properties
- self.data.superconducting_tfcoil.conductor_critical_current = (
- self.data.superconducting_tfcoil.cur_tf_turn_croco_strand_critical
- * N_CROCO_STRANDS_TURN
+ d_sc_tf.conductor_critical_current = (
+ d_sc_tf.cur_tf_turn_croco_strand_critical * N_CROCO_STRANDS_TURN
)
- self.data.superconducting_tfcoil.tf_coppera_m2 = (
- cur_tf_turn
- / self.data.superconducting_tfcoil.a_tf_turn_croco_cable_space_copper
- )
+ d_sc_tf.tf_coppera_m2 = cur_tf_turn / d_sc_tf.a_tf_turn_croco_cable_space_copper
- cur_critical = self.data.superconducting_tfcoil.conductor_critical_current
+ cur_critical = d_sc_tf.conductor_critical_current
# Critical current density in winding pack
# a_tf_turn : Area per turn (i.e. entire jacketed conductor with insulation) (m2)
@@ -4545,7 +4440,7 @@ def tf_croco_superconductor_properties(
j_tf_coil_turn=jwdgop,
bc20m=bc20m,
tc0m=tc0m,
- c_turn_cables_critical=self.data.superconducting_tfcoil.cur_tf_turn_croco_strand_critical,
+ c_turn_cables_critical=d_sc_tf.cur_tf_turn_croco_strand_critical,
)
@staticmethod
@@ -4564,25 +4459,8 @@ def tf_turn_croco_cable_space_properties(
Returns
-------
- CroCoCableSpaceGeometry
- A dataclass containing the calculated properties of the cable space in
- the TF turn, including:
- - dia_tf_turn_croco_cable: Diameter of the circular cable space in the TF
- turn (in meters).
- - a_tf_turn_cable_space_no_void: Area of the cable space in the TF turn
- without voids (in square meters).
- - a_tf_turn_cable_space_effective: Effective area of the cable space in
- the TF turn after accounting for cooling channels and voids
- (in square meters).
- - a_tf_turn_steel: Area of the steel in the TF turn (in square meters).
- - conductor_area: Total area of the conductor in the TF turn
- (in square meters).
- - conductor_jacket_area: Area of the conductor jacket in the TF turn
- (in square meters).
- - conductor_jacket_fraction: Fraction of the conductor area that is the
- jacket (dimensionless).
-
-
+ :
+ CroCo cable space geometry
"""
dia_tf_turn_croco_cable = t_conductor / 3.0e0 - dx_tf_turn_steel * (
2.0e0 / 3.0e0
@@ -4616,13 +4494,13 @@ def tf_turn_croco_cable_space_properties(
)
def croco_voltage(self) -> float:
+ d_sc_tf = self.data.superconducting_tfcoil
+
if self.data.tfcoil.quench_model == "linear":
- self.data.superconducting_tfcoil.time2 = (
- self.data.tfcoil.t_tf_superconductor_quench
- )
+ d_sc_tf.time2 = self.data.tfcoil.t_tf_superconductor_quench
croco_voltage = (
2.0e0
- / self.data.superconducting_tfcoil.time2
+ / d_sc_tf.time2
* (
self.data.tfcoil.e_tf_magnetic_stored_total
/ self.data.tfcoil.n_tf_coils
@@ -4630,12 +4508,10 @@ def croco_voltage(self) -> float:
/ self.data.tfcoil.c_tf_turn
)
elif self.data.tfcoil.quench_model == "exponential":
- self.data.superconducting_tfcoil.tau2 = (
- self.data.tfcoil.t_tf_superconductor_quench
- )
+ d_sc_tf.tau2 = self.data.tfcoil.t_tf_superconductor_quench
croco_voltage = (
2.0e0
- / self.data.superconducting_tfcoil.tau2
+ / d_sc_tf.tau2
* (
self.data.tfcoil.e_tf_magnetic_stored_total
/ self.data.tfcoil.n_tf_coils
@@ -4649,38 +4525,40 @@ def croco_voltage(self) -> float:
def output_croco_info(self) -> None:
"""Output the CroCo conductor geometry and properties."""
+ d_sc_tf = self.data.superconducting_tfcoil
+
po.oheadr(self.outfile, "TF CroCo Cable Space Information")
po.ovarre(
self.outfile,
"Thickness of REBCO layer in tape (m)",
"(dx_tf_hts_tape_rebco)",
- self.data.superconducting_tfcoil.dx_tf_hts_tape_rebco,
+ d_sc_tf.dx_tf_hts_tape_rebco,
)
po.ovarre(
self.outfile,
"Thickness of copper layer in tape (m)",
"(dx_tf_hts_tape_copper)",
- self.data.superconducting_tfcoil.dx_tf_hts_tape_copper,
+ d_sc_tf.dx_tf_hts_tape_copper,
)
po.ovarre(
self.outfile,
"Thickness of Hastelloy layer in tape (m) ",
"(dx_tf_hts_tape_hastelloy)",
- self.data.superconducting_tfcoil.dx_tf_hts_tape_hastelloy,
+ d_sc_tf.dx_tf_hts_tape_hastelloy,
)
po.ovarre(
self.outfile,
"Thickness of each HTS tape ",
"(dx_tf_hts_tape_total)",
- self.data.superconducting_tfcoil.dx_tf_hts_tape_total,
+ d_sc_tf.dx_tf_hts_tape_total,
"OP ",
)
po.ovarre(
self.outfile,
"Mean width of tape (m)",
"(dr_tf_hts_tape)",
- self.data.superconducting_tfcoil.dr_tf_hts_tape,
+ d_sc_tf.dr_tf_hts_tape,
"OP ",
)
po.oblnkl(self.outfile)
@@ -4689,34 +4567,34 @@ def output_croco_info(self) -> None:
self.outfile,
"Diameter of a CroCo strand (m) ",
"(dia_tf_turn_croco_cable)",
- self.data.superconducting_tfcoil.dia_tf_turn_croco_cable,
+ d_sc_tf.dia_tf_turn_croco_cable,
"OP ",
)
po.ovarre(
self.outfile,
"Inner diameter of CroCo strand tape region (m) ",
"(dia_tf_croco_strand_tape_region)",
- self.data.superconducting_tfcoil.dia_tf_croco_strand_tape_region,
+ d_sc_tf.dia_tf_croco_strand_tape_region,
"OP ",
)
po.ovarre(
self.outfile,
"Side thickness of copper in CroCo strand (m) ",
"(dx_tf_croco_strand_copper)",
- self.data.superconducting_tfcoil.dx_tf_croco_strand_copper,
+ d_sc_tf.dx_tf_croco_strand_copper,
)
po.ovarre(
self.outfile,
"Total thickness of tape stack in CroCo strand (m) ",
"(dx_tf_croco_strand_tape_stack)",
- self.data.superconducting_tfcoil.dx_tf_croco_strand_tape_stack,
+ d_sc_tf.dx_tf_croco_strand_tape_stack,
"OP ",
)
po.ovarre(
self.outfile,
"Number of HTS tapes in CroCo strand",
"(n_tf_croco_strand_hts_tapes)",
- self.data.superconducting_tfcoil.n_tf_croco_strand_hts_tapes,
+ d_sc_tf.n_tf_croco_strand_hts_tapes,
"OP ",
)
po.oblnkl(self.outfile)
@@ -4724,52 +4602,52 @@ def output_croco_info(self) -> None:
self.outfile,
"Area of total CroCo strand (m²)",
"(a_tf_croco_strand)",
- self.data.superconducting_tfcoil.a_tf_croco_strand,
+ d_sc_tf.a_tf_croco_strand,
"OP ",
)
po.ovarre(
self.outfile,
"Area of REBCO in strand (m²)",
"(a_tf_croco_strand_rebco)",
- self.data.superconducting_tfcoil.a_tf_croco_strand_rebco,
+ d_sc_tf.a_tf_croco_strand_rebco,
"OP ",
)
po.ovarre(
self.outfile,
"Area of copper in strand (m²)",
"(a_tf_croco_strand_copper_total)",
- self.data.superconducting_tfcoil.a_tf_croco_strand_copper_total,
+ d_sc_tf.a_tf_croco_strand_copper_total,
"OP ",
)
po.ovarre(
self.outfile,
"Area of hastelloy substrate in strand (m²) ",
"(a_tf_croco_strand_hastelloy)",
- self.data.superconducting_tfcoil.a_tf_croco_strand_hastelloy,
+ d_sc_tf.a_tf_croco_strand_hastelloy,
"OP ",
)
po.ovarre(
self.outfile,
"Area of solder in strand (m²) ",
"(a_tf_croco_strand_solder)",
- self.data.superconducting_tfcoil.a_tf_croco_strand_solder,
+ d_sc_tf.a_tf_croco_strand_solder,
"OP ",
)
po.ovarre(
self.outfile,
"Total: area of CroCo strand (m²) ",
"(a_tf_croco_strand)",
- self.data.superconducting_tfcoil.a_tf_croco_strand,
+ d_sc_tf.a_tf_croco_strand,
"OP ",
)
if (
abs(
- self.data.superconducting_tfcoil.a_tf_croco_strand
+ d_sc_tf.a_tf_croco_strand
- (
- self.data.superconducting_tfcoil.a_tf_croco_strand_rebco
- + self.data.superconducting_tfcoil.a_tf_croco_strand_copper_total
- + self.data.superconducting_tfcoil.a_tf_croco_strand_hastelloy
- + self.data.superconducting_tfcoil.a_tf_croco_strand_solder
+ d_sc_tf.a_tf_croco_strand_rebco
+ + d_sc_tf.a_tf_croco_strand_copper_total
+ + d_sc_tf.a_tf_croco_strand_hastelloy
+ + d_sc_tf.a_tf_croco_strand_solder
)
)
> 1e-6
@@ -4809,56 +4687,56 @@ def output_croco_info(self) -> None:
self.outfile,
"Area of conductor (m²)",
"(area)",
- self.data.superconducting_tfcoil.conductor_area,
+ d_sc_tf.conductor_area,
"OP ",
)
po.ovarre(
self.outfile,
"REBCO area of conductor (m²)",
"(a_tf_croco_strand_rebco)",
- self.data.superconducting_tfcoil.conductor_rebco_area,
+ d_sc_tf.conductor_rebco_area,
"OP ",
)
po.ovarre(
self.outfile,
"Area of central copper bar (m²)",
"(copper_bar_area)",
- self.data.superconducting_tfcoil.a_tf_turn_croco_copper_bar,
+ d_sc_tf.a_tf_turn_croco_copper_bar,
"OP ",
)
po.ovarre(
self.outfile,
"Total copper area of conductor, total (m²)",
"(a_tf_croco_strand_copper_total)",
- self.data.superconducting_tfcoil.a_tf_turn_croco_cable_space_copper,
+ d_sc_tf.a_tf_turn_croco_cable_space_copper,
"OP ",
)
po.ovarre(
self.outfile,
"Hastelloy area of conductor (m²)",
"(a_tf_croco_strand_hastelloy)",
- self.data.superconducting_tfcoil.a_tf_turn_croco_hastelloy,
+ d_sc_tf.a_tf_turn_croco_hastelloy,
"OP ",
)
po.ovarre(
self.outfile,
"Solder area of conductor (m²)",
"(a_tf_croco_strand_solder)",
- self.data.superconducting_tfcoil.conductor_solder_area,
+ d_sc_tf.conductor_solder_area,
"OP ",
)
po.ovarre(
self.outfile,
"Jacket area of conductor (m²)",
"(jacket_area)",
- self.data.superconducting_tfcoil.conductor_jacket_area,
+ d_sc_tf.conductor_jacket_area,
"OP ",
)
po.ovarre(
self.outfile,
"Helium area of conductor (m²)",
"(helium_area)",
- self.data.superconducting_tfcoil.conductor_helium_area,
+ d_sc_tf.conductor_helium_area,
"OP ",
)
@@ -4866,14 +4744,14 @@ def output_croco_info(self) -> None:
self.outfile,
"Critical current of CroCo strand (A)",
"(cur_tf_turn_croco_strand_critical)",
- self.data.superconducting_tfcoil.cur_tf_turn_croco_strand_critical,
+ d_sc_tf.cur_tf_turn_croco_strand_critical,
"OP ",
)
po.ovarre(
self.outfile,
"Critical current of conductor (A) ",
"(conductor_critical_current)",
- self.data.superconducting_tfcoil.conductor_critical_current,
+ d_sc_tf.conductor_critical_current,
"OP ",
)
diff --git a/pyproject.toml b/pyproject.toml
index ae07024b67..3959bc6da8 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -115,7 +115,7 @@ dependencies = ["pre-commit", "ruff", "ty"]
[tool.hatch.envs.lint.scripts]
fmt = ["pre-commit run --all-files --hook-stage manual {args:}"]
-fmt_extra = ["ruff check --select=E501,C901,PLR0904,PLR0912,PLR0913,PLR0914,PLR0915,PLR0916,PLR0917,PLR1702,D100,D101,D102,D103,DOC501,D404,D104,D105,S307 {args:.}"]
+fmt_extra = ["ruff check --select=C901,PLR0904,PLR0912,PLR0913,PLR0914,PLR0915,PLR0916,PLR0917,PLR1702,D100,D101,D102,D103,DOC501,D404,D104,D105,S307 {args:.}"]
[tool.coverage.report]
exclude_lines = ["no cov", "if __name__ == .__main__.:", "if TYPE_CHECKING:"]
@@ -194,6 +194,7 @@ max-locals = 17
]
"examples/**" = [ 'B018', 'E402']
"{tests,tracking,documentation/scripts,examples}/**" = ['INP001']
+"process/{core/io/plot/summary.py,data_structure/*}" = ["E501"]
[tool.ruff.lint]
preview = true
@@ -234,7 +235,6 @@ ignore = [
"G004",
# urgent removal remainder
- "E501",
# complexity
"C901",
"PLR0904",
diff --git a/tracking/git.py b/tracking/git.py
index 558c18e220..0d8fa2dc89 100644
--- a/tracking/git.py
+++ b/tracking/git.py
@@ -1,19 +1,26 @@
-"""Simple submodule to provide access to some git attributes about the current repository"""
+"""Simple submodule to provide access to some git attributes about the repository"""
import subprocess # noqa: S404
from pathlib import Path
-def git_commit_message(directory=None) -> str:
- """Get the commit message for `directory` or, if `directory` is not provided, the current working directory.
-
- Will raise a subprocess.CalledProcessError if the directory checked is not a git repository.
+def git_commit_message(directory=str | bytes | None) -> str:
+ """Get the commit message for `directory` or the current directory if not provided
+ Parameters
+ ----------
:param directory: the directory to get the commit message at
- :type directory: str | bytes | path-like
- :return commit_message: the commit message for the git repository
- :type commit_message: str
+ Returns
+ -------
+ :
+ the commit message for the git repository
+
+ Raises
+ ------
+ subprocess.CalledProcessError
+ if the directory checked is not a git repository.
+
"""
if directory is None:
directory = Path.cwd()
@@ -30,15 +37,21 @@ def git_commit_message(directory=None) -> str:
def git_commit_hash(directory=None) -> str:
- """Get the commit hash for `directory` or, if `directory` is not provided, the current working directory.
+ """Get the commit hash for `directory` or the current directory if not provided
- Will raise a subprocess.CalledProcessError if the directory checked is not a git repository.
+ Parameters
+ ----------
+ :param directory: the directory to get the commit hash at
- :param directory: the directory to get the commit hash for
- :type directory: str | bytes | path-like
+ Returns
+ -------
+ :
+ the commit hash for the git repository
- :return commit_hash: the commit hash for the git repository
- :type commit_hash: str
+ Raises
+ ------
+ subprocess.CalledProcessError
+ if the directory checked is not a git repository.
"""
if directory is None:
directory = Path.cwd()
diff --git a/tracking/run_tracking_inputs.py b/tracking/run_tracking_inputs.py
index 1bad54f125..7960623468 100755
--- a/tracking/run_tracking_inputs.py
+++ b/tracking/run_tracking_inputs.py
@@ -75,7 +75,8 @@ def tracking(arguments):
type=Path,
default=None,
help="A JSON file containing a list of variables to track."
- "See the description of DEFAULT_TRACKING_VARIABLES for details on formatting the strings in the list.",
+ "See the description of DEFAULT_TRACKING_VARIABLES "
+ "for details on formatting the strings in the list.",
)
subparser_trk.add_argument("--strict", action="store_true", default=False)
diff --git a/tracking/tracking_data.py b/tracking/tracking_data.py
index 68608fbd5c..e9af8d9230 100644
--- a/tracking/tracking_data.py
+++ b/tracking/tracking_data.py
@@ -1,33 +1,48 @@
"""The tracking tool aims to provide a CLI for two important tracking tools.
-We can generate tracking data for a given run of PROCESS, which corresponds to one output MFile.
-When generating tracking data, we store metadata about the run, such as time and commit message,
-and also variable data: the value of a given variable during this run; this is all stored in one
-JSON file.
-
-* Run title: the name of the run input, and hence output, file (e.g. baseline 2018).
-* Tracking history: the data held within all JSON files in the database that span many variables,
-many different run titles and spans a period of time.
-* Variable history: the data held within all JSON files in the database for a given variable;
-not all run titles will have a history for each variable being tracked
-* A run of PROCESS: refers to the output MFile from the running of one input file
-* JSON file: holds the metadata, and tracking data, generated by a run of PROCESS
-
-We can also plot a database of JSON files. The tracking history (ie all the data) must be loaded
-before being processed into a dataframe. This dataframe is then processed into a tracking dashboard:
-
-* The dashboard: represented by the entire html file generated, contains many panels
-* Panels: each parent module (or variable namespace) has its own tab which contains many graphs
-* Graphs: each graph shows the variable history of one variable, it will have many lines
-* Lines: each line represents many datapoints for a single variable, over a period of time,
-that all come from the same run title
-* Datapoints: the value of a variable at a point in time during a given run
+We can generate tracking data for a given run of PROCESS,
+which corresponds to one output MFile.
+When generating tracking data, we store metadata about the run,
+such as time and commit message,
+and also variable data: the value of a given variable during this run;
+this is all stored in one JSON file.
+
+* Run title:
+ the name of the run input, and hence output, file (e.g. baseline 2018).
+* Tracking history:
+ the data held within all JSON files in the database that span many variables,
+ many different run titles and spans a period of time.
+* Variable history:
+ the data held within all JSON files in the database for a given variable;
+ not all run titles will have a history for each variable being tracked
+* A run of PROCESS:
+ refers to the output MFile from the running of one input file
+* JSON file:
+ holds the metadata, and tracking data, generated by a run of PROCESS
+
+We can also plot a database of JSON files.
+The tracking history (ie all the data) must be loaded
+before being processed into a dataframe.
+This dataframe is then processed into a tracking dashboard:
+
+* The dashboard:
+ represented by the entire html file generated, contains many panels
+* Panels:
+ each parent module (or variable namespace) has its own tab which contains many graphs
+* Graphs:
+ each graph shows the variable history of one variable, it will have many lines
+* Lines:
+ each line represents many datapoints for a single variable,
+ over a period of time, that all come from the same run title
+* Datapoints:
+ the value of a variable at a point in time during a given run
To add a variable to track:
Add the variable to ProcessTracker.tracking_variables (in this file).
-If the variable is not a fortran module variable, ensure to override its parent module name
+If the variable is not a fortran module variable,
+ensure to override its parent module name
e.g. FOO.bar says `bar`'s parent module is `FOO`.
"""
@@ -141,7 +156,9 @@
class TrackingFile:
- """Acts as the data storage for a given JSON file ie. holds the data from a run of PROCESS
+ """Acts as the data storage for a given JSON file
+
+ ie. holds the data from a run of PROCESS
e.g. starfire_MFILE--