Custom rules and tracers¶
The biogeochemistry module for Veros is designed for allowing construction of user defined ecosystems.
Base systems are made available for a basic Nutrients-Plankton-Zooplankton-Detritus, NPZD, system,
which can optionally be extended by a basic carbon cycle. Enabling the biogeochemistry module and
activating the basic NPZD system can be done by setting enable_npzd = True
.
Ecosystems created with the biogeochemistry module are extensible and any components of them are in principle replaceable. This is handled by three principles: Representation of model tracers by classes, representation of interactions between tracers as rules, and separation of component creation from activation.
Tracer classes¶
All model tracers in the biogeochemistry module are created as instances of classes inheriting from a
base class NPZD_tracer
. This class itself inherits from numpy.ndarray, which allows using it
like any other Veros variable. The concentration (or appropriate unit) of the tracer within each cell
in Veros’ grid is stored in the corresponding cell in the tracer grid. The base class defines attributes
for operations which may apply to any tracer.
Instances of this class must be created with a numpy array backing the tracer values. Preferably this
array was created in variables.py. Additionally a name must be supplied. This name will uniquely
identify the tracer during simulation. Optional arguments may be supplied:
transport
By default this value is True. When transport
is true, the tracer is transported
according to the selected transportation scheme. Setting a value for for sinking_speed
will cause
the tracer to be included in calculations of sinking tracers. And setting light_attenuation
will
block downward shortwave radiation proportionally to the concentration of the tracer.
This class may itself be used for tracers, which should not express any further features such
as the nutrients phosphate.
NPZD_tracer(vs.po4, 'po4')
Tracers which should express actionable features such as grazing, primary production must implement
certain methods. Methods to implement are mortality
for mortality, recycle
for recycling,
potential_growth
for primary production. In addition to this methods should be supplied a list
of functions representing limiting in growth by nutrients. grazing
for grazing. This method
should return dictionaries for grazing, digestion, excretion, and sloppy feeding. Where the keys
are names of the tracers, which have been grazed upon.
It is possible to add additional actionable methods by editing npzd.py.
Predefined tracers¶
A number of classes for tracers have been predefined. These classes can be instantiated with different parameters to defined tracers with varying properties. For example creating tracers for coccolithophores and phytoplankton can be done like
coccolithophores = Phytoplankton(np.zeros((3,vs.nx, vs.ny, vs.nz)), 'coccolithophores',
light_attenuation=1,
growth_parameter=0.9,
recycling_rate=0.8,
mortality_rate=0.7)
phytoplankton = Phytoplankton(vs.phytoplankton, 'phytoplankton',
light_attenuation=vs.light_attenuation_phytoplankton,
growth_parameter=vs.maximum_growth_rate_phyto,
recycling_rate=vs.fast_recycling_rate_phytoplankton,
mortality_rate=vs.specific_mortality_phytoplankton)
Base tracer¶
- class veros_bgc.core.npzd_tracers.NPZD_tracer(input_array, name, sinking_speed=None, light_attenuation=None, transport=True, description=None)[source]¶
Bases:
numpy.ndarray
Class for npzd tracers to store additional information about themselves.
Note
Inhenrits from numpy.ndarray to make it work seamless with array operations
- Parameters
input_array (
numpy.ndarray
) – Numpy array backing dataname (
str
) – Identifier for the tracer, which must be unique within a given configurationsinking_speed (
numpy.ndarray
, optional) – Numpy array for how fast the tracer sinks in each celltransport (
bool
= True, optional) – Whether or not to include the tracer in physical transportlight_attenuation (
numpy.ndarray
, optional) – Factor for how much light is blocked
- name¶
Identifier for the tracer, which must be unique within a given configuration
- description¶
Description of the tracer represented by the class
- transport¶
Whether or not to include the tracer in physical transport
- sinking_speed¶
If set: how fast the tracer sinks in each cell
- Type
numpy.ndarray
, optional
- light_attenuation¶
If set: Factor for how much light is blocked
- Type
numpy.ndarray
, optional
Recyclable tracer¶
- class veros_bgc.core.npzd_tracers.Recyclable_tracer(input_array, name, recycling_rate=0, **kwargs)[source]¶
Bases:
veros_bgc.core.npzd_tracers.NPZD_tracer
A recyclable tracer
This would be tracer, which may be a tracer like detritus, which can be recycled
- Parameters
input_array (
numpy.ndarray
) – Numpy array backing dataname (
str
) – Identifier for the tracer, which must be unique within a given configurationrecycling_rate – A factor scaling the recycling by the population size
**kwargs – All named parameters accepted by super class
- recycling_rate¶
A factor scaling the recycling by the population size
- + All attributes held by super class
Plankton¶
- class veros_bgc.core.npzd_tracers.Plankton(input_array, name, mortality_rate=0, **kwargs)[source]¶
Bases:
veros_bgc.core.npzd_tracers.Recyclable_tracer
Class for plankton object, which is both recyclable and displays mortality
This class is intended as a base for phytoplankton and zooplankton and not as a standalone class
Note
Typically, it would desirable to also set light attenuation
- Parameters
input_array (
numpy.ndarray
) – Numpy array backing dataname (
str
) – Identifier for the tracer, which must be unique within a given configurationmortality_rate – Rate at which the tracer is dying in mortality method
**kwargs – All named parameters accepted by super class
- mortality_rate¶
Rate at which the tracer is dying in mortality method
- + All attributes held by super class
Phytoplankton¶
- class veros_bgc.core.npzd_tracers.Phytoplankton(input_array, name, growth_parameter=0, **kwargs)[source]¶
Bases:
veros_bgc.core.npzd_tracers.Plankton
Phytoplankton also has primary production
- Parameters
input_array (
numpy.ndarray
) – Numpy array backing dataname (
str
) – Identifier for the tracer, which must be unique within a given configurationgrowth_parameter – Scaling factor for maximum potential growth
**kwargs – All named parameters accepted by super class
- growth_parameter¶
Scaling factor for maximum potential growth
- + All attributes held by super class
Zooplankton¶
- class veros_bgc.core.npzd_tracers.Zooplankton(input_array, name, max_grazing=0, grazing_saturation_constant=1, grazing_preferences={}, assimilation_efficiency=0, growth_efficiency=0, maximum_growth_temperature=20, **kwargs)[source]¶
Bases:
veros_bgc.core.npzd_tracers.Plankton
Zooplankton displays quadratic mortality rate but otherwise is similar to ordinary phytoplankton
- Parameters
input_array (
numpy.ndarray
) – Numpy array backing dataname (
str
) – Identifier for the tracer, which must be unique within a given configurationmax_grazing – Scaling factor for maximum grazing rate
grazing_saturation_constant – Saturation in Michaelis-Menten
grazing_preferences – Dictionary of preferences for grazing on other tracers
assimilation_efficiency – Fraction of grazed material ingested
growth_efficiency – Fraction of ingested material resulting in growth
maximum_growth_temperature (= 20) – Temperature in Celsius where increasing temperature no longer increases grazing
**kwargs – All named parameters accepted by super class
- max_grazing¶
Scaling factor for maximum grazing rate
- grazing_saturation_constant¶
Saturation in Michaelis-Menten
- grazing_preferences¶
Dictionary of preferences for grazing on other tracers
- assimilation_efficiency¶
Fraction of grazed material ingested
- growth_efficiency¶
Fraction of ingested material resulting in growth
- maximum_growth_temperature¶
Temperature in Celsius where increasing temperature no longer increases grazing
- + All attributes held by super class
Extending tracers¶
The biogeochemistry tracers make use of the object oriented nature of Python to allow easy extensibility.
Tracers which exhibit nearly identical behavior can be created via extension. For example the
Zooplankton
class overrides the mortality function defined by the Plankton
class
class Zooplankton(Plankton):
# ...
@veros_method(inline=True)
def mortality(self, vs):
"""
Zooplankton mortality is modelled with a quadratic mortality rate
"""
return self.mortality_rate * self ** 2
By using this approach you only have to focus on the differences between tracers.
Rules¶
Creating your tracers as objects does not in itself add any time evolution to the system. You must also specify the interaction between the tracers. This is done by creating rules. A rule specifies the flow from one tracer to another. An ecosystem can be defined as a collection of rules each specifying part of the flow between tracers.
Rules consist of a function describing the interaction, the name of the source tracer and the name of the sink tracer. The function itself may be used in several rules. The rule function has access to any variable stored in the Veros object. This includes results of the methods described in the previous section. An example rule could look like
@veros_method(inline=True)
def recycling_to_po4(vs, source, sink):
return {source: -vs.recycled[source], sink: vs.redfield_ratio_PN * vs.recycled[source]}
The function returns a dictionary. The keys of the dictionary must be names of the tracers, which are affected by the rule. The values are numpy arrays corresponding to the change in the tracer. The return dictionary is not strictly required to contain two keys. If a rule only represents part of an interaction, just one key can be included. Any number of entries in the dictionary will be processed, but a rule is intended to represent a flow between two tracers. The rule should then be registered with the names of the source and sink to make it available for use in Veros.
register_npzd_rule(vs, 'recycle_phytoplankton_to_po4', (recycling_to_po4, 'phytoplankton', 'po4'))
The rule is registered with the Veros object as the first argument followed by a unique name for the rule and a tuple consisting of the rule function, the name of the source, and the name of the sink. Those two names will be passed as arguments to the function. The rule name is used for selecting the rule for activation. The tuple may also be replaced by a list containing names of other rules. This collection of rules may later be activated using just the name the list was registered with.
Optional arguments¶
Rules can also be registered with optional arguments.
The label
argument specifies a displayed
name which is shown in the graph generated by the biogeochemistry diagnostics.
boundary
may take 3 values. ‘SURFACE’, ‘BOTTOM’ or None (default). If ‘SURFACE’ the rule only applies
to the top layer of the grid. ‘BOTTOM’ means the rule only applies to the cells immediately above the
bottom. None means the rule applies to the entire grid.
group
specifies in which of three execution locations the rule will be applied. The ‘PRIMARY’
group is the default group. Rules in this group will be evaluated several times in a loop. The number
of times specified by the ratio between vs.dt_tracer
and vs.dt_bio
. The result of the
rule will be time stepped and added to the tracer concentrations. The ‘PRE’ group is evaluated once
per tracer time step before the ‘PRIMARY’ loop. The results of these rules are not time stepped before
adding to the result to the relevant tracers. The ‘POST’ group is evaluated once before the ‘PRIMARY’
rules. Time stepping is left out of ‘PRE’ and ‘POST’ rules in order to allow them to clean up or
reuse results from other rules.
Difference between rules and tracer classes¶
The difference between rules and classes and their methods is, that the tracer objects themselves do not modify tracer concentrations. Only the rules should influence the time evolution of the tracers. The results of the methods may be used in rules.
Activation¶
In order to use the created classes and rules. They must be activated. Tracers are activated by register_npzd_data. Rules are activated by adding their names to npzd_selected_rules for example.
detritus = Recyclable_tracer(vs.detritus, 'detritus',
sinking_speed=dtr_speed,
recycling_rate=vs.remineralization_rate_detritus)
register_npzd_data(vs, detritus)
This adds a tracer with the name ‘detritus’ to the model which sinks and a recycling method.
Rules which have been registered with register_npzd_rule are activated by selecting them with select_npzd_rule. select_npzd_rule accepts rule names. If the name represents a collection of rules, each rule in the collection is activated.
# activate the npzd_basic_phytoplankton_grazing rule
select_npzd_rule(vs, 'npzd_basic_phytoplankton_grazing')
# a list of rules, which have been registered with a single name
# may be activated collectively from that name
register_npzd_rule(vs, 'group_npzd_basic', [
'npzd_basic_phytoplankton_grazing',
'npzd_basic_phytoplankton_mortality',
'npzd_basic_phytoplankton_fast_recycling',
'npzd_basic_phytoplankton_primary_production',
'npzd_basic_zooplankton_grazing',
'npzd_basic_zooplankton_mortality',
'npzd_basic_zooplankton_sloppy_feeding',
'npzd_basic_detritus_remineralization',
'npzd_basic_detritus_grazing',
'npzd_basic_detritus_bottom_remineralization'
])
select_npzd_rule(vs, 'group_npzd_basic') # This activates all the rules in the collection
The example setup file for biogeochemistry demonstrates how a configuration file can be used to activate rules.