Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

plasma temperature units are now all provided in keV. #2892

Open
wants to merge 7 commits into
base: develop
Choose a base branch
from
45 changes: 32 additions & 13 deletions bluemira/base/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,11 @@ def _add_contexts(self, contexts: Optional[List[Context]] = None):
Add new contexts to registry
"""
if not self._contexts_added:
self.contexts = [self._energy_temperature_context(), self._flow_context()]
self.contexts = [
self._energy_temperature_context(),
self._mass_energy_context(),
self._flow_context(),
]

for c in self.contexts:
self.add_context(c)
Expand Down Expand Up @@ -107,6 +111,31 @@ def _energy_temperature_context(self):
lambda _, x: x / conversion,
)

def _mass_energy_context(self):
"""
Converter between mass and energy

energy = mass * speed-of-light^2

Returns
-------
pint context
"""
m_to_e = Context("Mass_to_Energy")

m_units = "[mass]"
e_units = "[energy]"

conversion = self.Quantity("c^2")

return self._transform(
m_to_e,
m_units,
e_units,
lambda _, x: x * conversion,
lambda _, x: x / conversion,
)

@property
def flow_conversion(self):
"""Gas flow conversion factor R * T"""
Expand Down Expand Up @@ -248,15 +277,14 @@ def _transform(
# Physical constants
# =============================================================================

# Speed of light
C_LIGHT = ureg.Quantity("c").to_base_units().magnitude # [m/s]

# Vacuum permeability
MU_0 = ureg.Quantity("mu_0").to_base_units().magnitude # [T.m/A] or [V.s/(A.m)]

# Vacuum permittivity
EPS_0 = ureg.Quantity("eps_0").to_base_units().magnitude # [A^2.s^4/kg/m^3]

# absolute charge of an electron
ELEMENTARY_CHARGE = ureg.Quantity("e").to_base_units().magnitude # [e]

# Commonly used..
MU_0_2PI = 2e-7 # [T.m/A] or [V.s/(A.m)]
Expand Down Expand Up @@ -337,15 +365,6 @@ def _transform(
# Conversions
# =============================================================================

# Electron-volts to Joules
EV_TO_J = ureg.Quantity(1, ureg.eV).to(ureg.joule).magnitude

# Joules to Electron-volts
J_TO_EV = ureg.Quantity(1, ureg.joule).to(ureg.eV).magnitude

# Atomic mass units to kilograms
AMU_TO_KG = ureg.Quantity(1, ureg.amu).to(ureg.kg).magnitude

# Years to seconds
YR_TO_S = ureg.Quantity(1, ureg.year).to(ureg.second).magnitude

Expand Down
9 changes: 6 additions & 3 deletions bluemira/codes/process/_solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

import numpy as np

from bluemira.base.constants import raw_uc
from bluemira.base.look_and_feel import bluemira_warn
from bluemira.base.parameter_frame import ParameterFrame
from bluemira.codes.error import CodesError
Expand Down Expand Up @@ -223,7 +224,7 @@
Returns
-------
tref:
The temperature in eV.
The temperature in keV.
l_ref:
The loss function value $L_z(n_e, T_e)$ in W.m3.
z_ref:
Expand All @@ -234,8 +235,10 @@
t_ref = filter(lambda lz: lz.content == "Te[eV]", lz_ref)
lz_ref = filter(lambda lz: f"{confinement_time_ms:.1f}" in lz.content, lz_ref)
z_av_ref = filter(lambda z: f"{confinement_time_ms:.1f}" in z.content, z_ref)
return tuple(
np.array(next(ref).data, dtype=float) for ref in (t_ref, lz_ref, z_av_ref)
return (

Check warning on line 238 in bluemira/codes/process/_solver.py

View check run for this annotation

Codecov / codecov/patch

bluemira/codes/process/_solver.py#L238

Added line #L238 was not covered by tests
raw_uc(np.array(next(t_ref).data, dtype=float), "eV", "keV"),
np.array(next(lz_ref).data, dtype=float),
np.array(next(z_av_ref).data, dtype=float),
)

def get_species_fraction(self, impurity: str) -> float:
Expand Down
13 changes: 7 additions & 6 deletions bluemira/fuel_cycle/cycle.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import numpy as np
from scipy.interpolate import interp1d

from bluemira.base.constants import N_AVOGADRO, T_LAMBDA, T_MOLAR_MASS, YR_TO_S, raw_uc
from bluemira.base.constants import N_AVOGADRO, T_LAMBDA, T_MOLAR_MASS, raw_uc

Check warning on line 23 in bluemira/fuel_cycle/cycle.py

View check run for this annotation

Codecov / codecov/patch

bluemira/fuel_cycle/cycle.py#L23

Added line #L23 was not covered by tests
from bluemira.base.look_and_feel import bluemira_print
from bluemira.fuel_cycle.blocks import FuelCycleComponent, FuelCycleFlow
from bluemira.fuel_cycle.tools import (
Expand Down Expand Up @@ -186,10 +186,11 @@
m_T = m_T_0 * np.ones(len(self.DEMO_t))
for i in range(1, len(self.DEMO_t)):
dt = self.DEMO_t[i] - self.DEMO_t[i - 1]
t_bred = TBR * self.brate[i] * (YR_TO_S * dt)
t_bred += self.prate[i] * (YR_TO_S * dt)
t_burnt = self.brate[i] * (YR_TO_S * dt)
t_DD = self.prate[i] * (YR_TO_S * dt)
dts = raw_uc(dt, "yr", "s")
t_bred = TBR * self.brate[i] * dts
t_bred += self.prate[i] * dts
t_burnt = self.brate[i] * dts
t_DD = self.prate[i] * dts

Check warning on line 193 in bluemira/fuel_cycle/cycle.py

View check run for this annotation

Codecov / codecov/patch

bluemira/fuel_cycle/cycle.py#L189-L193

Added lines #L189 - L193 were not covered by tests
m_T[i] = (m_T[i - 1]) * np.exp(-T_LAMBDA * dt) - t_burnt + t_bred + t_DD
return m_T

Expand Down Expand Up @@ -350,7 +351,7 @@

m_T_out = self.plasma(self.params.eta_iv, self.params.I_miv, flows=flows)
# Resolution - Not used everywhere for speed
n_ts = int(round((YR_TO_S * self.DEMO_t[-1]) / self.timestep))
n_ts = int(round(raw_uc(self.DEMO_t[-1], "yr", "s") / self.timestep))

Check warning on line 354 in bluemira/fuel_cycle/cycle.py

View check run for this annotation

Codecov / codecov/patch

bluemira/fuel_cycle/cycle.py#L354

Added line #L354 was not covered by tests
self.t, m_pellet_in = discretise_1d(self.DEMO_t, self.m_T_in, n_ts)

# Flow out of the vacuum vessel
Expand Down
26 changes: 16 additions & 10 deletions bluemira/fuel_cycle/lifecycle.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import numpy as np
from matplotlib.lines import Line2D

from bluemira.base.constants import S_TO_YR, YR_TO_S, raw_uc
from bluemira.base.constants import raw_uc

Check warning on line 20 in bluemira/fuel_cycle/lifecycle.py

View check run for this annotation

Codecov / codecov/patch

bluemira/fuel_cycle/lifecycle.py#L20

Added line #L20 was not covered by tests
from bluemira.base.look_and_feel import bluemira_print, bluemira_warn
from bluemira.fuel_cycle.timeline import Timeline
from bluemira.utilities.tools import abs_rel_difference, is_num, json_writer
Expand Down Expand Up @@ -125,8 +125,8 @@

self.n_blk_replace = 1 # HLR
self.n_div_replace = ndivch_in1blk + ndivch_in2blk
m_short = self.maintenance_s * S_TO_YR
m_long = self.maintenance_l * S_TO_YR
m_short = raw_uc(self.maintenance_s, "s", "yr")
m_long = raw_uc(self.maintenance_l, "s", "yr")

Check warning on line 129 in bluemira/fuel_cycle/lifecycle.py

View check run for this annotation

Codecov / codecov/patch

bluemira/fuel_cycle/lifecycle.py#L128-L129

Added lines #L128 - L129 were not covered by tests
phases = []
for i in range(ndivch_in1blk):
p_str = "Phase P1." + str(i + 1)
Expand Down Expand Up @@ -156,10 +156,12 @@
fpy += phases[i][0]
self.fpy = fpy
# Irreplaceable components life checks
self.t_on_total = self.fpy * YR_TO_S # [s] total fusion time
self.t_on_total = raw_uc(self.fpy, "yr", "s") # [s] total fusion time

Check warning on line 159 in bluemira/fuel_cycle/lifecycle.py

View check run for this annotation

Codecov / codecov/patch

bluemira/fuel_cycle/lifecycle.py#L159

Added line #L159 was not covered by tests
tf_ins_life_dose = tf_ins_nflux * self.t_on_total / self.params.tf_fluence
if tf_ins_life_dose > 1:
self.tf_lifeend = round(self.params.tf_fluence / tf_ins_nflux / YR_TO_S, 2)
self.tf_lifeend = round(

Check warning on line 162 in bluemira/fuel_cycle/lifecycle.py

View check run for this annotation

Codecov / codecov/patch

bluemira/fuel_cycle/lifecycle.py#L162

Added line #L162 was not covered by tests
raw_uc(self.params.tf_fluence / tf_ins_nflux, "s", "yr"), 2
)
tflifeperc = round(100 * self.tf_lifeend / self.fpy, 1)
bluemira_warn(
f"TF coil insulation fried after {self.tf_lifeend:.2f} full-power years"
Expand All @@ -174,7 +176,7 @@
f" years, or {vvlifeperc:.2f} % of neutron budget."
)
# TODO: treat output parameter
self.n_cycles = self.fpy * YR_TO_S / self.t_flattop
self.n_cycles = raw_uc(self.fpy, "yr", "s") / self.t_flattop

Check warning on line 179 in bluemira/fuel_cycle/lifecycle.py

View check run for this annotation

Codecov / codecov/patch

bluemira/fuel_cycle/lifecycle.py#L179

Added line #L179 was not covered by tests

def set_availabilities(self, load_factor: float):
"""
Expand Down Expand Up @@ -214,7 +216,7 @@
Calculate the number of pulses per phase.
"""
self.n_pulse_p = [
int(YR_TO_S * phases[i][0] // self.t_flattop)
int(raw_uc(phases[i][0], "yr", "s") // self.t_flattop)
for i in range(len(phases))
if phases[i][1].startswith("Phase P")
]
Expand Down Expand Up @@ -276,12 +278,14 @@
results that violate the tolerances.
"""
life = self.fpy / self.params.A_global
actual_life = S_TO_YR * (
actual_life = raw_uc(

Check warning on line 281 in bluemira/fuel_cycle/lifecycle.py

View check run for this annotation

Codecov / codecov/patch

bluemira/fuel_cycle/lifecycle.py#L281

Added line #L281 was not covered by tests
self.t_on_total
+ self.total_ramptime
+ self.t_interdown
+ self.total_planned_maintenance
+ self.t_unplanned_m
+ self.t_unplanned_m,
"s",
"yr",
)
actual_lf = self.fpy / actual_life
delt = abs_rel_difference(actual_life, life)
Expand Down Expand Up @@ -318,7 +322,9 @@
self.inputs,
) # Phoenix

if self.params.A_global > self.fpy / (self.fpy + S_TO_YR * self.min_downtime):
if self.params.A_global > self.fpy / (

Check warning on line 325 in bluemira/fuel_cycle/lifecycle.py

View check run for this annotation

Codecov / codecov/patch

bluemira/fuel_cycle/lifecycle.py#L325

Added line #L325 was not covered by tests
self.fpy + raw_uc(self.min_downtime, "s", "yr")
):
bluemira_warn("FuelCycle::Lifecyle: Input availability is unachievable.")
# Re-assign A
self.params.A_global = actual_lf
Expand Down
9 changes: 4 additions & 5 deletions bluemira/fuel_cycle/timeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import matplotlib.pyplot as plt
import numpy as np

from bluemira.base.constants import S_TO_YR, YR_TO_S
from bluemira.base.constants import raw_uc

Check warning on line 16 in bluemira/fuel_cycle/timeline.py

View check run for this annotation

Codecov / codecov/patch

bluemira/fuel_cycle/timeline.py#L16

Added line #L16 was not covered by tests
from bluemira.fuel_cycle.timeline_tools import (
LogNormalAvailabilityStrategy,
OperationalAvailabilityStrategy,
Expand Down Expand Up @@ -354,7 +354,7 @@
)
j += 1
elif "Phase M" in name:
p = MaintenancePhase(name, duration * YR_TO_S, t_start=t_start)
p = MaintenancePhase(name, raw_uc(duration, "yr", "s"), t_start=t_start)

Check warning on line 357 in bluemira/fuel_cycle/timeline.py

View check run for this annotation

Codecov / codecov/patch

bluemira/fuel_cycle/timeline.py#L357

Added line #L357 was not covered by tests
phases.append(p)
self.phases = phases
self.build_arrays(phases)
Expand Down Expand Up @@ -385,9 +385,8 @@
self.ft = np.zeros(len(self.t))
for i in fuse_indices[1::2]:
self.ft[i] = self.t[i] - self.t[i - 1]
self.ft = np.cumsum(self.ft)
self.ft *= S_TO_YR
self.t *= S_TO_YR
self.ft = raw_uc(np.cumsum(self.ft), "s", "yr")
self.t = raw_uc(self.t, "s", "yr")

Check warning on line 389 in bluemira/fuel_cycle/timeline.py

View check run for this annotation

Codecov / codecov/patch

bluemira/fuel_cycle/timeline.py#L388-L389

Added lines #L388 - L389 were not covered by tests
self.plant_life = self.t[-1] # total plant lifetime [calendar]

def to_dict(self) -> Dict[str, Union[np.ndarray, int]]:
Expand Down
14 changes: 6 additions & 8 deletions bluemira/fuel_cycle/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,8 +263,8 @@
The time vector
m_t_flow:
The mass flow vector
t_delay:
The delay duration [s]
tt_delay:
The delay duration [yr]

Returns
-------
Expand Down Expand Up @@ -575,7 +575,7 @@
if dt == 0:
return m_flow, inventory, sum_in, decayed

m_in = m_flow * YR_TO_S # kg/yr
m_in = m_flow * YR_TO_S # converts kg/s to kg/yr

Check warning on line 578 in bluemira/fuel_cycle/tools.py

View check run for this annotation

Codecov / codecov/patch

bluemira/fuel_cycle/tools.py#L578

Added line #L578 was not covered by tests
dts = dt * YR_TO_S
mass_in = m_flow * dts
sum_in += mass_in
Expand Down Expand Up @@ -731,13 +731,12 @@
decayed:
Accountancy parameter to calculate the total value of decayed T in a sink
"""
years = 365 * 24 * 3600
dt = t_out - t_in
if dt == 0:
return m_flow, inventory, sum_in, decayed

m_in = m_flow * years # kg/yr
dts = dt * years
m_in = m_flow * YR_TO_S # converts kg/s to kg/yr
dts = dt * YR_TO_S

Check warning on line 739 in bluemira/fuel_cycle/tools.py

View check run for this annotation

Codecov / codecov/patch

bluemira/fuel_cycle/tools.py#L738-L739

Added lines #L738 - L739 were not covered by tests
mass_in = m_flow * dts
sum_in += mass_in
j_inv0 = inventory
Expand Down Expand Up @@ -825,13 +824,12 @@
not accounted for in this function. We have to add decay in the sink and
ensure this is handled when calculation the absorbtion and out-flow.
"""
years = 365 * 24 * 3600
dt = t_out - t_in
if dt == 0:
# Nothing can happen if time is zero
return m_flow, inventory, sum_in, decayed

dts = dt * years
dts = dt * YR_TO_S

Check warning on line 832 in bluemira/fuel_cycle/tools.py

View check run for this annotation

Codecov / codecov/patch

bluemira/fuel_cycle/tools.py#L832

Added line #L832 was not covered by tests
mass_in = m_flow * dts
sum_in += mass_in

Expand Down
25 changes: 18 additions & 7 deletions bluemira/plasma_physics/collisions.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@

from bluemira.base.constants import (
ELECTRON_MASS,
ELEMENTARY_CHARGE,
EPS_0,
EV_TO_J,
H_PLANCK,
K_BOLTZMANN,
PROTON_MASS,
raw_uc,
)


Expand All @@ -35,7 +35,9 @@
-------
Debye length [m]
"""
return np.sqrt(EPS_0 * K_BOLTZMANN * temperature / (EV_TO_J**2 * density))
return np.sqrt(
EPS_0 * raw_uc(temperature, "K", "J") / (ELEMENTARY_CHARGE**2 * density)
)


def reduced_mass(mass_1: float, mass_2: float) -> float:
Expand Down Expand Up @@ -74,7 +76,10 @@
The sqrt(2) term is for a 3-dimensional system and the most probable velocity in
the particle velocity distribution.
"""
return np.sqrt(2) * np.sqrt(K_BOLTZMANN * temperature / mass)
return np.sqrt(2) * np.sqrt(
raw_uc(temperature, "K", "J") # = Joule = kg*m^2/s^2
/ mass
) # sqrt(m^2/s^2) = m/s


def de_broglie_length(velocity: float, mu_12: float) -> float:
Expand Down Expand Up @@ -110,7 +115,7 @@
-------
Perpendicular impact parameter [m]
"""
return EV_TO_J**2 / (4 * np.pi * EPS_0 * mu_12 * velocity**2)
return ELEMENTARY_CHARGE**2 / (4 * np.pi * EPS_0 * mu_12 * velocity**2)


def coulomb_logarithm(temperature: float, density: float) -> float:
Expand Down Expand Up @@ -146,7 +151,8 @@
Z_eff:
Effective charge [a.m.u.]
T_e:
Electron temperature on axis [eV]
Electron temperature on axis [keV]
The equation takes in temperature as [eV], so an in-line conversion is used here.
ln_lambda:
Coulomb logarithm value

Expand All @@ -160,4 +166,9 @@

\t:math:`\\sigma = 1.92e4 (2-Z_{eff}^{-1/3}) \\dfrac{T_{e}^{3/2}}{Z_{eff}ln\\Lambda}`
"""
return 1.92e4 * (2 - Z_eff ** (-1 / 3)) * T_e**1.5 / (Z_eff * ln_lambda)
return (

Check warning on line 169 in bluemira/plasma_physics/collisions.py

View check run for this annotation

Codecov / codecov/patch

bluemira/plasma_physics/collisions.py#L169

Added line #L169 was not covered by tests
1.92e4
* (2 - Z_eff ** (-1 / 3))
* raw_uc(T_e, "keV", "eV") ** 1.5
/ (Z_eff * ln_lambda)
)
Loading