Source code for ogstools.physics.nuclearwasteheat.nuclearwaste

# Copyright (c) 2012-2024, OpenGeoSys Community (http://www.opengeosys.org)
#            Distributed under a Modified BSD License.
#            See accompanying file LICENSE.txt or
#            http://www.opengeosys.org/project/license
#

from dataclasses import dataclass
from typing import Optional, Union

import numpy as np
from pint.facets.plain import PlainQuantity

from ._unitsetup import Q_


[docs] @dataclass class NuclearWaste: "Models the heat generated by one type of nuclear fuel waste." name: str "Name of this type of waste." nuclide_powers: Union[PlainQuantity, np.ndarray] "Powers for the different leading nuclides." decay_consts: Union[PlainQuantity, np.ndarray] "Decay constants for the different leading nuclides." num_bundles: int "Number of nuclear waste bundles." time_interim: Union[PlainQuantity, float] "Interim storage time before heat evaluation." time_deposit: Union[PlainQuantity, float] = 0.0 "Number of active bundles linearly increases until this time is reached." factor: Union[PlainQuantity, float] = 1.0 "Scale the calculated heat by this factor."
[docs] def heat( self, t: Union[PlainQuantity, float, np.ndarray], baseline: bool = False, ncl_id: Optional[int] = None, time_unit: str = "s", power_unit: str = "W", ) -> Union[float, np.ndarray]: """Calculate the heat of a nuclear waste proxy model. :param t: Timevalue(s) at which the heat is calculated. :param ncl_id: If given, only output the heat by nuclide with this id, else sum the heat over all nuclides. :param baseline: If True, evaluate one bundle with no interim or deposition time delay. :returns: Heat generated by the nuclear waste at time t. """ _t = Q_(t).magnitude _nuclide_powers = Q_(self.nuclide_powers, power_unit).magnitude _decay_consts = Q_(self.decay_consts, f"1/{time_unit}").magnitude _num_bundles = self.num_bundles _time_interim = Q_(self.time_interim, time_unit).magnitude _time_deposit = Q_(self.time_deposit, time_unit).magnitude if baseline: _num_bundles, _time_interim, _time_deposit = 1, 0.0, 0.0 t_per_bundle = np.linspace(_t - _time_deposit, _t, _num_bundles) t_per_bundle = np.ma.masked_less(t_per_bundle, 0) + _time_interim # decay values for each nuclide via matrix multiplicaation # results in shape (num_bundles, len(t), len(decay_consts)) decay = np.exp(-t_per_bundle[..., None] @ _decay_consts[None, ...]) # sum over all bundles res = np.sum(self.factor * _nuclide_powers * decay, axis=0) # optionally sum over nuclides return np.sum(res, axis=-1) if ncl_id is None else res[..., ncl_id]
[docs] @dataclass class Repository: "Models the heat generated by total repository inventory." waste: list[NuclearWaste] "Waste inventory of the repository."
[docs] def time_deposit(self, time_unit: str = "s") -> Union[float, list[float]]: "Deposition time for each nuclear waste type." if len(self.waste) == 1: return Q_(self.waste[0].time_deposit).to(time_unit).magnitude return [ Q_(nw.time_deposit).to(time_unit).magnitude for nw in self.waste ]
[docs] def heat( self, t: Union[PlainQuantity, float, np.ndarray], baseline: bool = False, ncl_id: Optional[int] = None, time_unit: str = "s", power_unit: str = "W", ) -> Union[float, np.ndarray]: """Calculate the heat produced by the repository at time t. :param t: Timevalue(s) at which the heat is calculated. :param ncl_id: If given, only output the heat by nuclide with this id, else sum the heat over all nuclides. :param baseline: If True, evaluate one bundle for each waste with no interim or deposition time delay. :returns: Heat generated by the repository at time t. """ result = [ nw.heat(t, baseline, ncl_id, time_unit, power_unit) for nw in self.waste ] return np.sum(np.array(result), axis=0)