esbmtk package
esbmtk: A general purpose Earth Science box model toolkit.
Copyright (C), 2020 Ulrich G. Wortmann
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
Submodules
esbmtk.base_classes module
esbmtk: A general purpose Earth Science box model toolkit.
Copyright (C), 2020 Ulrich G. Wortmann
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
- class esbmtk.base_classes.ElementProperties(**kwargs)[source]
Bases:
esbmtkBaseElement-specific properties for models.
Each model can have one or more elements. This class defines the properties specific to elements, such as name, mass unit, and isotope information.
- Parameters:
name (str) – The element name, e.g., “S”
model (Model) – The model handle
mass_unit (str | Q_) – Base mass unit, e.g., “mol”
li_label (str, optional) – Label of light isotope, e.g., “$^{32}$S”
hi_label (str, optional) – Label of heavy isotope, e.g., “$^{34}$S”
d_label (str, optional) – Label for delta value, e.g., r”$delta^{34}$S”
d_scale (str, optional) – Isotope scale, e.g., “VCDT”
r (float | int, optional) – Isotopic abundance ratio for element, defaults to 1
reference (str, optional) – Reference for isotope values, e.g., URL or citation
register (str | Model, optional) – Where to register this element, defaults to model
parent (str | Model, optional) – Parent object (usually model), defaults to model
full_name (str, optional) – Full name of the element
Examples
>>> ElementProperties( ... name="S", ... model=Test_model, ... mass_unit="mol", ... li_label="$^{32}$S", ... hi_label="$^{34}$S", ... d_label=r"$\delta^{34}$S", ... d_scale="VCDT", ... r=0.044162589, ... reference="https link or citation" ... )
- add_species(species: SpeciesProperties) None[source]
Add a species to this element’s species list.
- Parameters:
species (SpeciesProperties) – Species to add to this element
- Return type:
None
- class esbmtk.base_classes.Flux(**kwargs: dict[str, any])[source]
Bases:
esbmtkBaseA class which defines a flux object.
Flux objects contain information which links them to an species, describe things like the mass and time unit, and store data of the total flux rate at any given time step. Similarly, they store the flux of the light and heavy isotope flux, as well as the delta of the flux. This is typically handled through the Species2Species object. If you set it up manually
Example:
Flux = (name = "Name" # optional, defaults to _F species = species_handle, delta = any number, rate = "12 mol/s" # must be a string display_precision = number, optional, inherited from Model
)
You can access the flux data as
Name.m # mass
Name.d # delta
Name.c # same as Name.m since flux has no concentration
- exception esbmtk.base_classes.FluxError(message)[source]
Bases:
ExceptionCustom Error Class for flux-related errors.
- exception esbmtk.base_classes.ReservoirError(message)[source]
Bases:
ExceptionCustom Error Class for reservoir-related errors.
- exception esbmtk.base_classes.ScaleError(message)[source]
Bases:
ExceptionCustom Error Class for unit scale-related errors.
- class esbmtk.base_classes.Sink(**kwargs)[source]
Bases:
SourceSinkMeta class to setup a Source/Sink objects.
These are not actual reservoirs, but we stil need to have them as objects Example:
Sink(name = "Pyrite", species = SO4, display_precision = number, optional, inherited from Model delta = number or str. optional defaults to "None" register = Model handle )
- class esbmtk.base_classes.Source(**kwargs)[source]
Bases:
SourceSinkMeta class to setup a Source/Sink objects.
These are not actual reservoirs, but we stil need to have them as objects Example:
Ssource(name = "weathering", species = SO4, display_precision = number, optional, inherited from Model delta = number or str. optional defaults to "None" register = Model handle )
- class esbmtk.base_classes.SourceSink(**kwargs)[source]
Bases:
esbmtkBaseMeta class to setup a Source/Sink objects.
These are not actual reservoirs, but we stil need to have them as objects Example:
Sink(name = "Pyrite", species = SO4, display_precision = number, optional, inherited from Model delta = number or str. optional defaults to "None" register = Model handle )
- property delta
Delta Setter.
- class esbmtk.base_classes.Species(**kwargs)[source]
Bases:
SpeciesBaseSpecies implementation for chemical species in a model.
This class provides a concrete implementation of SpeciesBase for chemical species with properties like mass, concentration, and isotope information.
- Parameters:
name (str) – Name of the reservoir
species (SpeciesProperties) – Handle to the species properties
delta (float | int | str, optional) – Initial delta value for isotope calculation
concentration (str | Q_ | float, optional) – Species concentration (must provide either this or mass)
mass (str | Q_, optional) – Species mass (must provide either this or concentration)
volume (str | Q_, optional) – Reservoir volume (must provide either this or geometry)
geometry (list | dict | str, optional) – Geometry parameters for volume calculation
plot (str, optional) – Whether to plot this species, defaults to “yes”
plot_transform_c (callable, optional) – Function to transform concentration for plotting
legend_left (str, optional) – Custom label for left y-axis
display_precision (float | int, optional) – Decimal places for display, defaults to 0.01
register (any, optional) – Where to register this species
isotopes (bool, optional) – Whether to use isotope values
seawater_parameters (dict | str, optional) – Parameters for seawater calculations
Examples
>>> Species( ... name="foo", ... species=S, ... delta=20, ... concentration="1 mmol/liter", ... volume="1E5 liter", ... )
Notes
You must provide either mass or concentration, and either volume or geometry. For geometry, you can provide a list [upper_depth, lower_depth, total_area] or a dictionary with “area” and “volume” keys.
- DEFAULT_RTYPE = 'regular'
- class esbmtk.base_classes.SpeciesBase(**kwargs)[source]
Bases:
esbmtkBaseBase class for all Species objects.
This class provides common functionality for all species-related classes, including data handling, visualization, and state management.
Notes
This is an abstract base class that should not be instantiated directly. Use the derived classes like Species instead.
- get_conversion_unit_information() tuple[source]
Extract unit and scaling information.
This method provides the unit information and a scaling factor that maps from model units to display units.
- Returns:
Tuple containing (unit name, scaling factor)
- Return type:
- Raises:
SpeciesError – If plot_transform_c is not a callable function
- exception esbmtk.base_classes.SpeciesError(message)[source]
Bases:
ExceptionCustom Error Class for species-related errors.
- class esbmtk.base_classes.SpeciesProperties(**kwargs)[source]
Bases:
esbmtkBaseProperties class for chemical species in a model.
This class defines the properties specific to chemical species, such as their name, display format, and relationship to elements.
- Parameters:
name (str) – Name of the species, e.g., “SO4”
element (ElementProperties) – Handle to the element this species belongs to
display_as (str, optional) – How to display the species, defaults to name if not provided
m_weight (int | float | str, optional) – Molecular weight, defaults to 0
register (Model | ElementProperties | Species | GasReservoir, optional) – Where to register this species, defaults to element
parent (Model | ElementProperties | Species | GasReservoir, optional) – Parent object, defaults to register value
flux_only (bool, optional) – Whether this species only exists in fluxes, not reservoirs, defaults to False
logdata (bool, optional) – Whether to log data for this species, defaults to False
scale_to (str, optional) – Unit to scale to for display, defaults to “mmol”
stype (str, optional) – Species type, defaults to “concentration”
Examples
>>> SpeciesProperties( ... name="SO4", ... element=S, ... )
Notes
When a species is created, it’s automatically registered with its element.
- DEFAULT_SCALE_TO = 'mmol'
- DEFAULT_STYPE = 'concentration'
esbmtk.carbonate_chemistry module
esbmtk: A general purpose Earth Science box model toolkit.
Copyright (C), 2020-2021 Ulrich G. Wortmann
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
- exception esbmtk.carbonate_chemistry.CarbonateSystem2Error(message)[source]
Bases:
ExceptionCustom Error Class for Model-related errors.
- esbmtk.carbonate_chemistry.add_carbonate_system_1(rgs: list)[source]
Create a new carbonate system virtual reservoir.
For each reservoir in rgs. Note that rgs must be a list of reservoir groups.
- Required keywords:
rgs: tp.List = [] of Reservoir Group objects
These new virtual reservoirs are registered to their respective Species as ‘cs’.
The respective data fields are available as rgs.r.cs.xxx where xxx stands for a given key key in the vr_datafields dictionary (i.e., H, CA, etc.)
- esbmtk.carbonate_chemistry.add_carbonate_system_2(**kwargs) None[source]
Create a new carbonate system virtual reservoir.
which will compute carbon species, saturation, compensation, and snowline depth, and compute the associated carbonate burial fluxes
- Required keywords:
source_box: tp.List of Reservoir objects in the surface layer this_box: tp.List of Reservoir objects in the deep layer carbonate_export_fluxes: tp.List of flux objects which must match the list of Reservoir objects. zsat_min = depth of the upper boundary of the deep box z0 = upper depth limit for carbonate burial calculations typically zsat_min
Optional Parameters:
zsat = initial saturation depth (m) zcc = initial carbon compensation depth (m) zsnow = initial snowline depth (m) zsat0 = characteristic depth (m) Ksp0 = solubility product of calcite at air-water interface (mol^2/kg^2) kc = heterogeneous rate constant/mass transfer coefficient for calcite dissolution (kg m^-2 yr^-1) Ca2 = calcium ion concentration (mol/kg) pc = characteristic pressure (atm) pg = seawater density multiplied by gravity due to acceleration (atm/m) I = dissolvable CaCO3 inventory co3 = CO3 concentration (mol/kg) Ksp = solubility product of calcite at in situ sea water conditions (mol^2/kg^2)
- esbmtk.carbonate_chemistry.add_carbonate_system_3(**kwargs) None[source]
Create a new carbonate system virtual reservoir.
This function initializes carbonate system 2 (cs2) for each specified deep box. It computes saturation, compensation, and snowline depth, and the associated carbonate burial fluxes.
- Required keywords:
r_sb / source_box: list of surface Reservoirs r_db / this_box: list of deep Reservoirs r_nb / next_box: list of sink Reservoirs carbonate_export_fluxes: list of CaCO3 export Flux objects z0: depth (m) for burial calculations
- Optional (defaulted) keywords:
zsat, zcc, zsnow, zsat0, Ksp0, kc, alpha, pg, pc, I_caco3, zmax, Ksp
- esbmtk.carbonate_chemistry.carbonate_system_1(dic, ta, hplus_0, co2aq_0, p) tuple[source]
Return the H+ and carbonate alkalinity concentrations.
- Parameters:
dic – float with the dic concentration
ta – float with the ta concentration
hplus_0 – float with the H+ concentration
co2aq_0 – float with the [CO2]aq concentration
p – tuple with the parameter list
- Returns:
dCdt_Hplus, dCdt_co2aq
LIMITATIONS: - Assumes all concentrations are in mol/kg - Assumes your Model is in mol/kg ! Otherwise, DIC and TA updating will not be correct.
Calculations are based off equations from: Boudreau et al., 2010, https://doi.org/10.1029/2009GB003654 Follows, 2006, doi:10.1016/j.ocemod.2005.05.004
- esbmtk.carbonate_chemistry.carbonate_system_2(CaCO3_export: float, dic_t_db: float | tuple, ta_db: float, dic_t_sb: float | tuple, hplus_0: float, zsnow: float, p: tuple) tuple[source]
Return the fraction of the carbonate rain that is dissolved.
This functions returns:
DIC_burial, DIC_burial_l, Hplus, zsnow
LIMITATIONS: - Assumes all concentrations are in mol/kg - Assumes your Model is in mol/kg
Calculations are based off equations from: Boudreau et al., 2010, https://doi.org/10.1029/2009GB003654
- esbmtk.carbonate_chemistry.carbonate_system_3(CaCO3_export: float, dic_t_db: float | tuple, ta_db: float, dic_t_sb: float | tuple, hplus_0: float, zsnow: float, p: tuple) tuple[source]
Return the fraction of the carbonate rain that is dissolved.
This functions returns:
DIC_burial, DIC_burial_l, Hplus, zsnow
LIMITATIONS: - Assumes all concentrations are in mol/kg - Assumes your Model is in mol/kg
Calculations are based off equations from: Boudreau et al., 2010, https://doi.org/10.1029/2009GB003654
- esbmtk.carbonate_chemistry.get_hplus(dic, ta, h0, boron, K1, K1K2, KW, KB) float[source]
Calculate H+ concentration based on a previous estimate.
[H+]. After Follows et al. 2006, doi:10.1016/j.ocemod.2005.05.004
- Parameters:
dic – DIC in mol/kg
ta – TA in mol/kg
h0 – initial guess for H+ mol/kg
boron – boron concentration
K1 – Ksp1
K1K2 – Ksp1 * Ksp2
KW – K_water
KB – K_boron
- Returns H:
new H+ concentration in mol/kg
- esbmtk.carbonate_chemistry.get_zcc(export, zmax, zsat_min, zsat0, ca2, ksp0, AD, kc, co3)[source]
Calculate zcc.
- esbmtk.carbonate_chemistry.init_carbonate_system_1(rg: Reservoir)[source]
Create a new carbonate system virtual reservoir.
for each reservoir in rgs. Note that rgs must be a list of reservoir groups.
- Required keywords:
rgs: tp.List = [] of Reservoir Group objects
These new virtual reservoirs are registered to their respective Species as ‘cs’.
The respective data fields are available as rgs.r.cs.xxx where xxx stands for a given key key in the vr_datafields dictionary (i.e., H, CA, etc.)
- esbmtk.carbonate_chemistry.init_carbonate_system_2(export_flux: Flux, source_box: Reservoir, this_box: Reservoir, kwargs: dict)[source]
Initialize a carbonate system 2 instance.
Note that the current implmentation assumes that the export flux is the total export flux over surface area of the mixed layer, i.e., the sediment area between z0 and zmax
- esbmtk.carbonate_chemistry.init_carbonate_system_3(export_flux: Flux, source_box: Reservoir, this_box: Reservoir, next_box: Reservoir, kwargs: dict)[source]
Initialize a carbonate system 3 instance.
Note that the current implmentation assumes that the export flux into this_box is the total export flux over surface area of the mixed layer, i.e., the sediment area between z0 and zmax
esbmtk.connections module
esbmtk: A general purpose Earth Science box model toolkit.
Copyright (C), 2020 Ulrich G. Wortmann
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
- class esbmtk.connections.ConnectionProperties(**kwargs)[source]
Bases:
esbmtkBaseConnectionProperties Class.
Connect reservoir/sink/source groups when at least one of the arguments is a reservoirs_group object. This method will create regular connections for each matching species.
Use the connection.update() method to fine tune connections after creation
Example:
ConnectionProperties(source = upstream reservoir / upstream reservoir group sink = downstrean reservoir / downstream reservoirs_group delta = defaults to zero and has to be set manually epsilon = defaults to zero and has to be set manually rate = shared between all connections ref_reservoirs = shared between all connections ref_flux = shared between all connections species = list, optional, if present, only these species will be connected ctype = needs to be set for all connections. Use "Fixed" unless you require a specific connection type pl = [list]) process list. optional, shared between all connections id = optional identifier, passed on to individual connection plot = "yes/no" # defaults to yes, shared between all connections ) ConnectionProperties( source=OM_Weathering, sink=Ocean, rate={DIC: f"{OM_w} Tmol/yr" , ALK: f"{0} Tmol/yr"}, ctype = {DIC: "Fixed", ALK: "Fixed"}, )
- class esbmtk.connections.Species2Species(**kwargs)[source]
Bases:
esbmtkBaseConnect two reservoir species to each other.
This module creates the connecting flux and creates a connector object which stores all connection properties.
For simple connections, the type flux type is derived implcitly from the specified parameters. For complex connections, the flux type must be set explicitly. See the examples below:
- Parameters:
source (-)
sink (-)
rate (-)
delta (-)
ref_reservoirs (-)
epsilon (-)
id (-) – automatic name creation
signal (-)
ctype (-)
bypass (-)
The connection name is derived automatically, and can be queried with M.connection_summary()
Connection Types:
Connecting two reservoirs with a fixed rate: >>> Species2Species( # deep box to sediment >>> ctype=”fixed”, >>> source=M.L_b.PO4, >>> sink=M.Fb.PO4, >>> scale=”108 Gmol/year”, >>> id=”shelf_burial”, >>> )
Connecting two reservoirs with a concentration dependent flux: >>> Species2Species( # Surface to deep box >>> source=M.L_b.PO4, >>> sink=M.D_b.PO4, >>> ctype=”scale_with_concentration”, >>> scale=M.L_b.PO4.volume >>> / M.tau >>> * M.L_b.swc.density >>> / 1000, # concentration * volume = mass * 1/tau >>> id=”po4_productivity”, >>> )
Connecting two reservoirs using another flux as reference. Note presently, you cannot chain flux references! You can use a reference flux multiple times, but it is not possible to reference f1 for f2, and then reference f2 for f3. The reference flux can either be given as a flux object, e.g., as returned from a flux lookup:
M.flux_summary(filter_by=”po4_productivity”, return_list=True)[0]
or simply as the id string:
“po4_productivity”
>>> Species2Species( # deep box to sediment >>> source=M.D_b.PO4, >>> sink=M.Fb.PO4, >>> ctype="scale_with_flux", >>> ref_flux=""po4_productivity", >>> # increase p_burial >>> scale=(1 - M.remin_eff), # burial of ~1% P >>> id="burial", >>> )
Useful methods in this class
info() will provide a short description of the connection objects.
list_processes() which will list all the processes which are associated with this connection.
update() which allows you to update connection properties after the connection has been created
- get_species(r1, r2) None[source]
Set the species by r2.
However, if we have backward fluxes the species depends on the r2
esbmtk.esbmtk_base module
esbmtk: A general purpose Earth Science box model toolkit.
Copyright (C), 2020 Ulrich G. Wortmann
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
- exception esbmtk.esbmtk_base.FluxSpecificationError(message)[source]
Bases:
ExceptionException raised for errors in flux specifications.
- Parameters:
message (str) – Explanation of the error
Examples
>>> raise FluxSpecificationError("Unknown flux units")
- exception esbmtk.esbmtk_base.InputError(message)[source]
Bases:
ExceptionException raised for errors in the input parameters.
- Parameters:
message (str) – Explanation of the error
Examples
>>> raise InputError("Value must be positive")
- class esbmtk.esbmtk_base.InputParsing[source]
Bases:
objectProvides various routines to parse and process keyword arguments.
All derived classes need to declare the allowed keyword arguments, their default values and the type in the following format:
defaults = {“key”: [value, (allowed instances)]}
The recommended sequence is to first set default values via __register_variable_names__() and then update with provided values using __update_dict_entries__(defaults, kwargs).
Notes
This class is not meant to be instantiated directly.
- exception esbmtk.esbmtk_base.KeywordError(message)[source]
Bases:
ExceptionException raised for errors in keyword arguments.
- Parameters:
message (str) – Explanation of the error
Examples
>>> raise KeywordError("Invalid keyword 'xyz'")
- exception esbmtk.esbmtk_base.MissingKeywordError(message)[source]
Bases:
ExceptionException raised when a required keyword argument is missing.
- Parameters:
message (str) – Explanation of the error
Examples
>>> raise MissingKeywordError("'name' is a mandatory keyword")
- exception esbmtk.esbmtk_base.SpeciesPropertiesMolweightError(message)[source]
Bases:
ExceptionException raised when molecular weight is missing or invalid.
- Parameters:
message (str) – Explanation of the error
Examples
>>> raise SpeciesPropertiesMolweightError("Missing molecular weight for C")
- class esbmtk.esbmtk_base.esbmtkBase[source]
Bases:
InputParsingThe esbmtk base class template.
This class handles keyword arguments, name registration and other common tasks.
Examples
# Define required keywords in lrk list self.lrk: tp.List = ["name"] # Define allowed type per keyword in defaults dict self.defaults: dict[str, list[any, tuple]] = { "name": ["None", (str)], "model": ["None", (str, Model)], "salinity": [35, (int, float)], # int or float } # Parse and register all keywords with the instance self.__initialize_keyword_variables__(kwargs) # Register the instance self.__register_with_parent__()
- ensure_q(arg)[source]
Ensure that a given input argument is a quantity object.
- Parameters:
arg (str, Quantity, or numeric) – The argument to convert to a Quantity
- Returns:
The input argument as a Quantity object
- Return type:
Quantity
- Raises:
InputError – If the argument is None, empty, or cannot be converted to a Quantity
Examples
>>> self.ensure_q("10 kg") <Quantity(10, 'kilogram')> >>> self.ensure_q(existing_quantity) <Quantity(existing_quantity)>
- help() None[source]
Show all keywords, their default values and allowed types.
Prints information about all available keywords and highlights which ones are mandatory.
- Return type:
None
Examples
>>> obj.help()
- info(**kwargs) None[source]
Show an overview of the object properties.
- Parameters:
**kwargs (dict, optional)
arguments (Additional keyword)
----------------------------
indent (*) – Number of spaces for indentation
- Return type:
None
Examples
obj.info(indent=2)
- set_flux(mass: str, time: str, substance: SpeciesProperties)[source]
Convert a flux rate to model units (kg/s or mol/s).
- Parameters:
mass (str) – Mass value with units, e.g., “12 Tmol” or “500 kg”
time (str) – Time unit, e.g., “year”, “day”, “s”
substance (SpeciesProperties) – Species properties object containing molecular weight information
- Returns:
Flux rate in model units (mol/time or g/time)
- Return type:
Quantity
- Raises:
InputError – If input parameters are None, empty, or of incorrect type
FluxSpecificationError – If unit conversion cannot be performed
SpeciesPropertiesMolweightError – If substance has no molecular weight defined
Examples
>>> M.set_flux("12 Tmol", "year", M.C) <Quantity(12, 'teramol / year')>
Notes
If model mass units are in mol, no mass unit conversion will be made. If model mass units are in kg, the flux will be converted accordingly.
- validate() bool[source]
Validate the object state after initialization.
This method performs comprehensive validation of the object’s attributes to ensure they are in a consistent and valid state.
- Returns:
True if the object is valid
- Return type:
- Raises:
ValueError – If the object fails validation
AttributeError – If required attributes are missing
Examples
>>> obj = SomeClass(name="test", value=10) >>> obj.validate() # Returns True if valid, raises exception if not True
esbmtk.extended_classes module
esbmtk: A general purpose Earth Science box model toolkit.
Copyright (C), 2020 Ulrich G. Wortmann
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
- exception esbmtk.extended_classes.CSVDataError(message)[source]
Bases:
ExceptionCustom Error Class.
- exception esbmtk.extended_classes.CSVReadError(message)[source]
Bases:
ExceptionCustom Error Class.
- class esbmtk.extended_classes.DataField(**kwargs: dict[str, any])[source]
Bases:
esbmtkBaseDataField Class.
Datafields can be used to plot data which is computed after the model finishes in the overview plot windows. Therefore, datafields will plot in the same window as the reservoir they are associated with. Datafields must share the same x-axis is the model, and can have up to two y axis.
Example:
DataField(name = "Name" register = Model handle, x1_data = ["None", (np.ndarray, list)], defaults to model time y1_data = NDArrayFloat or list of arrays y1_label = Data label(s) y1_legend = Y-Axis Label y1_type = "plot", | "scatter" y2_data = NDArrayFloat # optional y2_legend = Y-Axis label # optional y2_label = Data legend(s) # optional y2_type = "plot", | "scatter" common_y_scale = "no", #optional, default "no" display_precision = number, optional, inherited from Model )
All y1 and y2 keywords can be either a single value or a list of values. Note that Datafield data is not mapped to model units. Care must be taken that the data units match the model units.
The instance provides the following data
Name.x = X-axis = model X-axis Name.y1_data Name.y1_label Name.y1_legend
Similarly for y2
You can specify more than one data set, and be explicit about color and linestyle choices.
Example:
DataField( name="df_pH", x1_data=[M.time, M.time, M.time, M.ef_hplus_l.x, M.ef_hplus_h.x, M.ef_hplus_d.x], y1_data=[ -np.log10(M.L_b.Hplus.c), -np.log10(M.H_b.Hplus.c), -np.log10(M.D_b.Hplus.c), -np.log10(M.ef_hplus_l.y), -np.log10(M.ef_hplus_h.y), -np.log10(M.ef_hplus_d.y), ], y1_label="Low latitude, High latitude, Deep box, d_L, d_H, d_D".split( ", "), y1_color="C0 C1 C2 C0 C1 C2".split(" "), y1_style="solid solid solid dotted dotted dotted".split( " "), y1_legend="pH", register=M, )
- exception esbmtk.extended_classes.DataFieldError(message)[source]
Bases:
ExceptionCustom Error Class.
- exception esbmtk.extended_classes.ESBMTKFunctionError(message)[source]
Bases:
ExceptionCustom Error Class.
- class esbmtk.extended_classes.ExternalCode(**kwargs)[source]
Bases:
SpeciesNoSetImplement user-provided functions.
The data inside an ExternalCode instance will only change in response to a user-provided function but will otherwise remain unaffected. That is, it is up to the user-provided function to manage changes in response to external fluxes.
An ExternalCode instance is declared in the following way:
ExternalCode( name="cs", # instance name species=M.CO2, # must be Speciesproperties instance vr_datafields={ # the vr_datafields contain any data that is referenced inside the "Hplus": self.swc.hplus, # function, rather than passed as an argument, and all data "Beta": 0.0 # that is explicitly referenced by the model }, function=calc_carbonates, # function reference, see below fname="function name as string", function_input_data="DIC TA", # Note that parameters must be individual float values function_params=(float), return_values={ # list of return values, these must be known species definitions "Hplus": rg.swc.hplus, "zsnow": float(abs(kwargs["zsnow"])), }, register=rh # reservoir_handle to register with )
The dictionary keys of vr_datafields will be used to create alias names which c an be used to access the respective variables. See the online documentation: https://esbmtk.readthedocs.io/
In the default configuration, ExternalCode instances are computed after all regular connections have been established. However, sometimes, a connection may depend on a computed value. In this case set the optional parameter ftype to “in_sequence”
- append(**kwargs) None[source]
Update GenericFunction parameters.
After the VirtualSpecies has been initialized. This is most useful when parameters have to reference other virtual reservoirs which do not yet exist, e.g., when two virtual reservoirs have a circular reference.
Example:
VR.update(a1=new_parameter, a2=new_parameter)
- class esbmtk.extended_classes.ExternalData(**kwargs: dict[str, str])[source]
Bases:
esbmtkBaseInstances of this class hold external X/Y data.
which can be associated with a reservoir.
Example:
ExternalData(name = "Name" filename = "filename", legend = "label", legend_z = "label", offset = "0 yrs", reservoir = reservoir_handle, scale = scaling factor, optional display_precision = number, optional, inherited from Model convert_to = optional, see below y_as_z = False, plot_as_line = False, plot_args = {}, e.g., {"alpha": 0.5} )
The data must exist as CSV file, where the first column contains the X-values, and the second column contains the Y-values.
The x-values must be time and specify the time units in the header between square brackets They will be mapped into the model time units.
The y-values can be any data, but the user must take care that they match the model units defined in the model instance. So your data file mujst look like this
Time [years], Data [units], Data [units] 1, 12, -12 2, 13, 12
By convention, the secon column should contain the same type of data as the reservoir (i.e., a concentration), whereas the third column contain isotope delta values. In cases were there is no concentration data, set y_as_z = True, and the second column will be printed on the right side of the plot. This will only work for reservoirs that have isotope data though!
The column headers are only used for the time or concentration data conversion, and are ignored by the default plotting methods, but they are available as self.xh,yh
The convert_to keyword can be used to force a specific conversion. The default is to convert into the model concentration units.
Note that the instance name will be a combination of the name specified in the name field, and the name of the reservoir the data is associated with.
The plot_args keyword allows to pass arbitrary plot arguments
- - name.plot()
- Data:
name.x
name.y
name.df = dataframe as read from csv file
- exception esbmtk.extended_classes.ExternalDataError(message)[source]
Bases:
ExceptionCustom Error Class.
- class esbmtk.extended_classes.GasReservoir(**kwargs)[source]
Bases:
SpeciesBasereservoir specific information similar to the Species class.
Example:
Species(name = "foo", # Name of reservoir species = CO2, # SpeciesProperties handle # initial delta - optional (defaults to 0) delta = 20, reservoir_mass = quantity # total mass of all gases defaults to 1.78E20 mol species_ppm = number # concentration in ppm plot = "yes"/"no", defaults to yes plot_transform_c = a function reference, optional (see below) legend_left = str, optional, useful for plot transform display_precision = number, optional, inherited from Model register = optional, use to register with Reservoir Group isotopes = True/False otherwise use Model.m_type )
Accesing Species Data:
You can access the reservoir data as:
Name.m # species mass
Name.l # mass of light isotope
Name.d # species delta (only avaible after M.get_delta_values()
Name.c # partial pressure
Name.v # total gas mass
Useful methods include:
Name.write_data() # save data to file
Name.info() # info Species
- exception esbmtk.extended_classes.GasReservoirError(message)[source]
Bases:
ExceptionCustom Error Class.
- class esbmtk.extended_classes.Reservoir(**kwargs)[source]
Bases:
esbmtkBaseCreate a group of reservoirs.
which share a common volume, and potentially connections. E.g., if we have twoy reservoir groups with the same reservoirs, and we connect them with a flux, this flux will apply to all reservoirs in this group.
A typical examples might be ocean water which comprises several species. A reservoir group like ShallowOcean will then contain sub-reservoirs like DIC in the form of ShallowOcean.DIC
Example:
Reservoir(name = "ShallowOcean", # Name of reservoir group volume/geometry = "1E5 l", # see below delta = {DIC:0, TA:0, PO4:0] # dict of delta values mass/concentration = {DIC:"1 unit", TA: "1 unit"} plot = {DIC:"yes", TA:"yes"} defaults to yes isotopes = {DIC: True/False} see Species class for details seawater_parameters = dict, optional, see below register= model handle, required )
- Notes: The subreservoirs are derived from the keys in the concentration or mass
dictionary. Toward this end, the keys must be valid species handles and – not species names – !
Connecting two reservoir groups requires that the names in both group match, or that you specify a dictionary which delineates the matching.
Most parameters are passed on to the Species class. See the reservoir class documentation for details
The geometry keyword specifies the upper depth interval, the lower depth interval, and the fraction of the total ocean area inhabited by the reservoir
If the geometry parameter is supplied, the following instance variables will be computed:
self.volume: in model units (usually liter)
self.area: surface area in m^2 at the upper bounding surface
self.sed_area: area of seafloor which is intercepted by this box.
self.area_fraction: area of seafloor which is intercepted by this relative to the total ocean floor area
seawater_parameters:
If this optional parameter is specified, a SeaWaterConstants instance will be registered for this Species as Species.swc See the SeaWaterConstants class for details how to specify the parameters, e.g.:
seawater_parameters = {"temperature": 2, "pressure": 240, "salinity" : 35, },
- exception esbmtk.extended_classes.ReservoirError(message)[source]
Bases:
ExceptionCustom Error Class.
- class esbmtk.extended_classes.Signal(**kwargs)[source]
Bases:
esbmtkBaseCreate a signal.
which is described by its startime (relative to the model time), it’s size (as mass) and duration, or as duration and magnitude. Furthermore, we can presribe the signal shape (square, pyramid, bell, file )and whether the signal will repeat. You can also specify whether the event will affect the delta value. Alternatively, signal can be read from a CSV file. The file needs to specify Time [unit], Flux [unit/time unit], delta value
The delta value column is optional.The units must be of similar dimensions as the model dimensions (e.g., mol/l or mol/kg). Data will be automatically interpolated.
Example:
Signal(name = "Name", species = SpeciesProperties handle, start = "0 yrs", # optional duration = "0 yrs", # reverse_time: [False, (bool)], # optional delta = 0, # optional stype = "addition" # or multiplication/epsilon_only shape = "square/pyramid/bell/filename" mass/magnitude/filename # give one offset = '0 yrs', # scale = 1, optional, # offset = option # reservoir = r-handle # optional, see below source = s-handle optional, see below display_precision = number, optional, inherited from Model register, )
Signals are cumulative, i.e., complex signals ar created by adding one signal to another (i.e., Snew = S1 + S2)
The optional scaling argument will only affect the y-column data of external data files
Signals are registered with a flux during flux creation, i.e., they are passed on the process list when calling the connector object.
if the filename argument is used, you can provide a filename which contains the data to be used in csv format. The data will be interpolated to the model domain, and added to the already existing data. The external data need to be in the following format
Time, Rate, delta value 0, 10, 12
i.e., the first row needs to be a header line
All time data in the csv file will be treated as realative time (i.e., the start time will be mapped to zero). The reverse keyword can be used to invert a signal that is read from a csv file.
Last but not least, you can provide an optional reservoir name. In this case, the signal will create a source as (signal_name_source) and the connection to the specified reservoir. If you build a complex signal do this as the last step. If you additionally provide a source name the connection will be made between the provided source (this can be useful if you use source groups).
This class has the following methods
Signal.repeat() Signal.plot() Signal.info()
The signal class provides the following data fields
- self.data.m which contains the interpolated signal
also available as self.m
- self.data.l which contain the interpolated isotope
data in the form of the light isotope also availavle as self.l If no isotope data is given, it is 0
- self.ed is the object reference for the externaldata
instance in cases wher data is read from a csv file
Isotopes: Delta values are always additive, regardless of signal type. The epsilon_only type ignores are flux values (the column must be present though), and applies the delta value to a given flux. This setting is most useful to dynamically control the fractionation factor of an output flux.
- repeat(start, stop, offset, times) None[source]
Create a new signal by repeating an existing signal.
Example:
new_signal = signal.repeat(start, # start time of signal slice to be repeated stop, # end time of signal slice to be repeated offset, # offset between repetitions times, # number of time to repeat the slice )
- signal_data
self.__map_signal__() returns a Flux object, so we need to remove this from the list of model Fluxes, with self.mo.lof.remove(self.data) since we do not use is as a Flux. Probably better to just create a vector object instead. FIXME sometime
- exception esbmtk.extended_classes.SignalError(message)[source]
Bases:
ExceptionCustom Error Class.
- class esbmtk.extended_classes.SinkProperties(**kwargs)[source]
Bases:
SourceSinkPropertiesA wrapper to setup a Sink object.
Example:
SinkProperties(name = "Burial", species = [SO42, H2S], delta = {"SO4": 10} )
- class esbmtk.extended_classes.SourceProperties(**kwargs)[source]
Bases:
SourceSinkPropertiesA wrapper to setup a Source object.
Example:
SourceProperties(name = "weathering", species = [SO42, H2S], delta = {"SO4": 10} )
- class esbmtk.extended_classes.SourceSinkProperties(**kwargs)[source]
Bases:
esbmtkBaseCreate Source/Sink Groups.
These are not actual reservoirs, but we stil need to have them as objects Example:
SinkProperties(name = "Pyrite", species = [SO42, H2S], )
where the first argument is a string, and the second is a reservoir handle
- exception esbmtk.extended_classes.SourceSinkPropertiesError(message)[source]
Bases:
ExceptionCustom Error Class.
- class esbmtk.extended_classes.SpeciesNoSet(**kwargs)[source]
Bases:
SpeciesBaseclass that makes no assumptions about the type of data.
I.e., all data will be left alone. The original class will calculate delta and concentration from mass an d and h and l. Since we want to use this class without a priory knowledge of how the reservoir arrays are being used we overwrite the data generated during initialization with the values provided in the keywords
- class esbmtk.extended_classes.VectorData(**kwargs: dict[str, any])[source]
Bases:
esbmtkBaseA simple container for 1-dimensional data.
Typically used for results obtained by postprocessing.
- class esbmtk.extended_classes.VirtualSpecies(**kwargs)[source]
Bases:
SpeciesA virtual reservoir.
Unlike regular reservoirs, the mass of a virtual reservoir depends entirely on the return value of a function.
Example:
VirtualSpecies(name="foo", volume="10 liter", concentration="1 mmol", species= , function=bar, a1 to a3 = to 3optional function arguments, display_precision = number, optional, inherited from Model, )
The concentration argument will be used to initialize the reservoir and to determine the display units.
The function definition follows the GenericFunction class. which takes a generic function and up to 6 optional function arguments, and will replace the mass value(s) of the given reservoirs with whatever the function calculates. This is particularly useful e.g., to calculate the pH of a given reservoir as function of e.g., Alkalinity and DIC.
The function must return a list of numbers which correspond to the data which describe a reservoir i.e., mass, light isotope, heavy isotope, delta, and concentration
In order to use this function we need first declare a function we plan to use with the generic function process. This function needs to follow this template:
def my_func(i, a1, a2, a3) -> tuple: # # i = index of the current max_timestep # a1 to a3 = optional function parameter. These must be present, # even if your function will not use it See above for details # calc some stuff and return it as # where m= mass, and l & h are the respective return [m, l, h, d, c] # isotopes. d denotes the delta value and # c the concentration # Use dummy value as necessary.
This class provides an update method to resolve cases where e.g., two virtual reservoirs have a circular reference. See the documentation of update().
- update(**kwargs) None[source]
Update GenericFunction parameters.
After the VirtualSpecies has been initialized. This is most useful when parameters have to reference other virtual reservoirs which do not yet exist, e.g., when two virtual reservoirs have a circular reference.
Example:
VR.update(a1=new_parameter, a2=new_parameter)
- class esbmtk.extended_classes.VirtualSpeciesNoSet(**kwargs)[source]
Bases:
ExternalCodeAlias to ensure backwards compatibility.
esbmtk.initialize_unit_registry module
Initialize a common unit registry.
esbmtk.model module
esbmtk: A general purpose Earth Science box model toolkit.
Copyright (C), 2020 Ulrich G. Wortmann
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
- exception esbmtk.model.FluxNameError(message)[source]
Bases:
ExceptionCustom Error Class for Flux lookup errors.
- class esbmtk.model.Model(**kwargs: dict[str, any])[source]
Bases:
esbmtkBaseEarth Science Box Model Toolkit (ESBMTK) Model class.
This class represents the main model framework for creating and running Earth science box models. It handles initialization of model parameters, management of reservoirs, fluxes, and species, and provides methods for running simulations and visualizing results.
The user-facing methods of the model class are:
Model_Name.info() - Display model information
Model_Name.save_data() - Save model data to files
Model_Name.plot([sb.DIC, sb.TA]) - Plot specified objects
Model_Name.save_state() - Save current model state
Model_Name.read_state() - Initialize with a previous model state
Model_Name.run() - Run the model simulation
Model_Name.list_species() - List all defined species
Model_Name.flux_summary() - Display flux information
Model_Name.connection_summary() - Display connection information
- Parameters:
**kwargs (dict) – A dictionary with key-value pairs for model configuration.
Examples
>>> esbmtkModel( ... name="Test_Model", # required ... stop="10000 yrs", # end time ... max_timestep="1 yr", # maximum time step ... element=["Carbon", "Sulfur"] ... )
Important Parameters
- namestr
The model name, e.g., “M”.
- mass_unitstr
Base mass unit for the model, default is “mol”.
- volume_unitstr
Volume unit for the model, default is “liter”.
- elementlist or str
One or more species names to include in the model.
- max_timestepstr
Limit automatic step size increase (time resolution of the model). Optional, defaults to model duration/100.
- m_typestr
Controls isotope calculation for the entire model. Options: “Not set” (default, isotopes calculated only for reservoirs with isotope keyword), “mass_only”, or “both” (overrides reservoir settings).
- offsetstr
Offset the time axis by the specified amount when plotting data. For display purposes only, does not affect model calculations.
- display_precisionfloat
Affects on-screen display of data and sets cutoff for graphical output.
- opt_k_carbonicint
- opt_pH_scaleint
pH scale setting: total=1, free=3.
- debug: bool
output debug information
- debug_equations_file: bool
write a debug version of the equations file.
- connection_summary(**kwargs) None[source]
Display a summary of model connections.
Prints information about all connections in the model or a filtered subset. For each connection, shows source and target, plus additional attributes if requested.
- Parameters:
**kwargs (dict) –
Optional keyword arguments:
- filter_bystr, default=None
If provided, only show connections containing this substring in their name.
- list_allbool, default=False
If True, print all connection attributes including internal ones.
- Returns:
This method prints to stdout but doesn’t return a value.
- Return type:
None
Examples
>>> model.connection_summary() # Show all connections
>>> model.connection_summary(filter_by="DIC") # Show only DIC connections
>>> model.connection_summary(list_all=True) # Show all connection details
- flux_summary(**kwargs: dict) list | None[source]
Display or return a filtered summary of model fluxes.
Creates a report of fluxes in the model, filtered by name patterns. Can either print the results to the console or return them as a list.
- Parameters:
**kwargs (dict) –
Optional keyword arguments:
- filter_bystr, default=””
Filter fluxes by name or partial name. Multiple words separated by spaces act as additional conditions - all words must appear in the flux name.
- excludestr, default=””
Exclude any fluxes whose names contain this string.
- return_listbool, default=False
If True, return a list of flux objects instead of printing to console.
- Returns:
If return_list=True, returns a list of flux objects matching the filters. If return_list=False, returns None (results are printed to console).
- Return type:
list or None
- Raises:
ModelError – If the deprecated “filter” parameter is used instead of “filter_by”.
Examples
# Display all fluxes containing “PO4” in their name >>> model.flux_summary(filter_by=”PO4”)
# Get a list of fluxes containing both “POP” and “A_sb” in their names >>> fluxes = model.flux_summary(filter_by=”POP A_sb”, return_list=True)
# Display fluxes containing “PO4” but not “H_sb” >>> model.flux_summary(filter_by=”PO4”, exclude=”H_sb”)
- get_delta_values() None[source]
Calculate reservoir masses and isotope delta values.
Updates the mass (m) and delta (d) values for all reservoirs in the model that have isotopes enabled. For each reservoir, the mass is calculated from concentration and volume, and the delta value is calculated using the get_delta_h function.
- Parameters:
None
- Returns:
The method modifies reservoir objects in place.
- Return type:
None
- info(**kwargs) None[source]
Display an overview of the model properties.
Prints information about the model instance including defined elements and their associated species.
- Parameters:
- Returns:
This method prints to stdout but doesn’t return a value.
- Return type:
None
- list_species() None[source]
Display all elements and species defined in the model.
Prints a hierarchical list of all elements in the model and their associated species properties. This provides a quick overview of the chemical species available in the model simulation.
- Parameters:
None
- Returns:
This method prints to stdout but doesn’t return a value.
- Return type:
None
Examples
>>> model.list_species() Currently defined elements and their species: Carbon Defined SpeciesProperties: DIC CO2 HCO3 CO3 Sulfur Defined SpeciesProperties: SO4 H2S
- plot(pl: list = None, **kwargs) tuple[source]
Plot model objects and save results to a file.
Creates a figure with subplots for each provided model object and renders their data using the object’s __plot__ method.
- Parameters:
pl (list or object, default=None) – A list of ESBMTK instances (e.g., reservoirs) to plot. If a single object is provided, it will be converted to a list. If None, an empty list will be used.
**kwargs (dict) –
Optional plotting parameters:
- fnstr, default=”{model_name}.pdf”
Filename to save the plot.
- titlestr, default=None
Title for the plot window.
- no_showbool, default=False
If True, don’t display or save the figure; instead return the plt, fig, and axes handles for manual customization.
- reverse_timebool, default=False
If True, reverse the time axis and adjust tick labels.
- blockingbool, default=True
If True, block execution until plot window is closed.
- Returns:
If no_show=True, returns (plt, fig, axes), otherwise None.
- Return type:
tuple or None
Examples
Basic usage:
>>> M.plot([sb.PO4, sb.DIC], fn='test.pdf')
Advanced usage with customization:
>>> from esbmtk import data_summaries >>> species_names = [M.DIC, M.TA, M.pH, M.CO3, M.zcc, M.zsat, M.zsnow, M.PO4] >>> box_names = [M.L_b, M.H_b, M.D_b] >>> pl = data_summaries(M, species_names, box_names, M.L_b.DIC) >>> pl += [M.CO2_At] >>> plt, fig, axs = M.plot( >>> pl, >>> fn="steady_state.pdf", >>> title="ESBMTK Preindustrial Steady State", >>> no_show=True, >>> )
- post_process_data(results) None[source]
Process solver results and update model data structures.
Takes the raw numerical results from the ODE solver and maps them back into the appropriate ESBMTK data structures (reservoirs, signals, fluxes). Also performs post-processing operations like interpolating signals, calculating derived quantities, and checking for pH stability.
- Parameters:
results (scipy.integrate._ivp.ivp.OdeResult) – The results object returned by the ODE solver, containing solution time points (t) and state variables (y)
- Returns:
The method updates model data structures in-place
- Return type:
None
Notes
The processing order is important: 1. Interpolate signals and external data to match solver time points 2. Map state variables to reservoir concentrations and masses 3. Update time vector and flux data 4. Perform specialized checks (pH stability) and calculations (carbonate chemistry)
- read_data(directory: str = './data') None[source]
Read model results from CSV files.
Loads previously saved model data from CSV files in the specified directory. Updates the model’s internal state with the loaded data.
- Parameters:
directory (str, default="./data") – Directory containing the saved model data files.
- Return type:
None
- read_state(directory='state')[source]
Initialize the model with the result of a previous.
For this to work, you will first need to issue a save_state command at then end of a model run. This will create the necessary data files to initialize a subsequent model run.
- run(**kwargs) None[source]
Run the model simulation.
Executes the model simulation by solving the system of ordinary differential equations (ODEs) that describe the model dynamics.
- Parameters:
**kwargs (dict) –
Optional keyword arguments to control the simulation:
- solverstr, default=”ode”
The solver type to use. Currently only “ode” is supported.
- methodstr, default=”BDF”
The integration method for the ODE solver. Options include “BDF” and “LSODA”.
- stypestr, default=”solve_ivp”
The solver function to use. Currently only “solve_ivp” is supported.
- Returns:
Results are stored in the model instance.
- Return type:
None
- Raises:
ModelError – If an unsupported solver type is specified.
SolverError – If the solver fails to find a solution.
Notes
After running, performance metrics (CPU time, memory usage) are printed.
- save_data(directory: str = './data') None[source]
Save all model results to CSV files.
Creates a directory (or recreates if it exists) and saves the full time series of all model components to separate CSV files. Each reservoir, signal, and vector data object will have its own CSV file.
- Parameters:
directory (str, default="./data") – Directory where data files will be saved. Will be created if it doesn’t exist and deleted if it already exists.
- Return type:
None
- Raises:
FileExistsError – If the directory exists and cannot be deleted.
- save_state(directory: str = 'state', prefix: str = 'state') None[source]
Save the current model state to files.
Saves only the last time step of each reservoir to files in the specified directory. This is similar to save_data() but focuses on capturing the current state rather than the full time series.
- Parameters:
- Return type:
None
- Raises:
FileExistsError – If the directory exists and cannot be deleted.
- sub_sample_data() None[source]
Reduce data resolution by subsampling time series data.
If the number of time points exceeds the desired number of data points, this method reduces the data resolution by taking every nth point (where n is the stride). This affects the time array and all data in reservoirs, virtual reservoirs, and fluxes.
The method is mainly used to reduce memory usage and file sizes when saving model output.
- Parameters:
None
- Returns:
The method modifies model data in place.
- Return type:
None
Notes
Subsampling only occurs if the stride is greater than 1. The time series boundaries (first two and last two points) are excluded from subsampling to avoid boundary effects.
- test_d_pH(reservoir_group: Species, time_vector: NDArrayFloat) None[source]
Test for large changes in pH between time steps.
Checks if the pH change between consecutive time steps exceeds 0.01 units, which could indicate numerical instability or unrealistic model behavior. Warnings are issued for any time steps where the threshold is exceeded.
- Parameters:
reservoir_group (Species) – The reservoir group containing a Hplus species to be checked
time_vector (NDArrayFloat) – Time vector as returned by the solver
- Returns:
Issues warnings if large pH changes are detected
- Return type:
None
Notes
This is a crude test since the solver interpolates between integration steps, so it may not catch all problems. It only identifies pH changes that exceed 0.01 units between the specific time points in the solution.
The pH is calculated as -log10([H+]), where [H+] is the hydrogen ion concentration.
- exception esbmtk.model.ModelError(message)[source]
Bases:
ExceptionCustom Error Class for Model-related errors.
esbmtk.ode_backend_2 module
esbmtk: A general purpose Earth Science box model toolkit.
Copyright (C), 2020 Ulrich G. Wortmann
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
- exception esbmtk.ode_backend_2.SourceIsotopeError(message)[source]
Bases:
ExceptionCustom Error Class.
- esbmtk.ode_backend_2.build_eqs_matrix(M: Model) tuple[NDArrayFloat, NDArrayFloat][source]
Build the coefficient matrix CM and Flux vector f.
So that we can solve dC_dt = C dot flux_values
- esbmtk.ode_backend_2.check_signal_2(rhs: str, rhs_l: str, c: Species2Species, icl: dict)[source]
Test if connection is affected by a signal.
- Parameters:
ex – equation string
c – connection object
icl – dict of reservoirs that have actual fluxes
- Returns:
(modified) equation string
- esbmtk.ode_backend_2.get_flux(flux: Flux, M: Model, R: list[float], icl: dict) tuple[str, str, list][source]
Create formula expressions that calculates the flux F.
Return the equation expression as string
- Parameters:
flux – The flux object for which we create the equation
M – The current model object
R – The list of initial conditions for each reservoir
icl – dict of reservoirs that have actual fluxes
- Returns:
A tuple where the first string is the equation for the total flux, and the second string is the equation for the flux of the light isotope
- esbmtk.ode_backend_2.get_ic(r: Species, icl: dict, isotopes=False) str[source]
Get initial condition in a reservoir.
If the reservoir is icl, return index expression into R.c. If the reservoir is not in the index, return the Species concentration a t=0
In both cases return these a string
If isotopes == True, return the pointer to the light isotope concentration
- Parameters:
r – A reservoir handle
icl – icl = dict[Species, list[int, int]] where reservoir indicates the reservoir handle, and the list contains the index into the reservoir data. list[0] = concentration list[1] concentration of the light isotope.
- Raises:
ValueError – get_ic: can’t find {r.full_name} in list of initial conditions
- Returns:
the string s which is the full_name of the reservoir concentration or isotope concentration
- esbmtk.ode_backend_2.get_initial_conditions(M: Model, rtol: float, atol_d: float = 1e-07) tuple[dict[str, float], dict, list, list, NDArrayFloat][source]
Get list of initial conditions.
This list needs to match the number of equations.
- Parameters:
Model – The model handle
rtol – relative tolerance for BDF solver.
atol_d – default value for atol if c = 0
- Returns:
lic = dict of initial conditions
- Returns:
icl = dict[Species, list[int, int]] where reservoir indicates the reservoir handle, and the list contains the index into the reservoir data. list[0] = concentration list[1] concentration of the light isotope.
- Returns:
cpl = list of reservoirs that use function to evaluate reservoir data
- Returns:
ipl = list of static reservoirs that serve as input
- Returns:
rtol = array of tolerence values for ode solver
We need to consider 3 types of reservoirs:
1) Species that change as a result of physical fluxes i.e. r.lof > 0. These require a flux statements and a reservoir equation.
2) Species that do not have active fluxes but are computed as a tracer, i.e.. HCO3. These only require a reservoir equation
3) Species that do not change but are used as input. Those should not happen in a well formed model, but we cannot exclude the possibility. In this case, there is no flux equation, and we state that dR/dt = 0
get_ic() will look up the index position of the reservoir_handle on icl, and then use this index to retrieve the correspinding value in R
Isotopes are handled by adding a second entry
- esbmtk.ode_backend_2.get_regular_flux_eq(flux: Flux, c: Species2Species, icl: dict, ind2, ind3, CM: NDArrayFloat, toc: tuple) tuple[str, str, list][source]
Create a string containing the equation for a regular connection.
Regular = fixed rate
- Parameters:
flux – flux instance
c – connection object
icl – dict of reservoirs that have actual fluxes
ind2 – indent 2 times
ind3 – indent 3 times
- Returns:
two strings, where the first describes the equation for the total flux, and the second describes the rate for the light isotope
- esbmtk.ode_backend_2.get_scale_with_concentration_eq(flux: Flux, c: Species2Species, cfn: str, icl: dict, ind2: str, ind3: str, CM: NDArrayFloat, toc: tuple) tuple[str, str, list][source]
Create equation string for flux.
The flux will scale with the concentration in the upstream reservoir
Example: M1_ConnGrp_D_b_to_L_b_TA_thc__F = M1.ConnGrp_D_b_to_L_b.TA_thc.scale * R[5]
- Parameters:
flux – Flux object
c – connection instance
cfn – full name of the connection instance
icl – dict[Species, list[int, int]] where reservoir indicates the reservoir handle, and the list contains the index into the reservoir data. list[0] = concentration list[1] concentration of the light isotope.
- Returns:
two strings with the respective equations for the change in the total reservoir concentration and the concentration of the light isotope
- esbmtk.ode_backend_2.get_scale_with_flux_eq(flux: Flux, c: Species2Species, cfn: str, icl: dict, ind2: str, ind3: str, CM: NDArrayFloat, toc: tuple)[source]
Equation defining a flux.
The flux will scale relative to the magnitude of another flux. If isotopes are used, use the isotope ratio of the upstream reservoir.
- Parameters:
flux – Flux object
c – connection instance
cfn – full name of the connection instance
icl – dict[Species, list[int, int]] where reservoir indicates the reservoir handle, and the list contains the index into the reservoir data. list[0] = concentration list[1] concentration of the light isotope.
- Returns:
two strings with the respective equations for the change in the total reservoir concentration and the concentration of the light isotope
- esbmtk.ode_backend_2.isotopes_regular_flux(f_m: str, c: Species2Species, icl: dict, ind3: str, ind2: str, CM: NDArrayFloat, toc: NDArrayFloat, flux: Flux) str[source]
Test if the connection involves any isotope effects.
- Parameters:
f_m – string with the flux name
c – connection object
icl – dict of reservoirs that have actual fluxes
ind2 – indent 2 times
ind3 – indent 3 times
- Returns equation string:
- esbmtk.ode_backend_2.isotopes_scale_concentration(f_m: str, c: Species2Species, icl: dict, ind3: str, ind2: str, CM: NDArrayFloat, toc: NDArrayFloat, flux: Flux) str[source]
Test if the connection involves any isotope effects.
- Parameters:
f_m – string with the flux name
c – connection object
icl – dict of reservoirs that have actual fluxes
ind2 – indent 2 times
ind3 – indent 3 times
- Returns equation string:
- esbmtk.ode_backend_2.isotopes_scale_flux(f_m: str, c: Species2Species, icl: dict, ind3: str, ind2: str, CM: NDArrayFloat, toc: NDArrayFloat, flux: Flux) str[source]
Test if the connection involves any isotope effects.
- Parameters:
f_m – string with the flux name
c – connection object
icl – dict of reservoirs that have actual fluxes
ind2 – indent 2 times
ind3 – indent 3 times
- Returns equation string:
- esbmtk.ode_backend_2.parse_esbmtk_input_data_types(d: any, r: Species, ind: str, icl: dict) str[source]
Parse esbmtk data types.
That are provided as arguments to external function objects, and convert them into a suitable string format that can be used in the ode equation file
- esbmtk.ode_backend_2.write_ef(eqs, ef: Species | ExternalFunction, icl: dict, rel: str, ind2: str, ind3: str, gpt: tuple) str[source]
Write external function call code.
- Parameters:
eqs – equation file handle
ef – external_function handle
icl – dict of reservoirs that have actual fluxes
rel – string with reservoir names returned by setup_ode
ind2 – indent 2 times
ind3 – indent 3 times
gpt – tuple with global paramaters
- Returns:
rel: modied string of reservoir names
- esbmtk.ode_backend_2.write_equations_3(M: Model, R: list[float], icl: dict, cpl: list, ipl: list, eqs_fn: str) str[source]
Write file that contains the ode-equations for the Model.
- Parameters:
Model – Model handle
R – tp.List of floats with the initial conditions for each reservoir
icl – dict of reservoirs that have actual fluxes
cpl – tp.List of reservoirs that have no fluxes but are computed based on other reservoirs
ipl – tp.List of reservoir that do not change in concentration
fn – str, filename
Returns: equationfile name
esbmtk.post_processing module
esbmtk: A general purpose Earth Science box model toolkit.
Copyright (C), 2020 Ulrich G. Wortmann
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
- esbmtk.post_processing.carbonate_system_1_pp(box_names: SpeciesGroup) None[source]
Calculate carbonate species.
Based on previously calculated Hplus, TA, and DIC concentrations.
LIMITATIONS: - Assumes all concentrations are in mol/kg - Assumes your Model is in mol/kg ! Otherwise, DIC and TA updating will not be correct.
Calculations are based off equations from: Boudreau et al., 2010, https://doi.org/10.1029/2009GB003654 Follows, 2006, doi:10.1016/j.ocemod.2005.05.004
- Parameters:
rg – A reservoirgroup object with initialized carbonate system
- esbmtk.post_processing.carbonate_system_2_pp(bn: Reservoir | list, export_fluxes: float | list, zsat_min: float = 200, zmax: float = 10000) None[source]
Calculate the fraction of carbonate that is dissolved.
- Parameters:
rg – Reservoir, e.g., M.D_b
export – export flux in mol/year
zsat_min – depth of mixed layer
zmax – depth of lookup table
This function then saves the data as
M.box_name.Hplus M.box_name.CO3 M.box_name.CO2aq M.box_name.pH M.box_name.zsat # top of lysocline M.box_name.zcc # bottom of lysocline M.box_name.zsnow # snow line M.box_name.Fburial # The CaCO3 burial flux (Export - dissolution) M.box_name.Fdiss # The CaCO3 dissolution flux
LIMITATIONS: - Assumes all concentrations are in mol/kg - Assumes your Model is in mol/kg ! Otherwise, DIC and TA updating will not be correct.
Calculations are based off equations from: Boudreau et al., 2010, https://doi.org/10.1029/2009GB003654 Follows, 2006, doi:10.1016/j.ocemod.2005.05.004
- esbmtk.post_processing.carbonate_system_3_pp(bn: Reservoir | list, export_fluxes: float | list, zsat_min: float = 200, zmax: float = 10000) None[source]
Calculate the fraction of carbonate that is dissolved.
- Parameters:
rg – Reservoir, e.g., M.D_b
export – export flux in mol/year
zsat_min – depth of mixed layer
zmax – depth of lookup table
This function then saves the data as
M.box_name.Hplus M.box_name.CO3 M.box_name.CO2aq M.box_name.pH M.box_name.zsat # top of lysocline M.box_name.zcc # bottom of lysocline M.box_name.zsnow # snow line M.box_name.Fburial # The CaCO3 burial flux (Export - dissolution) M.box_name.Fdiss # The CaCO3 dissolution flux
LIMITATIONS: - Assumes all concentrations are in mol/kg - Assumes your Model is in mol/kg ! Otherwise, DIC and TA updating will not be correct.
Calculations are based off equations from: Boudreau et al., 2010, https://doi.org/10.1029/2009GB003654 Follows, 2006, doi:10.1016/j.ocemod.2005.05.004
- esbmtk.post_processing.gas_exchange_fluxes(liquid_reservoir: Species, gas_reservoir: GasReservoir, pv: str)[source]
Calculate gas exchange fluxes for a given reservoir.
- Parameters:
liquid_reservoir – Species handle
gas_reservoir – Species handle
pv – piston velocity as string e.g., “4.8 m/d”
- Returns:
esbmtk.processes module
esbmtk: A general purpose Earth Science box model toolkit.
Copyright(C), 2020-2021 Ulrich G. Wortmann
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
- esbmtk.processes.gas_exchange(gas_c: float | tuple, liquid_c: float | tuple, gas_aq_c: float, p: tuple) float | tuple[source]
Calculate the gas exchange flux across the air sea interface.
including isotope effects.
- Parameters:
- Returns:
float | tuple – gas flux across the air/sea interface
Note that the sink delta is co2aq as returned by the carbonate VR
this equation is for mmol but esbmtk uses mol, so we need to
multiply by 1E3
The Total flux across interface dpends on the difference in either
concentration or pressure the atmospheric pressure is known, as gas_c, and
we can calculate the equilibrium pressure that corresponds to the dissolved
gas in the water as [CO2]aq/beta.
Conversely, we can convert the the pCO2 into the amount of dissolved CO2 =
pCO2 * beta
The h/c ratio in HCO3 estimated via h/c in DIC. Zeebe writes C12/C13 ratio
but that does not work. the C13/C ratio results however in -8 permil
offset, which is closer to observations
- esbmtk.processes.init_gas_exchange(c: Species2Species)[source]
Create ExternalCode instance for gas exchange reactions.
- Parameters:
c (Species2Species) – connection instance
- esbmtk.processes.init_weathering(c: Species2Species, pco2: float, pco2_0: float | str | Q_, area_fraction: float, ex: float, f0: float | str | Q_)[source]
Create a new external code instance.
- Parameters:
c – Species2Species
pco2 – float current pco2
pco2_0 – float reference pco2
ex – exponent
- Area_fraction:
float area/total area
- F0:
flux at pco2_0
- esbmtk.processes.weathering_isotopes(c_pco2: float | list[float], source_data: float | list[float], p: tuple) float | tuple[source]
Calculate weathering as a function of pCO2.
This is the same function as weathering_no_isotopes, but assumes that we weather a species (e.g., carbonate) that requires fluxes for both isotopes. data is a tuple.
- esbmtk.processes.weathering_isotopes_alpha(c_pco2: float | list[float], source_data: float | list[float], p: tuple) float | tuple[source]
Calculate weathering as a function of pCO2.
This is the same function as weathering_no_isotopes, but assumes that we weather a species (e.g., carbonate) that requires fluxes for both isotopes. data is a tuple. s_c = source mass s_l = source mass of light isotope
- esbmtk.processes.weathering_isotopes_delta(c_pco2: float | list[float], source_data: float | list[float], p: tuple) float | tuple[source]
Calculate weathering as a function of pCO2.
This is the same function as weathering_no_isotopes, but assumes that we weather a species (e.g., carbonate) that requires fluxes for both isotopes. data is a tuple.
- esbmtk.processes.weathering_no_isotopes(c_pco2: float | list[float], source_data: float | list[float], p: tuple) float | tuple[source]
Calculate weathering as a function of pCO2.
- Parameters:
- Returns:
float – a float value for the weathering flux
Explanation
———–
If the model uses isotopes, the function expects the concentration
values for the total mass and the light isotope as a list, and
will simiraly return the flux as a list of total flux and flux of
the light isotope.
The flux itself is calculated as – F_w = area_fraction * f0 * (pco2/pco2_0)**ex
esbmtk.sealevel module
esbmtk: A general purpose Earth Science box model toolkit.
Copyright (C), 2020 Ulrich G. Wortmann
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
- esbmtk.sealevel.get_box_geometry_parameters(box) None[source]
Calculate box volume and area from the data in box.
- Parameters:
box – list or dict with the geometry parameters
- Fraction:
0 to 1 to specify a fractional part (i.e., Atlantic)
If box is a list the first entry is the upper depth datum, the second entry is the lower depth datum, and the third entry is the fraction of ocean area. E.g., to specify the upper 200 meters of the entire ocean, you would write:
geometry=[0, -200, 1]
the corresponding ocean volume will then be calculated by the calc_volume method in this case the following instance variables will also be set:
self.volume in model units (usually liter)
self.are:a surface area in m^2 at the upper bounding surface
self.sed_area: area of seafloor which is intercepted by this box.
self.area_fraction: area of seafloor which is intercepted by this relative to the total ocean floor area
It is also possible to specify volume and area explicitly. In this case provide a dictionary like this:
box = {"area": "1e14 m**2", # surface area in m**2 "volume": "3e16 m**3", # box volume in m**3 "ta": "4e16 m**2", # reference area }
- esbmtk.sealevel.grid_area(lat: float, size: float) float[source]
Calculate the area of a rectangular area of size = 1 deg.
At a given lat-long position.
- class esbmtk.sealevel.hypsometry(**kwargs)[source]
Bases:
esbmtkBaseCalculate hypsometric data.
Depth interval between -6000 to 1000 meter (relative to sealevel)
- Invoke as:
hyspometry(name=”hyp”)
- area_dz(upper: float, lower: float) float[source]
Calculate the area between two elevation datums.
- Parameters:
- Returns:
area in m^2
- Return type:
- Raises:
ValueError – if elevation datums are outside the defined interval
- get_lookup_table_area() ndarray[tuple[Any, ...], dtype[float64]][source]
Return the area values between 0 and max_depth as 1-D array.
- get_lookup_table_area_dz() ndarray[tuple[Any, ...], dtype[float64]][source]
Return the are_dz values between 0 and max_depth as 1-D array.
- read_data(fn: str) None[source]
Read the hypsometry data from a pickle file.
If the pickle file is missing, create it from the csv data save the hypsometry data as a numpy array with elevation, area, and area_dz in self.hypdata
- Parameters:
fn (str) – file name to read from
- Raises:
The file structure must follow this scheme –
Elevation[m], Cumsum –
-11000, 0 –
- esbmtk.sealevel.process_slice(start: int, end: int, lat: ndarray[tuple[Any, ...], dtype[float64]], grid: ndarray[tuple[Any, ...], dtype[float64]], dz: int, elevation_minimum: float, elevation_maximum: float, elevations: ndarray[tuple[Any, ...], dtype[float64]], dx: float) ndarray[tuple[Any, ...], dtype[float64]][source]
Take grid area in to account when calculating the elevation count.
As earth is elliptical, the grid area for same latitude and longitude gap is different, the function adjust the weight for each slice and return the weighted elevation count array for each slice.
- Parameters:
start (int) – start index of the slice
end (int) – end index of the slice
lat (NDArrayFloat) – latitude array
grid (NDArrayFloat) – grid of elevation data
dz (int) – elevation interval
elevation_minimum (int) – minimum elevation in the grid
elevation_maximum (int) – maximum elevation in the grid
elevations (NDArrayFloat) – elevation array
dx (float) – grid resolution in degrees
- Returns:
elevation count array for each latitudinal slice
- Return type:
NDArrayFloat
- esbmtk.sealevel.slice_count(start: int, end: int, weight: ndarray[tuple[Any, ...], dtype[float64]], grid: ndarray[tuple[Any, ...], dtype[float64]], elevation_minimum: float, elevation_maximum: float, elevations: ndarray[tuple[Any, ...], dtype[float64]], dz: int) ndarray[tuple[Any, ...], dtype[float64]][source]
Generate elevation count array for each latitudinal slice.
Summarizing the count of elevation values in each elevation interval in current slice.
- Parameters:
start (int) – start index of the slice
end (int) – end index of the slice
weight (NDArrayFloat) – weight array for each latitudinal slice
grid (NDArrayFloat) – grid of all the data about to be sliced
elevation_minimum (int) – minimum elevation
elevation_maximum (int) – maximum elevation
elevations (NDArrayFloat) – elevation array
dz (int) – elevation interval
- Returns:
elevation count array for each latitudinal slice
- Return type:
NDArrayFloat
esbmtk.seawater module
esbmtk: A general purpose Earth Science box model toolkit.
Copyright(C), 2020-2021 Ulrich G. Wortmann
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
- class esbmtk.seawater.SeawaterConstants(**kwargs: dict[str, str])[source]
Bases:
esbmtkBaseProvide basic seawater properties as a function of T, P and Salinity.
Since we cannot know if TA and DIC have already been specified, creating the instance uses standard seawater composition. Updating/Setting TA & DIC does not recalculate these values after initialization, unless you explicitly call the update_parameters() method.
Example:
Seawater(name="SW", register=M # model handle temperature = optional in C, defaults to 25, salinity = optional in psu, defaults to 35, pressure = optional, defaults to 0 bars = 1atm, pH = 8.1, # optional )
Results are always in mol/kg
Acess the values “dic”, “ta”, “ca”, “co2”, “hco3”, “co3”, “boron”, “boh4”, “boh3”, “oh”, “ca2”, “so4”,”hplus”, as SW.co3 etc.
This method also provides “K0”, “K1”, “K2”, “KW”, “KB”, “Ksp”, “Ksp0”, “KS”, “KF” and their corresponding pK values, as well as the density for the given (P/T/S conditions)
useful methods:
SW.show() will list values
After initialization this class provides access to each value the following way
instance_name.variable_name
Since this class is just a frontend to PyCO2SYS, it is easy to add parameters that are supported in PyCO2SYS. See the update_parameter() method.
- calc_solubility_term(S, T, A1, A2, A3, A4, B1, B2, B3) float[source]
Calculate solubility of given gas species.
- co2_solubility_constant() None[source]
Calculate the solubility of CO2 at a given temperature and salinity.
The value for K0 is taken from pyCO2sys which is in mol/kg-SW/atm esbmtk uses mol/(t atm). pyCO2sys follows Weiss, R. F., Marine Chemistry 2:203-215, 1974.
- get_density(S, TC, P) float[source]
Calculate density as function of T, P, S.
- Parameters:
S – salinity in PSU
TC – temp in C
P – pressure in bar
- Returns rho:
in kg/m**3
- o2_solubility_constant() None[source]
Calculate the solubility of CO2 at a given temperature and salinity.
Coefficients after Sarmiento and Gruber 2006 which includes corrections for non ideal gas behavior
Parameters Ai & Bi from Tab 3.2.2 in Sarmiento and Gruber 2006
The result is in mol/(l atm)
- water_vapor_partial_pressure() None[source]
Calculate the water vapor partial pressure at sealevel (1 atm).
As a function of temperature and salinity. Eq. Weiss and Price 1980 doi:10.1016/0304-4203(80)90024-9
Since we assume that we only use this expression at sealevel, we drop the pressure term
The result is in p/1atm (i.e., a percentage)
esbmtk.species_definitions module
esbmtk: A general purpose Earth Science box model toolkit.
Copyright(C), 2020 Ulrich G. Wortmann
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
- esbmtk.species_definitions.Boron(model)[source]
Element property definitions.
- Parameters:
model (Model) – Model instance
- esbmtk.species_definitions.Calcium(model)[source]
Element property definitions.
- Parameters:
model (Model) – Model instance
- esbmtk.species_definitions.Carbon(model)[source]
Element property definitions.
- Parameters:
model (Model) – Model instance
- esbmtk.species_definitions.Hydrogen(model)[source]
Element property definitions.
- Parameters:
model (Model) – Model instance
- esbmtk.species_definitions.Nitrogen(model)[source]
Element property definitions.
- Parameters:
model (Model) – Model instance
- esbmtk.species_definitions.Oxygen(model) None[source]
Element property definitions.
- Parameters:
model (Model) – Model instance
- esbmtk.species_definitions.Phosphor(model)[source]
Element property definitions.
- Parameters:
model (Model) – Model instance
esbmtk.utility_functions module
esbmtk: A general purpose Earth Science box model toolkit.
Copyright (C), 2020 Ulrich G. Wortmann
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
- exception esbmtk.utility_functions.ScaleError(message)[source]
Bases:
ExceptionCustom Error Class.
- esbmtk.utility_functions.add_to(my_list, e)[source]
Add element e to list l, but check if the entry already exist.
If so, throw exception. Otherwise add
- esbmtk.utility_functions.build_concentration_dicts(cd: dict, bg: dict) dict[source]
Build a dict which can be used by create_reservoirs.
- Parameters:
bg – dict where the box_names are dict keys.
cd – dictionary
with the following format:
cd = { # species: [concentration, isotopes] PO4: [Q_("2.1 * umol/liter"), False], DIC: [Q_("2.1 mmol/liter"), False], }
This function returns a new dict in the following format
# box_names: [concentrations, isotopes] d= {“bn”: [{PO4: .., DIC: ..},{PO4:False, DIC:False}]}
- esbmtk.utility_functions.build_ct_dict(d: dict, p: dict) dict[source]
Build a connection dictionary.
From a dict containing connection keys, and a dict containing connection properties. This is most useful for connections which a characterized by a fixed rate but apply to many species. E.g., mixing fluxes in a complex model etc.
- esbmtk.utility_functions.calc_volumes(bg: dict, M: any, h: any) list[source]
Calculate volume contained in a given depth interval.
bg is a dictionary in the following format:
bg={ "hb": (0.1, 0, 200), "sb": (0.9, 0, 200), }
where the key must be a valid box name, the first entry of the list denoted the areal extent in percent, the second number is upper depth limit, and last number is the lower depth limit.
M must be a model handle h is the hypsometry handle
The function returns a list with the corresponding volumes
- esbmtk.utility_functions.check_for_NaN(a: ndarray[tuple[Any, ...], dtype[float64]]) bool[source]
Test if a contains NaN values.
- esbmtk.utility_functions.check_for_quantity(quantity, unit)[source]
Check if keyword is quantity or string an convert as necessary.
If input is a string, convert string into a quantity
If input is a quantity, do nothing
if input is a number, convert to default quantity
- Parameters:
- Returns:
Returns a Quantity
- Return type:
Q\_
- Raises:
ValueError – if keywword is neither number, str or quantity
- esbmtk.utility_functions.convert_to_lists(d: dict, my_list: int) dict[source]
Expand mixed dict entries.
(i.e. list and single value) such that they are all lists of equal length
- esbmtk.utility_functions.create_bulk_connections(ct: dict, M: Model, mt: int = '1:1') dict[source]
Create connections from a dictionary.
The dict can have the following format:
mt = mapping type. See below for explanation
# na: names, tuple or str. If lists, all list elements share the same properties # sp: species list or species # ty: type, str # ra: rate, Quantity # sc: scale, Number # re: reference, optional # al: epsilon, optional # de: delta, optional # bp: bypass, see scale_with_flux # si: signal # mx: True, optional defaults to False. If set, it will create forward and backward fluxes (i.e. mixing)
There are 6 different cases how to specify connections
- Case 1 One connection, one set of parameters
ct1 = {“sb2hb”: {“ty”: “scale”, ‘ra’….}}
- Case 2 One connection, one set of instructions, one subset with multiple parameters
This will be expanded to create connections for each species ct2 = {“sb2hb”: {“ty”: “scale”, “sp”: [“a”, “b”]}}
- Case 3 One connection complete set of multiple characters. Similar to case 2,
but now all parameters are given explicitly ct3 = {“sb2hb”: {“ty”: [“scale”, “scale”], “sp”: [“a”, “b”]}}
- Case 4 Multiple connections, one set of parameters. This will create
identical connection for “sb2hb” and “ib2db” ct4 = {(“sb2hb”, “ib2db”): {“ty”: “scale”, ‘ra’: …}}
- Case 5 Multiple connections, one subset of multiple set of parameters. This wil
- create a connection for species ‘a’ in sb2hb and with species ‘b’ in ib2db
ct5 = {(“sb2hb”, “ib2db”): {“ty”: “scale”, “sp”: [“a”, “b”]}}
- Case 6 Multiple connections, complete set of parameters of multiple parameters
Same as case 5, but now all parameters are specified explicitly ct6 = {(“sb2hb”, “ib2db”): {“ty”: [“scale”, “scale”], “sp”: [“a”, “b”]}}
The default interpretation for cases 5 and 6 is that each list entry corresponds to connection. However, sometimes we want to create multiple connections for multiple entries. In this case provide the mt=’1:N’ parameter which will create a connection for each species in each connection group. See the below example.
It is easy to shoot yourself in the foot. It is best to try the above first with some simple examples, e.g.,
from esbmtk import expand_dict ct2 = {“sb2hb”: {“ty”: “scale”, “sp”: [“a”, “b”]}}
It is best to use the show_dict function to verify that your input dictionary produces the correct results!
- esbmtk.utility_functions.create_connection(n: str, p: dict, M: Model) None[source]
Create a connection group.
It is assumed that all rates are in liter/year or mol per year. This may not be what you want or need.
- Parameters:
n – a connection key. if the mix flag is given interpreted as mixing a connection between sb and db and thus create connections in both directions
p – a dictionary holding the connection properties
M – the model handle
- esbmtk.utility_functions.data_summaries(M: Model, species_names: list, box_names: list, register_with='None') list[source]
Group results by species and Reservoirs.
- Parameters:
M – model instance
species_names – tp.List of species instances
box_names – tp.List of Reservoir instances
register_with – defaults to M
- Returns pl:
a list of datafield instances to be plotted
Note: because pl is a list, you need to expand it before using it in the plot method. Either use
M.plot(pl)
or M.plot([*pl])
If you call a plot with many subfigures, use pl like this:
M.plot([o1, o2, *pl])
- esbmtk.utility_functions.dict_alternatives(d: dict, e: str, a: str) any[source]
Use dictionary =d=, an expression =e=, and an alternative expression =a=.
Returns the value associated with either =a= or =e= in the dictionary =d=.
- Parameters:
d – A dictionary.
e – The first expression to check.
a – The alternative expression to check.
- Returns r:
The value associated with either =a= or =e= in the dictionary =d=.
- Raises:
ValueError – If neither =a= nor =e= are found in the dictionary.
- esbmtk.utility_functions.expand_dict(d: dict, mt: str = '1:1') int[source]
Determine dict structure.
in case we have mutiple connections with mutiple species, the default action is to map connections to species (t = ‘1:1’). If you rather want to create mutiple connections (one for each species) in each connection set t = ‘1:N’
- esbmtk.utility_functions.find_matching_fluxes(my_list: list, filter_by: str, exclude: str) list[source]
Loop over all reservoirs in my_list.
And extract the names of all fluxes which match the filter string. Return the list of names (not objects!)
- esbmtk.utility_functions.find_matching_strings(s: str, fl: list[str]) bool[source]
Test if all elements of fl occur in s.
Return True if yes,otherwise False
- esbmtk.utility_functions.fractionate_with_epsilon(epsilon: float, source_c: float, source_l: float, sink_c: float) float[source]
Calculate how a given epsilon would affect the downstream isotoe ratio.
- esbmtk.utility_functions.gen_dict_entries(M: Model, **kwargs)[source]
Find all fluxes that contain the reference string.
Create a new Species2Species instance that connects the flux matching ref_id, with a flux matching target_id. The function will a tuple containig the new connection keys that can be used by the create bulk_connection() function. The second return value is a list containing the reference fluxes.
The optional inverse parameter, can be used where in cases where the flux direction needs to be reversed, i.e., the returned key will not read sb_to_dbPOM, but db_to_sb@POM
- Parameters:
M – Model or list
kwargs – keyword dictionary, known keys are ref_id, and raget_id, inverse
- Return f_list:
tp.List of fluxes that match ref_id
- Return k_tuples:
tuple of connection keys
- esbmtk.utility_functions.get_connection_keys(f_list: set, ref_id: str, target_id: str, inverse: bool, exclude: str) list[str][source]
Extract connection keys from set of flux names.
Replace ref_id with target_id so that the key can be used in create_bulk_connnections()
- Parameters:
f_list – a set with flux objects
ref_id – string with the reference id
target_id – string with the target_id
inverse – Bool, optional, defaults to false
- Return cnc_l:
a list of connection keys (str)
The optional inverse parameter, can be used where in cases where the flux direction needs to be reversed, i.e., the returned key will not read sb2db@POM, but db2s@POM
- esbmtk.utility_functions.get_delta(li: ndarray[tuple[Any, ...], dtype[float64]], h: ndarray[tuple[Any, ...], dtype[float64]], r: float) ndarray[tuple[Any, ...], dtype[float64]][source]
Calculate the delta from the mass of light and heavy isotope.
- Parameters:
l – light isotope mass/concentration
h – heavy isotope mass/concentration
r – reference ratio
:return : delta
- esbmtk.utility_functions.get_delta_from_concentration(c, li, r)[source]
Calculate the delta from the mass of light and heavy isotope.
- Parameters:
c – total mass/concentration
l – light isotope mass/concentration
r – reference ratio
- esbmtk.utility_functions.get_delta_h(R) float[source]
Calculate the delta of a flux or reservoir.
- Parameters:
R – Species or Flux handle
returns d as vector of delta values R.c = total concentration R.l = concentration of the light isotope
- esbmtk.utility_functions.get_imass(m: float, d: float, r: float) [<class 'float'>, <class 'float'>][source]
Calculate the isotope masses from bulk mass and delta value.
Arguments are m = mass, d= delta value, r = abundance ratio species
- esbmtk.utility_functions.get_l_mass(m: float, d: float, r: float) float[source]
Get mass of light isotope.
- Parameters:
m – mass or concentration
d – delta value
r – isotopic reference ratio
return mass or concentration of the light isotopeb
- esbmtk.utility_functions.get_longest_dict_entry(d: dict) int[source]
Get length of each item in the connection dict.
- esbmtk.utility_functions.get_name_only(o: any) any[source]
Test if item is an esbmtk type.
If yes, extract the name
- esbmtk.utility_functions.get_new_ratio_from_alpha(ref_mass: float, ref_l: float, a: float) [<class 'float'>, <class 'float'>][source]
Calculate the effect of the istope fractionation factor alpha.
For the ratio between the mass of the light isotope devided by the total mass
Note that alpha needs to be given as fractional value, i.e., 1.07 rather than 70 (i.e., (alpha-1) * 1000
- esbmtk.utility_functions.get_object_from_list(name: str, my_list: list) any[source]
Match a name to a list of objects.
Return the object
- esbmtk.utility_functions.get_object_handle(res: list, M: Model)[source]
Test if the key is a global reservoir handle.
Or exists in the model namespace
- Parameters:
res – tp.List of strings, or reservoir handles
M – Model handle
- esbmtk.utility_functions.get_plot_layout(obj)[source]
Select a row, column layout.
Based on the number of objects to display. The expected argument is a reservoir object which contains the list of fluxes in the reservoir
- esbmtk.utility_functions.get_reservoir_reference(k: str, M: Model) tuple[source]
Get SpeciesProperties and Species handles.
- Parameters:
- Returns:
Species2Species, SpeciesProperties
- Return type:
- Raises:
ValueError – If reservoir_name is not of type ConnectionProperties or Species2Species
- esbmtk.utility_functions.get_simple_list(my_list: list) list[source]
Return a list.
Which only has the full name rather than all the object properties
- esbmtk.utility_functions.get_string_between_brackets(s: str) str[source]
Parse string and extract substring between square brackets.
- esbmtk.utility_functions.get_sub_key(d: dict, i: int) dict[source]
Take a dict which has where the value is a list.
Return the key with the n-th value of that list
- esbmtk.utility_functions.initialize_reservoirs(M: Model, box_dict: dict)[source]
Initialize one or more reservoirs.
Based on the data in box_dict (see the example below).
- Parameters:
- Returns:
list of all Species objects in box_dict
- Return type:
tp.List
- Raises:
ValueError – If there are no Species objects in the dictionary
Example:
box_parameters = { # name: [[ud, ld ap], T, P, S] # Atlantic Ocean "M.A_sb": { "g": [0, -100, A_ap], "T": 20, "P": 5, "S": 34.7, "c": {M.PO4: "2.1 mmol/kg", M.DIC: "2.21 mmol/kg", M.TA: "2.31 mmol/kg", } species_list = initialize_reservoirs(M, box_parameters)
Note: the first entry in the box_parameters dict must be a regular reservoir, not a Source or Sink.
- esbmtk.utility_functions.is_name_in_list(n: str, my_list: list) bool[source]
Test if an object name is part of the object list.
- esbmtk.utility_functions.list_fluxes(self, name, i) None[source]
Echo all fluxes in the reservoir to the screen.
- esbmtk.utility_functions.make_dict(keys: list, values: list) dict[source]
Create a dictionary from a list and value, or from two lists.
- esbmtk.utility_functions.map_units(obj: any, v: any, *args) float[source]
Parse v to see if it is a string.
If yes, map to quantity. parse v to see if it is a quantity, if yes, map to model units and extract magnitude, assign mangitude to return value if not, assign value to return value
- Parameters:
obj – connection object
v – input string/number/quantity
- Args:
tp.List of model base units
- Returns:
number
- Raises:
ScaleError – if input cannot be mapped to a model unit
- esbmtk.utility_functions.phc(c: float) float[source]
Calculate concentration as pH.
c can be a number or numpy array
- esbmtk.utility_functions.plot_geometry(noo: int)[source]
Define plot geometry based on number of objects to plot.
- esbmtk.utility_functions.register_new_flux(ec, model_object, dict_key, dict_value) list[source]
Register a new flux object with a Species2Species instance.
- esbmtk.utility_functions.register_return_values(ef: ExternalFunction, rg) None[source]
Register the return values of an external function instance.
- Parameters:
- Raises:
ValueError – If the return value type is undefined
Check the return values of external function instances, –
and create the necessary reservoirs, fluxes, or connections –
if they are missing. –
These fluxes are not associated with a connection Object –
so we register the source/sink relationship with the –
reservoir they belong to. –
This fails for GasReservoir since they can have a 1:many –
relatioship. The below is a terrible hack, it would be –
better to express this with several connection –
objects, rather than overloading the source attribute of the –
GasReservoir class. –
- esbmtk.utility_functions.register_user_function(M: Model, lib_name: str, func_name: str | list) None[source]
Register user supplied library and function with the model.
- esbmtk.utility_functions.reverse_tick_labels_factory(max_tick_value)[source]
Reverse the label of the x-axis ticks but not the data.
Usage:
From matplotlib.ticker import FuncFormatter ax.xaxis.set_major_formatter(FuncFormatter(reverse_tick_labels_factory(x_max)))
where xmax = max value on the x-axis
- esbmtk.utility_functions.rmtree(f) None[source]
Delete file or files if file is directory.
- Parameters:
f – pathlib path object
- esbmtk.utility_functions.set_y_limits(ax: Axes, obj: any) None[source]
Prevent the display or arbitrarily small differences.
- esbmtk.utility_functions.show_dict(d: dict, mt: str = '1:1') None[source]
Show dict entries in an organized manner.
- esbmtk.utility_functions.sort_by_type(my_list: list, t: list, m: str) list[source]
Divide a list by type into new lists.
This function will return a list and it is up to the calling code to unpack the list
l is list with various object types t is a list which contains the object types used for sorting m is a string for the error function
- esbmtk.utility_functions.split_key(k: str, M: any) any | any | str[source]
Split the string k with letters _to_.
Test if optional id string is present
esbmtk.version module
Get esbmtk version information.
This is in a dedicated file to avoid circular imports during initialization