bluemira.fuel_cycle.tools ========================= .. py:module:: bluemira.fuel_cycle.tools .. autoapi-nested-parse:: Fuel cycle utility objects, including sink algorithms Classes ------- .. autoapisummary:: bluemira.fuel_cycle.tools.NoiseModeType bluemira.fuel_cycle.tools.FitMethod Functions --------- .. autoapisummary:: bluemira.fuel_cycle.tools.find_noisy_locals bluemira.fuel_cycle.tools.discretise_1d bluemira.fuel_cycle.tools.convert_flux_to_flow bluemira.fuel_cycle.tools.piecewise_linear_threshold bluemira.fuel_cycle.tools.piecewise_sqrt_threshold bluemira.fuel_cycle.tools.fit_sink_data bluemira.fuel_cycle.tools.delay_decay bluemira.fuel_cycle.tools.fountain bluemira.fuel_cycle.tools._speed_recycle bluemira.fuel_cycle.tools.find_max_load_factor bluemira.fuel_cycle.tools.legal_limit bluemira.fuel_cycle.tools._dec_I_mdot bluemira.fuel_cycle.tools._timestep_decay bluemira.fuel_cycle.tools._find_t15 bluemira.fuel_cycle.tools._fountain_linear_sink bluemira.fuel_cycle.tools._linear_thresh_sink bluemira.fuel_cycle.tools._sqrt_thresh_sink bluemira.fuel_cycle.tools.linear_bathtub bluemira.fuel_cycle.tools.sqrt_bathtub bluemira.fuel_cycle.tools.fountain_bathtub Module Contents --------------- .. py:class:: NoiseModeType(*args, **kwds) Bases: :py:obj:`enum.Enum` .. autoapi-inheritance-diagram:: bluemira.fuel_cycle.tools.NoiseModeType :parts: 1 :private-bases: Enumeration of noise search modes. .. py:attribute:: MIN .. py:attribute:: MAX .. py:method:: _missing_(value: str | NoiseModeType) -> NoiseModeType :classmethod: .. py:function:: find_noisy_locals(x: numpy.ndarray, x_bins: int = 50, mode: str = 'min') -> tuple[numpy.ndarray, numpy.ndarray] Find local minima or maxima in a noisy signal. :param x: The noise data to search :param x_bins: The number of bins to search with :param mode: The search mode ['min', 'max'] :returns: * *local_mid_x* -- The arguments of the local minima or maxima * *local_m* -- The local minima or maxima .. py:function:: discretise_1d(x: numpy.ndarray, y: numpy.ndarray, n: int, method: str = 'linear') -> tuple[numpy.ndarray, numpy.ndarray] Discretise x and y for a given number of points. :param x: The x data :param y: The y data :param n: The number of discretisation points :param method: The interpolation method :returns: * *x_1d* -- The discretised x data * *y_1d* -- The discretised y data .. py:function:: convert_flux_to_flow(flux: float, area: float) -> float Convert an atomic flux to a flow-rate. :param flux: The atomic flux [T/m^2/s] :param area: The surface area of the flux [m^2] :rtype: The flow-rate [kg/s] .. py:function:: piecewise_linear_threshold(x: numpy.ndarray, x0: float, y0: float, m1: float, m2: float) -> numpy.ndarray Piecewise linear model with initial linear slope, followed by threshold. :param x: The vector of x values to calculate the function for :param x0: The x coordinate of the kink point :param y0: The y coordinate of the kink point :param m1: The slope of the first curve :param m2: The threshold value of the function :rtype: The vector of fitted values .. py:function:: piecewise_sqrt_threshold(x: numpy.ndarray, factor: float, kink: float, threshold: float) -> numpy.ndarray Piecewise square-root model, followed by threshold. :param x: The vector of x values to calculate the function for :param factor: The multiplication factor for the sqrt function :param kink: The x value where the behaviour changes from sqrt to constant :param threshold: The threshold value of the model :rtype: The vector of fitted values .. py:class:: FitMethod(*args, **kwds) Bases: :py:obj:`enum.Enum` .. autoapi-inheritance-diagram:: bluemira.fuel_cycle.tools.FitMethod :parts: 1 :private-bases: Sink Data fit methods .. py:attribute:: LINEAR .. py:attribute:: SQRT .. py:method:: _missing_(value: str) :classmethod: .. py:function:: fit_sink_data(x: numpy.ndarray, y: numpy.ndarray, method: str | FitMethod = FitMethod.SQRT, *, plot: bool = True) -> tuple[float, float] Function used to determine simplified tritium sink model parameters, from data values. :param x: The vector of x values :param y: The vector of y values :param method: The type of fit to use ['linear', 'sqrt'] :param plot: Whether or not to plot the fitting result :returns: * *slope* -- The slope of the fitted piecewise linear threshold function * *threshold* -- The threshold of the fitted piecewise linear threshold function .. py:function:: delay_decay(t: numpy.ndarray, m_t_flow: numpy.ndarray, tt_delay: float) -> numpy.ndarray Time-shift a tritium flow with a delay and account for radioactive decay. :param t: The time vector [s] :param m_t_flow: The mass flow vector [kg/s] [or any other unit same as return value] :param tt_delay: The delay duration (scalar) [yr] :rtype: The delayed flow vector [kg/s] [or any other unit same as m_t_flow] .. py:function:: fountain(flow: numpy.ndarray, t: numpy.ndarray, min_inventory: float) -> tuple[numpy.ndarray, Ellipsis] Fountain tritium block. Needs a minimum T inventory to operate. This is a binary description. In reality, the TFV systems modelled here (such as the cryogenic distillation column) can and do operate below I_min. :param flow: :math:`m_{T_{flow}}` tritium flow through system [kg/s] :param t: :math:`t` time [years] :param min_inventory: :math:`I_{min}` minimum T inventory for system to operate [kg] :returns: * *m_out* -- :math:`m_{T_{flowout}}` mass flow out [kg/s] * *inventory* -- :math:`I` built-up T inventory in system [kg] .. rubric:: Notes :math:`dt = t[i]-t[i-1]` \n :math:`I[i] = I[i-1]e^{-ln(2)dt/t_{1/2}}+m_{T_{flow}}dt` \n if :math:`I > I_{min}`: :math:`I[i] = I_{min}` [kg]\n :math:`m_{T_{flowout}} = \frac{I_{min}-I[i]}{dt}` [kg/s] \n if :math:`I < I_{min}`: :math:`I[i] = I[i-1]+m_{T_{flow}}dt` [kg] \n :math:`m_{T_{flowout}} = 0` [kg/s] .. py:function:: _speed_recycle(m_start_up: float, t: numpy.ndarray, m_in: numpy.ndarray, m_fuel_injector: numpy.ndarray) -> numpy.ndarray The main recycling loop, JIT compiled. :param m_start_up: An initial guess for the start-up inventory [kg] :param t: The time vector [years] :param m_in: The array of tritium flow-rates required for fusion [kg/s] :param m_fuel_injector: The array of tritium flow-rates fuelling the plasma [kg/s] :returns: The tritium in the stores .. py:function:: find_max_load_factor(time_years: numpy.ndarray, time_fpy: numpy.ndarray) -> float Finds peak slope in fpy as a function of calendar years Divides implicitly by slightly less than a year :param time_years: The time signal [calendar years] :param time_fpy: The time signal [fpy] :returns: The maximum load factor in the time signal (over a one year period) .. py:function:: legal_limit(max_load_factor: float, fb: float, m_gas: float, eta_f: float, eta_fuel_pump: float, f_dir: float, f_exh_split: float, f_detrit_split: float, f_terscwps: float, TBR: float, mb: float | None = None, p_fus: float | None = None) -> float Calculates the release rate of T from the model TFV cycle in kg/yr. :math:`A_{max}\Bigg[\Big[\dot{m_{b}}\Big((\frac{1}{f_{b}}-1)+ (1-{\eta}_{f_{pump}})(1-{\eta}_{f})\frac{1}{f_{b}{\eta}_{f}}\Big)+ \dot{m_{gas}}\Big](1-f_{DIR})(1-f_{tfv})(1-f_{detrit})+\dot{m_{b}} \Lambda f_{TERSCWPS}\Bigg]\times365\times24\times3600` Where: :math:`\dot{m_{b}} = \frac{P_{fus}[MW]M_{T}[g/mol]} {17.58 [MeV]eV[J]N_{A}[1/mol]} [g/s]` :param m_gas: mass of gas flow [kg/s] :param mb: tritium inventory gross burn rate [kg/s] :param p_fus: fusion power [W] :param All other parameters are dimensionless: :returns: release rate of T [kg/yr] :rtype: legal_limit :raises FuelCycleError: Fusion power or burn rate must be specified .. py:function:: _dec_I_mdot(inventory: float, eta: float, m_dot: float, t_in: float, t_out: float) -> float Analytical value of series expansion for an inventory I with a incoming flux of tritium (kg/yr). :math:`I_{end} = Ie^{-{\lambda}{\Delta}t}+{\eta}\dot{m}\sum_{t=0}^{{\Delta}t}e^{-\lambda(T-t)}` :math:`I_{end} = Ie^{-{\lambda}{\Delta}t}+{\eta}\dot{m}\dfrac{e^{-{\lambda}T}\big(e^{{\lambda}({\Delta}t+1/2)}-1\big)}{e^{\lambda}-1}` :returns: output inventory :raises ValueError: Output inventory < 0 .. py:function:: _timestep_decay(flux: float, dt: float) -> float Analytical value of series expansion for an in-flux of tritium over a time- step. Accounts for decay during the timestep only. :math:`I_{end} = I\dfrac{e^{-{\lambda}T}\big(e^{{\lambda}({\Delta}t+1)}-1\big)}{e^{\lambda}-1}` :param flux: The total inventory flowing through on a given time-step [kg] :param dt: The time-step [years] :returns: The value of the total inventory which decayed over the time-step. .. py:function:: _find_t15(inventory: float, eta: float, m_flow: float, t_in: float, t_out: float, inventory_limit: float) -> float Inter-timestep method solving for dt in the below equality: :math:`Ie^{\lambda{\Delta}t}+{\eta}\dot{m}\dfrac{e^{-{\lambda}{\Delta}t} \big(e^{{\lambda}({\Delta}t+1/2)}-1\big)}{e^{\lambda}-1}=I_{lim}` :math:`{\Delta}t=\dfrac{ln\bigg(\dfrac{Ie^{\lambda}-I-{\eta}\dot{m}} {I_{lim}e^{{\lambda}}-I_{lim}-{\eta}\dot{m}e^{\lambda/2}}\bigg)}{\lambda}` :returns: dt relative to t_in of crossing point .. py:function:: _fountain_linear_sink(m_flow: float, t_in: float, t_out: float, inventory: float, fs: float, max_inventory: float, min_inventory: float, sum_in: float, decayed: float) -> tuple[float, float, float, float] A simple linear fountain tritium retention sink model between a minimum and a maximum. Used over a time-step. :param m_flow: The in-flow of tritium [kg/s] :param t_in: The first point in the time-step [years] :param t_out: The second point in the time-step [years] :param inventory: The inventory of tritium already in the sink [kg] :param fs: The tritium release rate of the sink (1-absorbtion rate) :param max_inventory: The threshold inventory of the sink at which point it saturates :param min_inventory: The minimum inventory required for the system to release tritium :param sum_in: Accountancy parameter to calculate the total value lost to a sink :param decayed: Accountancy parameter to calculate the total value of decayed T in a sink :returns: * *m_out* -- The out-flow of tritium [kg/s] * *inventory* -- The amount of tritium in the sink [kg] * *sum_in* -- Accountancy parameter to calculate the total value lost to a sink * *decayed* -- Accountancy parameter to calculate the total value of decayed T in a sink :raises ValueError: Undefined behaviour for inventory > maximum Outflow greater than inflow Negative inventory Negative outflow .. py:function:: _linear_thresh_sink(m_flow: float, t_in: float, t_out: float, inventory: float, fs: float, max_inventory: float, sum_in: float, decayed: float) -> tuple[float, float, float, float] A simple linear tritium retention sink model. Used over a time-step. :param m_flow: The in-flow of tritium [kg/s] :param t_in: The first point in the time-step [years] :param t_out: The second point in the time-step [years] :param inventory: The inventory of tritium already in the sink [kg] :param fs: The tritium release rate of the sink (1-absorbtion rate) :param max_inventory: The threshold inventory of the sink at which point it saturates :param sum_in: Accountancy parameter to calculate the total value lost to a sink :param decayed: Accountancy parameter to calculate the total value of decayed T in a sink :returns: * *m_out* -- The out-flow of tritium [kg/s] * *inventory* -- The amount of tritium in the sink [kg] * *sum_in* -- Accountancy parameter to calculate the total value lost to a sink * *decayed* -- Accountancy parameter to calculate the total value of decayed T in a sink .. py:function:: _sqrt_thresh_sink(m_flow: float, t_in: float, t_out: float, inventory: float, factor: float, max_inventory: float, sum_in: float, decayed: float, *, _testing: bool) -> tuple[float, float, float, float] A simple sqrt tritium retention sink model. Used over a time-step. :param m_flow: The in-flow of tritium [kg/s] :param t_in: The first point in the time-step [years] :param t_out: The second point in the time-step [years] :param inventory: The inventory of tritium already in the sink [kg] :param factor: The multiplication factor of the sqrt function :param max_inventory: The threshold inventory of the sink at which point it saturates :param sum_in: Accountancy parameter to calculate the total value lost to a sink :param decayed: Accountancy parameter to calculate the total value of decayed T in a sink :returns: * *m_out* -- The out-flow of tritium [kg/s] * *inventory* -- The amount of tritium in the sink [kg] * *sum_in* -- Accountancy parameter to calculate the total value lost to a sink * *decayed* -- Accountancy parameter to calculate the total value of decayed T in a sink .. rubric:: Notes :math:`I_{sequestered} = factor \times \sqrt{ t_{fpy}}` The time in the equation is sub-planted for the inventory, to make the retention model independent of time. The values for the threshold and factor must be obtained from detailed T retention modelling. Here, we're tacking the growth of the inventory to a function, but decay is 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. .. py:function:: linear_bathtub(flow: numpy.ndarray, t: numpy.ndarray, eta: float, bci: int, max_inventory: float) -> tuple[numpy.ndarray, numpy.ndarray, float, float] Bathtub sink model. :param flow: The vector of flow-rates [kg/s] :param t: The time vector [years] :param eta: The bathtub tritium release fraction :param bci: The blanket change index. Used if a component is replaced to reset the inventory to 0. :param max_inventory: The threshold inventory for the bathtub. :returns: * *m_out* -- The out-flow of tritium [kg/s] * *inventory* -- The amount of tritium in the sink [kg] * *sum_in* -- Accountancy parameter to calculate the total value lost to a sink * *decayed* -- Accountancy parameter to calculate the total value of decayed T in a sink .. py:function:: sqrt_bathtub(flow: numpy.ndarray, t: numpy.ndarray, factor: float, bci: int, max_inventory: float, *, _testing: bool = False) -> tuple[numpy.ndarray, numpy.ndarray, float, float] Bathtub sink model with a sqrt inventory retention law. :param flow: The vector of flow-rates [kg/s] :param bci: The blanket change index. Used if a component is replaced to reset the inventory to 0. :param t: The time vector [years] :param factor: The sqrt model multiplication factor :param max_inventory: The threshold inventory for the bathtub. :param _testing: Used for testing purposes only (switches off decay). :returns: * *m_out* -- The out-flow of tritium [kg/s] * *inventory* -- The amount of tritium in the sink [kg] * *sum_in* -- Accountancy parameter to calculate the total value lost to a sink * *decayed* -- Accountancy parameter to calculate the total value of decayed T in a sink .. py:function:: fountain_bathtub(flow: numpy.ndarray, t: numpy.ndarray, fs: float, max_inventory: float, min_inventory: float) -> tuple[numpy.ndarray, numpy.ndarray, float, float] A fountain and bathtub sink simultaneously. :param flow: Tritium flow through system [kg/s] :param t: Time [years] :param fs: efficiency of bathtub :param min_inventory: Minimum T inventory for system to operate [kg] :param max_inventory: Maximum T inventory for system to operate [kg] :returns: * *m_out* -- The out-flow of tritium [kg/s] * *inventory* -- The amount of tritium in the sink [kg] * *sum_in* -- Accountancy parameter to calculate the total value lost to a sink * *decayed* -- Accountancy parameter to calculate the total value of decayed T in a sink :math:`dt = t[i]-t[i-1]` :math:`I[i] = I[i-1]e^{-ln(2)dt/t_{1/2}}` if :math:`I < I_{min}`: :math:`I[i] += m_{T_{flow}}dt` :math:`m_{T_{flowout}} = 0` if :math:`I >= I_{max}`: :math:`I[i] = I_{max}` :math:`m_{T_{flowout}} = m_{T_{flow}}` if :math:`I < I_{max}`: :math:`m_{T_{flowout}} = {\eta}m_{T_{flow}}` :math:`I += (1-{\eta})m_{T_{flow}}dt`