microbenthos.model package¶
Submodules¶
microbenthos.model.equation module¶
-
class
microbenthos.model.equation.
ModelEquation
(model, varpath, coeff=1, track_budget=False)[source]¶ Bases:
object
Class that handles the creation of partial differential equations for a transient variable of the model
-
__init__
(model, varpath, coeff=1, track_budget=False)[source]¶ Initialize the model equation for a given variable
- Parameters
model (
MicroBenthosModel
) – model this belongs tovarpath (str) – Model path of the equation variable (example: “env.oxygen”)
-
model
¶ the model instance this equation belongs to
-
varpath
¶ the path (str) to the equation variable
-
var
¶ The equation variable object (
Variable
)
-
source_formulae
¶ container (dict) of the formulae of the sources (sympy expressions)
-
source_exprs
¶ container (dict) of the expressions of the sources (fipy variable binOp)
-
source_terms
¶ container (dict) of the fipy equation terms (explicit & implicit) of the sources
-
source_coeffs
¶ the coefficients in the equation for the sources
-
sources_total
¶ The additive sum of the values in
source_exprs
-
diffusion_def
¶ type : (str, float)
The model path to the diffussion coeff and a numeric coefficient to multiply in the equation
-
obj
¶ the fipy term that is used in the model full_eqn
-
finalized
¶ flag to indicate if the equation has been finalized
-
Tracked
¶ namedtuple definition for tracked fields: (‘time_step’, ‘var_expected’, ‘var_actual’, ‘sources_change’, ‘transport_change’)
-
finalize
()[source]¶ Call this to setup the equation. Once this is called, no more terms can be added.
This does:
self.obj = self.term_transient == sum(self.RHS_terms)
- Raises
RuntimeError – if no
term_transient
defined or no RHS terms defined
-
property
term_transient
¶ dv/dt
- Type
The transient term of the equation
-
_get_term_obj
(path)[source]¶ Get the model object at the path and return a usable fipy type
- Parameters
path (str) – dotted path in the model store
- Returns
Variable |
fipy.terms.binaryTerm._BinaryTerm
-
property
term_diffusion
¶ The diffusion term for the equation
- Returns
Instance of
fipy.DiffusionTerm
-
property
RHS_terms
¶ The right hand side terms of the equation
- Returns
A list of terms, with the first one being
term_diffusion
, followed by the values insource_terms
.
-
snapshot
(base=False)[source]¶ Return a state dictionary of the equation, with the structure
- “sources”
“metadata”: source paths and coefficients
“data”: the net rate of the combined sources
- “diffusion”
metadata: dict(
diffusion_def
)
- “transient”
- “metadata”:
varpath
: transient term coeff
- “tracked_budget” (if
track_budget
is True) var_expected: data: integrated density of variable from tracked changes
var_actual: data: integrated density of variable
time_step: data: the time step duration
sources_change: data: integrated rate of combined sources over the time step
transport_change: data: change in variable quantity due to mass transport
- “tracked_budget” (if
- “metadata”
“variable”:
varpath
- Returns
dict – A dictionary of the equation state
- Raises
RuntimeError – if the equation is not yet finalized
-
restore_from
(state, tidx)[source]¶ If “tracked_budget” is in the state, then set the values on the instance
-
sources_rate
()[source]¶ Estimate the rate of change of the variable quantity caused by source terms.
- Returns
PhysicalField – The integrated quantity of the sources
-
transport_rate
()[source]¶ Estimate the rate of change of the variable quantity caused by transport at the domain boundaries
- Returns
PhysicalField – The integrated quantity of the transport rate
-
var_quantity
()[source]¶ Calculate the integral quantity of the variable in the domain
- Returns
PhysicalField – depth integrated amount
-
update_tracked_budget
(dt)[source]¶ Update the tracked quantities for the variable, sources and transport
- Parameters
dt (PhysicalField) – the time step
Note
This is not a very accurate way to measure it, because the boundaries conditions keep the value at the domain boundaries constant, and so is not a true measure of the equation change in the time step. However, it should provide an order of magnitude metric for the accuracy of the numerical approximation in solving the equation.
-
property
track_budget
¶ Flag to indicate if the variable quantity should be tracked.
When this is set, the variable quantity in the domain is
tracked
throughupdate_tracked_budget()
.- Returns
bool – Flag state
-
microbenthos.model.model module¶
-
class
microbenthos.model.model.
MicroBenthosModel
(**kwargs)[source]¶ Bases:
microbenthos.utils.create.CreateMixin
The theater where all the actors of microbenthos come together in a concerted play driven by the clock. This is the class that encapsulates the nested structure and function of the various entities, variables, microbial groups and binds them with the domain.
-
schema_key
= 'model'¶
-
__init__
(**kwargs)[source]¶ Initialize the model instance.
- Parameters
**kwargs – definition dictionary assumed to be validated by
MicroBenthosSchemaValidator
.
See also
-
env
¶ container (dict) of the environmental variables and processes
-
equations
¶ container (dict) of the
ModelEquation
defined in the model
-
add_formula
(name, vars, expr)[source]¶ Add a formula to the sympy namespace of
Expression
- Parameters
Example
name = "optimum_response" variables = "x Ks Ki" expr = "x / (x + Ks) / (1 + x/Ki)"
-
property
domain
¶ The model domain, typically
SedimentDBLDomain
-
create_entity_from
(defdict)[source]¶ Create a model entity from dictionary, and set it up with the model and domain.
See Also:
Entity.from_dict()
- Returns
The entity created
-
_create_entity_into
(target, name, defdict)[source]¶ Create an entity from its definition dictionary and store it into the target dictionary
-
_setup
(**definition)[source]¶ Set up the model instance from the definition dictionary, which is assumed to be validated by
MicroBenthosSchemaValidator
.
-
entities_setup
()[source]¶ Check that the model entities are setup fully, if not attempt it for each entity in
env
and :attr:.microbes`
-
property
all_entities_setup
¶ Flag that indicates if all entities have been setup
-
snapshot
(base=False)[source]¶ Create a snapshot of the model state.
This method recursively calls the
snapshot()
method of all contained entities, and compiles them into a nested dictionary. The dictionary has the structure of the model, as well as nodes with the numeric data and metadata. The state of the model can then be serialized, for example throughsave_snapshot()
, or processed through various exporters (inexporters
).- Parameters
base (bool) – Whether the entities should be converted to base units?
- Returns
dict – model state snapshot
See also
save_snapshot()
for details about the nested structure of the state and how it is processed.
-
restore_from
(store, time_idx)[source]¶ Restore the model entities from the given store
- Parameters
store (
Group
) – The root of the model data storetime_idx (int) – the index along the time series to restore. Uses
syntax (python) –
:param : :param i.e first element is 0: :param second is 1: :param last element is -1: :param etc.:
Warning
This is a potentially destructive operation! After checking that we
can_restore_from()
the given store,truncate_model_data()
is called. This method modifies the data structure in the supplied store by truncating the datasets to the length of the time series as determined from time_idx. Only in the case oftime_idx=-1
it may not modify the data.- Raises
TypeError – if the store data is not compatible with model
Exception – as raised by
truncate_model_data()
.
See also
check_compatibility()
to see how the store is assessed to be compatible with the instantiated model.truncate_model_data()
for details on how the store is truncated.
-
can_restore_from
(store)[source]¶ Check if the model can be resumed from the given store
- Parameters
store (
hdf.Group
) – The root of the model data store- Returns
True if it is compatible
-
add_equation
(name, transient, sources=None, diffusion=None, track_budget=False)[source]¶ Create a transient reaction-diffusion equation for the model.
The term definitions are provided as (model_path, coeff) pairs to be created for the transient term, diffusion term and source terms.
If all inputs are correct, it creates and finalizes a
ModelEquation
instance, stored inequations
.- Parameters
-
create_full_equation
()[source]¶ Create the full equation (
full_eqn
) of the model by coupling the individualequations
.
-
get_object
(path)[source]¶ Get an object stored in the model
- Parameters
path (str) – The stored path for the object in the model
- Returns
The stored object if found
- Raises
ValueError if no object found at given path –
-
revert_vars
()[source]¶ Revert vars to the old settings. This is used when sweeping equations has to be rolled back
-
-
class
microbenthos.model.model.
ModelClock
(*args, **kwds)[source]¶ Bases:
fipy.variables.variable.Variable
Subclass of
fipy.Variable
to implement hooks and serve as clock of the model.-
property
value
¶ “Evaluate” the Variable and return its value (longhand)
>>> a = Variable(value=3) >>> print(a.value) 3 >>> b = a + 4 >>> b (Variable(value=array(3)) + 4) >>> b.value 7
-
increment_time
(dt)[source]¶ Increment the clock
- Parameters
dt (float, PhysicalField) – Time step in seconds
-
set_time
(t)[source]¶ Set the clock time in hours :param t: Time in hours :type t: float, PhysicalField
-
property
as_hms
¶ Return a tuple of (hour, minute, second)
-
property
as_hms_string
¶ Return a string of hour, min, sec
-
property
microbenthos.model.resume module¶
Module to implement the resumption of a simulation run.
The assumption is that a model object is created, and a HDF data store is available.
-
microbenthos.model.resume.
check_compatibility
(state, store)[source]¶ Check that the given model snapshot is compatible with the structure of the store. This checks that every path in the snapshot exists in the HDF store.
- Parameters
state (dict) – a model snapshot dictionary
store (
Group
) – the root node of the stored model data
- Returns
True if the structures are compatible
- Raises
ValueError – if an incompatible data is returned
NotImplementedError – for state arrays of dim > 1
-
microbenthos.model.resume.
truncate_model_data
(store, time_idx)[source]¶ Truncates the model data in store till the time_idx along the time axis.
Warning
This is a destructive operation on the provided store, if it is write-enabled. Use with caution, because it will resize the datasets in the store to the extent determined by time_idx and all the data beyond that will be lost. Only in the case of time_idx = -1, may there be no data loss as the resize will occur to the same size as the time vector.
- Parameters
store (
hdf.Group
) – root store of the model data (should be writable)time_idx (int) – An integer indicating that index of the time point to truncate
- Returns
size (int) – the size of the time dimension after truncation
microbenthos.model.saver module¶
Implements a data saver for model snapshots
-
microbenthos.model.saver.
save_snapshot
(fpath, snapshot, compression=6, shuffle=True)[source]¶ Save a snapshot dictionary of the model to a HDF file
This method preserves the nested structure of the model snapshot. If the specified file path already exists, then the snapshot data is recursively appended to the nested data structure within.
The nested data structure has three keys with special meaning:
"metadata"
The dictionary under this key will be saved as HDF attributes of the group it is in.
"data"
The value here is expected to be a tuple (data_array, meta_dict), and is saved as a HDF dataset with the attributes set from the meta_dict. This dataset will be appended to if future snapshots are appended to the file.
"data_static"
This is similar to the data case, except it is for data that does not change during model evolution. So a fixed-size dataset called “data” is created here.
Note
Due to the recursive traversal of the snapshot, no guarantees are made that the data saving is done atomically for the dictionary. As far as possible, the file access is brief and done under a closing context of
File
.Also, nested snapshot dictionaries with infinite self references in nodes will be problematic.
- Parameters
- Raises
TypeError – if snapshot is not a suitable mapping type
ValueError – if saving fails due to incompatible data types
microbenthos.model.simulation module¶
Module to handle the simulation of microbenthos models
-
class
microbenthos.model.simulation.
Simulation
(simtime_total=6, simtime_days=None, simtime_lims=(0.1, 120), snapshot_interval=60, fipy_solver='scipy', max_sweeps=100, max_residual=1e-12)[source]¶ Bases:
microbenthos.utils.create.CreateMixin
This class enables the process of repeatedly solving the model’s equations for a (small) time step to a certain numerical accuracy, and then incrementing the model clock. During the evolution of the simulation, the state of the model as well as the simulation is yielded repeatedly.
Numerically approximating the solution to a set of partial differential equations requires that the solver system has a reasonable target accuracy (“residual”) and enough attempts (“sweeps”) to reach both a stable and accurate approximation for a time step. This class attempts to abstract out these optimizations for the user, by performing adaptive time-stepping. The user needs to specify a worst-case residual (
max_residual
), maximum number of sweeps per time-step (max_sweeps
) and the range of time-step values to explore during evolution (simtime_lims
). During the evolution of the simulation, the time-step is penalized if the max residual is overshot or max sweeps reached. If not, the reward is a bump up in the time-step duration, allowing for faster evolution of the simulation.-
schema_key
= 'simulation'¶
-
FIPY_SOLVERS
= ('scipy', 'pyAMG', 'trilinos', 'pysparse')¶
-
__init__
(simtime_total=6, simtime_days=None, simtime_lims=(0.1, 120), snapshot_interval=60, fipy_solver='scipy', max_sweeps=100, max_residual=1e-12)[source]¶ - Parameters
simtime_total (float, PhysicalField) – The number of hours for the
to run (simulation) –
simtime_days (float) – The number of days (in terms of the model’s irradiance cycle) the simulation should run for. Note that specifying this will override the given
simtime_total
when themodel
is supplied.simtime_lims (float, PhysicalField) – The minimum and maximum
for the (limits) –
simtime_step
for adaptive time-stepping. This should be supplied as a pair of values, which are assumed to be in seconds and cast into PhysicalField internally. (default: 0.01, 240)max_sweeps (int) – Maximum number of sweeps to attempt per
(default (timestep) –
max_residual (float) – Maximum residual value for the solver at a
(default – 1e-14)
snapshot_interval (int, float,
PhysicalField
) – thein seconds (duration) – of the model clock between yielding snapshots of the model state for exporters (default: 60)
fipy_solver (str) – Name of the fipy solver to use. One of
('scipy', 'pyAMG', 'trilinos','pysparse')
(default: “scipy”)
-
simtime_days
¶ Numer of days to simulate in terms of the model’s irradiance source
-
property
started
¶ Returns: bool: Flag for if the sim evolution has started
-
property
fipy_solver
¶
-
property
simtime_total
¶ The number of hours of the model clock the simulation should be evolved for.
The supplied value must be larger than the time-steps allowed. Also, it may be over-ridden by supplying
simtime_days
.- Returns
PhysicalField – duration in hours
-
property
simtime_step
¶ The current time-step duration. While setting, the supplied value will be clipped to within
simtime_lims
.- Returns
PhysicalField – in seconds
-
property
simtime_lims
¶ The limits for the time-step duration allowed during evolution.
This parameter determines the degree to which the simulation evolution can be speeded up. In phases of the model evolution where the numerical solution is reached within a few sweeps, the clock would run at the max limit, whereas when a large number of sweeps are required, it would be penalized towards the min limit.
A high max value enables faster evolution, but can also lead to numerical inaccuracy ( higher residual) or solution breakdown (numerical error) during
run_timestep()
. A small enough min value allows recovery, but turning back the clock to the previous time step and restarting with the min timestep and allowing subsequent relaxation.- Parameters
vals (float, PhysicalField) – the (min, max) durations in seconds
- Returns
lims (tuple) – The (min, max) limits of
simtime_step
each as aPhysicalField
-
property
max_sweeps
¶ The maximum number of sweeps allowed for a timestep
- Parameters
val (int) – should be > 0
- Returns
int
-
property
model
¶ The model to run the simulation on. This is typically an instance of
MicroBenthosModel
or its subclasses. The interface it must provide is:a method
create_full_equation()
an attribute
full_eqn
created by above method, which is a_BinaryTerm
that has asweep()
method.method
model.update_vars()
which is called before each
timestep
method
model.clock.increment_time(dt)()
which is called
after each timestep
Additionally, if
simtime_days
is set, then setting the model will try to find the"env.irradiance:
object and use itshours_total
attribute to set thesimtime_total
.- Parameters
model (
MicroBenthosModel
) – model instance- Returns
MicroBenthosModel
- Raises
RuntimeError – if model has already been set
ValueError – if modes interface does not match
ValueError – if model
model.full_eqn
does not get created even aftermodel.create_full_equation()
is called.
-
evolution
()[source]¶ Evolves the model clock through the time steps for the simulation, i.e. by calling
run_timestep()
andmodel.clock.increment_time()
repeatedly whilemodel.clock() <= self.simtime_total
.This is a generator that yields the step number, and the state of the evolution after each time step. If
snapshot_due()
is true, then also the model snapshot is included in the state.- Yields
(step, state) tuple of step number and simulation state
- Raises
RuntimeError – if
started
is already True
-
get_state
(state=None, metrics=None, **kwargs)[source]¶ Get the state of the simulation evolution
- Parameters
state (None, dict) – If state is given (from
model.snapshot()
), then that is used. If None, then just the time info is created by usingmodel.clock
.metrics (None, dict) – a dict to get the simulation metrics from, else from kwargs
**kwargs – parameters to build metrics dict. Currently the keys “calc_time”, “residual” and “num_sweeps” are used, if available.
- Returns
dict – the simulation state
-
snapshot_due
()[source]¶ - Returns
bool – If the current model clock time has exceeded
snapshot_interval
since the last snapshot time
-
update_simtime_step
(residual, num_sweeps)[source]¶ Update the
simtime_step
to be adaptive to the current residual and sweeps.A multiplicative factor for the time-step is determined based on the number of sweeps and residual. If the residual is more than
max_residual
, then the time-step is quartered. If not, it is boosted by up to double, depending on the num_sweeps andmax_sweeps
. Once a new timestep is determined, it is limited to the time left in the model simulation.
-