Utility Packages
Pipe Geometry
A pipe geometry interface used by different calculations, defined through
EffectivePipe.
- class EffectivePipe(length, heated_perimeter, wet_perimeter, area, heated_parts=(), width=None, depth=None)[source]
A simple constant-cross-sectional pipe’s parameters, where the parameters are “effectively” fitting to a circular pipe, and there is a distinction between “wet” (for fluid flow) and “heated” (for heat transfer) geometries.
Essentially, for both perimeters, \(P_\text{heated}, P_\text{wet}\), the appropriate diameter is given using the flow area \(A\):
\[D = 4A / P\]- Parameters:
length (Meter) – Pipe Length
heated_perimeter (Meter) – The cross-sectional heated perimeter
wet_perimeter (Meter) – The cross-sectional wet (hydraulic) perimeter
area (Meter2) – Flow cross-section
heated_parts (tuple[Meter, ...] or None) – For a cross-section of the pipe, there may be several distinct regions which contribute flux (e.g. in MTR there are 2 in most cases). This is also the default case.
width (Meter | None) – Channel width. When this is None, that means one should not use this attribute. This property is currently only used in the Sudo & Kaminaga CHF for one of its terms. See that usage in
Sudo_Kaminaga_CHF. For rectangular channels this is the longer side of the channel, which is commonly also the heated one. In annular channels, this is the hydraulic diameter of the channel. The reference for why this is so is by[1].depth (Meter | None) – Channel depth. This property is in use in the Elenbaas correlation for natural convection between parallel plates stream.physical_models.heat_transfer_coeffcient.natural_convection.Elenbaas_h_spl For rectangular channels this is the shorter side of the channel cross-section.
References
- classmethod circular(length, diameter)[source]
Create an EffectivePipe geometry for a channel with a circular cross-section, which is fully heated.
- Parameters:
length (Meter) – Length along the flow.
diameter (Meter) – Diameter of the pipe.
- Return type:
- classmethod rectangular(length, edge1, edge2, heated_edge, one_sided=None)[source]
Create an EffectivePipe geometry for a channel with a rectangular cross-section, which is heated on two opposite sides.
- Parameters:
length (Meter) – Length along the flow.
edge1 (Meter) – Edges of the rectangular cross-section.
edge2 (Meter) – Edges of the rectangular cross-section.
heated_edge (Meter) – The heated section length which may differ from the edge itself.
one_sided (bool) – A flag for whether heating happens on two opposite edges (False) or on just one edge (True).
- Return type:
- area: float | ndarray
- depth: float | ndarray | None
- heated_diameter: float | ndarray
- heated_parts: tuple[float | ndarray, ...]
- heated_perimeter: float | ndarray
- hydraulic_diameter: float | ndarray
- length: float | ndarray
- wet_perimeter: float | ndarray
- width: float | ndarray | None
Substances
This package contains several substances (read: correlations or effective state equations).
For example:
>>> from numpy import array as ar
>>> light_water.density(T=ar([20, 100]))
array([997.95471288, 959.13959928])
References
A. Crabtree and M. Siman-Tov, “Thermophysical Properties of Saturated Light and Heavy Water for Advanced Neutron Source Applications”, ORNL/TM-12322, 1993.
- class Liquid(density, vapor_density, specific_heat, viscosity, sat_temperature, surface_tension, latent_heat, conductivity, thermal_expansion)[source]
Bulk properties of a liquid.
- Parameters:
density (KgPerM3) – Liquid density
specific_heat (JPerKgK) – Liquid specific heat
viscosity (PaS) – Liquid viscosity
conductivity (WPerMK) – Liquid thermal conductivity
vapor_density (KgPerM3) – Vapor density
sat_temperature (Celsius) – Saturation (Boiling) temperature
surface_tension (NPerM) – Liquid surface tension
latent_heat (JPerKg) – Liquid-Vapor transition specific latent heat
thermal_expansion (PerC) – Thermal volume expansion coefficient
- conductivity: float | ndarray
- density: float | ndarray
- latent_heat: float | ndarray
- sat_temperature: float | ndarray
- specific_heat: float | ndarray
- surface_tension: float | ndarray
- thermal_expansion: float | ndarray
- vapor_density: float | ndarray
- viscosity: float | ndarray
- class LiquidFuncs(density, vapor_density, specific_heat, viscosity, sat_temperature, surface_tension, latent_heat, conductivity, thermal_expansion)[source]
A dataclass containing functions of temperature and pressure depicting several properties of a liquid
- Parameters:
density (Callable[[Celsius], KgPerM3]) – Liquid density
specific_heat (Callable[[Celsius], JPerKgK]) – Liquid specific heat
viscosity (Callable[[Celsius], PaS]) – Liquid viscosity
conductivity (Callable[[Celsius], WPerMK]) – Liquid thermal conductivity
vapor_density (Callable[[Celsius], KgPerM3]) – Vapor density
sat_temperature (Callable[[Pascal], Celsius]) – Saturation (Boiling) temperature. Note the pressure dependence
surface_tension (Callable[[Celsius], NPerM]) – Liquid surface tension
latent_heat (Callable[[Celsius], JPerKg]) – Liquid-Vapor transition specific latent heat
thermal_expansion (Callable[[Celsius], PerC]) – Thermal volume expansion coefficient
- to_properties(T, p=101325.0)[source]
Apply T, p once to receive every property of the liquid at the given phase space point.
- Parameters:
T (Celsius) – Temperature
p (Pascal) – Pressure. Specifically used only for the saturation temperature, so it is optional and 1 Atmosphere (101,325 Pa) by default.
- Returns:
liquid – A Liquid Dataclass containing the aforementioned properties.
- Return type:
- conductivity: Callable[[float | ndarray], float | ndarray]
- density: Callable[[float | ndarray], float | ndarray]
- latent_heat: Callable[[float | ndarray], float | ndarray]
- sat_temperature: Callable[[float | ndarray], float | ndarray]
- specific_heat: Callable[[float | ndarray], float | ndarray]
- surface_tension: Callable[[float | ndarray], float | ndarray]
- thermal_expansion: Callable[[float | ndarray], float | ndarray]
- vapor_density: Callable[[float | ndarray], float | ndarray]
- viscosity: Callable[[float | ndarray], float | ndarray]
Liquid Properties and Interface
Two dataclasses are defined, which serve as an interface to the rest of the code whenever liquid properties such as coolant density, latent heat etc.
These classes are LiquidFuncs, which is a template for adding such properties as functions of the
\((T, p)\), phase space. Applying these functions for such a phase space point yields a Liquid object,
containing the same properties, actualized.
- class Liquid(density, vapor_density, specific_heat, viscosity, sat_temperature, surface_tension, latent_heat, conductivity, thermal_expansion)[source]
Bulk properties of a liquid.
- Parameters:
density (KgPerM3) – Liquid density
specific_heat (JPerKgK) – Liquid specific heat
viscosity (PaS) – Liquid viscosity
conductivity (WPerMK) – Liquid thermal conductivity
vapor_density (KgPerM3) – Vapor density
sat_temperature (Celsius) – Saturation (Boiling) temperature
surface_tension (NPerM) – Liquid surface tension
latent_heat (JPerKg) – Liquid-Vapor transition specific latent heat
thermal_expansion (PerC) – Thermal volume expansion coefficient
- class LiquidFuncs(density, vapor_density, specific_heat, viscosity, sat_temperature, surface_tension, latent_heat, conductivity, thermal_expansion)[source]
A dataclass containing functions of temperature and pressure depicting several properties of a liquid
- Parameters:
density (Callable[[Celsius], KgPerM3]) – Liquid density
specific_heat (Callable[[Celsius], JPerKgK]) – Liquid specific heat
viscosity (Callable[[Celsius], PaS]) – Liquid viscosity
conductivity (Callable[[Celsius], WPerMK]) – Liquid thermal conductivity
vapor_density (Callable[[Celsius], KgPerM3]) – Vapor density
sat_temperature (Callable[[Pascal], Celsius]) – Saturation (Boiling) temperature. Note the pressure dependence
surface_tension (Callable[[Celsius], NPerM]) – Liquid surface tension
latent_heat (Callable[[Celsius], JPerKg]) – Liquid-Vapor transition specific latent heat
thermal_expansion (Callable[[Celsius], PerC]) – Thermal volume expansion coefficient
- to_properties(T, p=101325.0)[source]
Apply T, p once to receive every property of the liquid at the given phase space point.
- Parameters:
T (Celsius) – Temperature
p (Pascal) – Pressure. Specifically used only for the saturation temperature, so it is optional and 1 Atmosphere (101,325 Pa) by default.
- Returns:
liquid – A Liquid Dataclass containing the aforementioned properties.
- Return type:
Heavy Water
\(\text{D}_2\text{O}\) constants and correlations,
as given in[2]. The user facing function is of type
LiquidFuncs
>>> type(heavy_water)
<class 'stream.substances.liquid.LiquidFuncs'>
Light Water
\(\text{H}_2\text{O}\) constants and correlations, as given in[2].
The user facing function is of type LiquidFuncs
>>> type(light_water)
<class 'stream.substances.liquid.LiquidFuncs'>
Mocks
Mock Substances, whose properties are mostly just 1’s
- constant_LiquidFuncs(fluid, T, p)[source]
Create a constant-valued
LiquidFuncsbased on a given instance at a (T, p) phase-space point.T, p are taken as at_least1d to allow compatibility with vector operations.
- Parameters:
fluid (LiquidFuncs) – Model fluid to be evaluated.
T (Celsius) – Temperature.
p (Pascal) – Pressure.
- Returns:
const_fluid – A LiquidFuncs which always returns the same value for each parameter.
- Return type:
Examples
>>> from stream.substances import light_water >>> clf = constant_LiquidFuncs(light_water, T=20., p=1e5) >>> bool(clf.density(20.) == clf.density(80.) == light_water.density(20.)) True >>> clf.density(np.zeros(4)) / clf.density(20) array([1., 1., 1., 1.])
Units
Physical, abstract and data units for type hinting.
Naming convention
Whenever a unit is on its own, its full name is used. A number following a unit denotes its power (e.g. Meter3 is cubic meters). The word “Per” separates the unit into [numerator]Per[denominator].
Note
Physical Units use mostly the SI units.
Kelvin and Celsius are used interchangeably whenever they appear at the denominator.
Utilities
Here lie some unspoken heroes…
As well as some helper functions regarding mixing, conversions, flux shapes and more.
- concat(*arrays, **kwargs)[source]
np.concatenate is cumbersome, this function makes it nicer to use >>> concat((False, ), (False, False)) array([False, False, False]) >>> concat((False,), (False, False), np.zeros(3, dtype=bool)) array([False, False, False, False, False, False])
- Parameters:
arrays (Sequence)
- Return type:
ndarray
- cosine_shape(x, ppf=1.5707963267948966, *, xmax=None)[source]
Creates a normalized cosine profile for cells whose boundaries are x, assuming its maximum is achieved at \(\ell/2 = (x[-1] + x[0])/2\) unless stated otherwise.
- Parameters:
x (Array1D) – Linear array, 1D spatial ticks of cells boundaries
ppf (float) – Power Peaking Factor. The default value is \(\pi/2\).
xmax (float) – The point where the cosine shape is at its theoretical maximum. Defaults to the midpoint between x[0] and x[-1].
- Returns:
phi – a normalized array whose profile is cosine which is zero at the outer boundaries, and is normalized to unity.
- Return type:
Array1D
Notes
Here is the derivation. The flux profile is assumed to take the following form:
\[\phi = \cos\left(\frac{\pi (x - \ell/2)}{L}\right)\]Where \(L\) is the extrapolated length (half of the period), which is set by the
PPF:\[\text{PPF} \equiv \frac{\max{\phi}}{\bar{\phi}}\]That is
\[1/\text{PPF} = \bar{\phi} = \frac{1}{\ell}\int^{\ell/2}_{-\ell/2}dx\cos\left(\frac{\pi (x-\ell/2)}{L}\right) = \frac{2L}{\ell\pi}\sin\left(\frac{\ell\pi}{2L}\right)\]Then, \(L\) is found by solving for \(h = \ell\pi/2L \Rightarrow h/\text{PPF} = \sin(h)\).
Finally, the cosine shape is integrated for each cell:
\[\int^{x_{i+1}}_{x_i} dx' \cos\left(\frac{\pi (x' - \ell/2)}{L}\right) = \frac{L}{\pi}\left[\sin\left(\frac{\pi (x_{i+1} - \ell/2)}{L}\right) - \sin\left(\frac{\pi (x_i - \ell/2)}{L}\right)\right]\]
- cosine_shape_by_zero_endpoints(xi, xe, x)[source]
A cosine shape which is 0 at the extrapolation values, and integrates to 1 over the unextrapolated values.
- Parameters:
xi (Low extrapolation boundary.)
xe (High extrapolation boundary.)
x (Boundaries over which to bin the cosine shape)
- Return type:
ndarray
Notes
The general cosine shape is \(b\cos\left(a(x-x_{max})\right)\).
\(a\) is determined from the extrapolation, where the cosine nullifies at \(-\frac{\pi}{2},\frac{\pi}{2}\). This means that at xi and xe we want \(a(xe-x_{max})=\frac{\pi}{2}\) and \(a(xi-x_{max})=-\frac{\pi}{2}\). Since the max point of a cosine shape is exactly midway between those points, \(x_{max}=\frac{xi+xe}{2}\), which means that if we set \(ll=xe-xi\) we can write \(a=\frac{\pi}{ll}\).
\(b\) is determined from the normalization condition. We desire that the integral inside the boundaries in the x vector be strictly 1. If we mark the external boundaries as \(x_0\) and \(x_1\), we get:
\[1 = b\int_{x_0}^{x_1}{\cos(a(x-x_{max}))dx} = \frac{b}{a}\left[\sin(a(x_1-x_{max}))-\sin(a(x_0-x_{max}))\right]\]and thus \(b=a\left[\sin(a(x_1-x_{max}))-\sin(a(x_0-x_{max}))\right]\).
Now that we know what the analytical shape is, we can do the discretization. We integrate over each cell in the boundaries of x, which have the same shape as the equation above, but for a different integration range:
\[v_i = b \int_{x_i}^{x_{i+1}}{\cos(a(x-x_{max}))dx} = \frac{b}{a}\left[\sin(a(x_{i+1}-x_{max}))-\sin(a(x_i-x_{max}))\right]\]This guarantees that \(\sum_{i}{v_i}=1\).
See also
cosine_shapeA similar function based on knowing the PPF rather than the extrapolation points.
- Returns:
A discretized cell integration of a cosine function which is 0 at xi and xe, and integrates to 1 over [xi_in, xe_in]. The vector is thus normalized to have a sum of 1.
- Return type:
Array1D
- Parameters:
xi (float)
xe (float)
x (ndarray)
- dataclass_map(dc, f)[source]
If a function should work in the same manner on all fields of a dataclass, create that function and return it.
- Parameters:
dc (dataclass)
f (Callable)
- Returns:
A function which operates f on all fields of dc instances, returning
a new dc instance.
- Return type:
_DataclassMap
- directed(a, val)[source]
- Parameters:
a (np.ndarray) – array to be traversed
val – determining value for traversal. If negative, the array is flipped
- Returns:
a* – A view of ‘a’ which is either flipped or not
- Return type:
np.ndarray
- directed_Tin(Tin, Tin_minus, mdot)[source]
Computes the inlet temperature for a point component based on flow direction.
- Parameters:
Tin (Celsius or None) – Positive (Negative) flow associated inlet temperature
Tin_minus (Celsius or None) – Positive (Negative) flow associated inlet temperature
mdot (KgPerS) – Fluid mass flow rate
- Returns:
Tin’ – Inlet temperature
- Return type:
Celsius
Notes
For the sake of removing stiffness, for absolute flow values under
MDOT_INTER_THRESHOLD, a linear interpolation betweenTinandTin_minus. This value may be changed by overridingstream.utilities.MDOT_INTER_THRESHOLD.Examples
>>> directed_Tin(1, 2, 3) 1.0 >>> directed_Tin(1, 2, -3) 2.0 >>> directed_Tin(None, 2, 3) 2 >>> directed_Tin(1, None, 3) 1 >>> directed_Tin(1, 2, 0) 1.5 >>> directed_Tin(np.array([1., 2.]), np.array([3., 4.]), 0.) array([2., 3.])
:raises ValueError : If both
TinandTin_minusare None.:
- factor(f, by=1.0, add=0.0)[source]
A functor used to lineraly transform a given function’s output by some values.
- Parameters:
f (Callable) – The decorated function
by (float) – The multiplicative value
add (float) – The additve value
- Returns:
f’ – A new function
- Return type:
Callable
Examples
>>> factor(np.ones, 2)(3) array([2., 2., 2.])
- flatten_values(d, dtype=<class 'numpy.float64'>)[source]
Take a dictionary of values or sequences of values and return a long array with all the values in order, flattened out.
- Parameters:
d (dict[Any, float | Sequence[float]]) – Dictionary to flatten down.
dtype – NumPy dtype value.
- Returns:
An array of just the values from the dictionary, unless there is only one element, in which case it is returned.
- Return type:
Value
- just(val)[source]
- Parameters:
val (Any) – A value which the returned function just returns
- Returns:
f – A function which returns
valfor any input.- Return type:
Callable
Examples
>>> a = just(5) >>> a(3, b="yes") 5
- lin_interp(x1, x2, y1, y2, x)[source]
Linearly interpolate between two points: (x1, y1) and (x2, y2). The assumption being that \(x_1 \neq x_2\).
Let a line be drawn between the two points. Thus:
\(y_1 = a x_1 + b, y_2 = a x_2 + b \Rightarrow a=(y_2-y_1)/(x_2-x_1)\) and \(b = y_2 - a x_2 = y_1 - a x_1\)
Then:
\[y = \frac{(y_2 - y_1)}{(x_2 - x_1)}(x - x_2) + y_2\]- Parameters:
x (Value) – desired position for the interpolation
x1 (Value) – known points, assuming \(x \in [x_1, x_2]\)
x2 (Value) – known points, assuming \(x \in [x_1, x_2]\)
y1 (Value) – known function values for x1, x2
y2 (Value) – known function values for x1, x2
- Return type:
The interpolated value, y
Examples
>>> lin_interp(x1=1, x2=3, y1=1, y2=3, x=2) 2.0 >>> lin_interp(x1=0, x2=4, y1=0, y2=2, x=3) 1.5
- mutually_exclusive(*arrays)[source]
Checks if the arrays provided are mutually exclusive (don’t contain the same elements).
- Parameters:
arrays (Sequence)
- Return type:
bool
- offset(s, move_by)[source]
- offset(s, move_by)
- offset(s, move_by)
- offset(s, move_by)
- offset(s, move_by)
Move a variable representing a
placeby some integer value.- Parameters:
s (one of (slice, int, np.array) or a dict whose values are of those types) – Variable to move by an offset.
move_by (int) – Offset value.
- Returns:
s’ – The returned type matches
s.- Return type:
one of (slice, int, np.array) or a dict whose values are of those types
- strictly_monotonous(*arrays)[source]
Concatenate and sort arrays for strictly monotonously rising time
Examples
>>> strictly_monotonous([1, 2, 3], [1.5, 2, 2.5]) array([1. , 1.5, 2. , 2.5, 3. ])
- Parameters:
arrays (Sequence)
- Return type:
ndarray
- summed(it, initial=None)[source]
Sum items of an iterable by their
__add__()functionThis differs in behavior from the builtin
sumin that sum requires an initial value, which is 0 by default, whereassummeddoes not.- Parameters:
it (Iterable[T]) – The items to be summed
initial – Value to start the sum from.
- Returns:
sum – The summed item
- Return type:
T
Examples
>>> summed(("Hello, ", "it's ", "nice ", "to ", "meet ", "you!")) "Hello, it's nice to meet you!" >>> summed(([1, 2], [3, 4])) [1, 2, 3, 4]
- to_array(d, dtype=<class 'numpy.float64'>)[source]
Turn dictionary values into numpy array of type dtype.
- Parameters:
d (dict[Any, float]) – Dictionary to turn into a 1D array.
dtype – NumPy dtype value.
- Returns:
An array of just the values from the dictionary.
- Return type:
Array1D