Recommendations for biogeochemical models - fabm-model/fabm GitHub Wiki
Introduction
This section describes how the design and implementation of your biogeochemical models can be optimized to integrate well with existing FABM-based modular models, such as those underpinning the Copernicus Marine Service. The conventions described here are therefore optional - while they can facilitate collaboration (notably, exchange of modules), other approaches that use standard FABM APIs remain perfectly valid.
In general
Modularity
The minimum level of modularity that you need follows from the components you want to exchange with others, now or in the future. For instance, to support module exchange in NECCTON, modules for oxygen, carbonate chemistry, irradiance, suspended particulate matter and higher trophic levels are best written as stand-alone module, as this will allow them to be used in the different CMEMS Monitoring and Forecasting Centres.
The optimum level of modularity depends on the intended uses of the model. In practice, many have found it useful to use one module instance per “integral physical particle”, e.g., a type of molecule (e.g., dissolved nitrate, oxygen), generalized compound (e.g., a class of particulate or dissolved organic matter) or organism (e.g., a plankton functional type). Each instance has a separate entry in fabm.yaml. In this scenario, the model code would typically include FABM modules (Fortran derived types, each coded in a separate source file) for a generalized passive tracer, generalized phytoplankton, and generalized zooplankton. In fabm.yaml, the passive tracer module is then used for nutrients, dissolved organic matter classes and particulate organic matter classes, the phytoplankton module is used for every instantiated phytoplankton type, and the zooplankton module is used for every instantiated zooplankton type.
Particle-based modularisation has several benefits:
- the same code can be used to construct different ecosystem configurations (by adding or removing plankton functional types in
fabm.yaml) - consolidated codes for generic phytoplankton and generic zooplankton are written once (no separate copies for pico-, nano-, and microphytoplankton, diatoms, califyers, etc.), which reduces code size and guarantees consistency among plankton functional types. It thereby reduces the risk of bugs.
- mass conservation can be diagnosed per module, which makes conservation checking much easier.
Registering variables
- Each module can register any mixture of state variables, diagnostic variables, dependencies and state dependencies that it needs.
- To leverage implicit coupling, link your state variables and diagnostic variables to a predefined standard variable identity where appropriate. This is done by supplying the
standard_variableargument during variable registration, e.g.,standard_variable=standard_variables%alkalinity_expressed_as_mole_equivalentwhen you register alkalinity. Note that if you do this, you promise that units of your variable and the predefined standard variable are identical. - Register the contributions of your state and diagnostic variables to aggregate variables. This is essential for conserved quantities such as total carbon, nitrogen, phosphorus, silicon, iron, since aggregate variables are used both for model coupling and conservation checks. However, it is also useful for additional aggregate quantities such as total chlorophyll, which is widely used by irradiance models to compute attenuation, and net primary production, which is used by higher trophic level models (e.g., SEAPODYM-LMTL).
- If you see a need for additional standard variable identities, post a message on the FABM discussion forum.
Coupling to other modules
- Where possible, couple based on predefined standard variable identities. These can be used to access fields from the hosting hydrodynamic model (e.g., temperature), but also fields from other modules, e.g., alkalinity. Note that standard variables have specific defined units.
- When coupling to other “particles”, e.g., nutrients, a class of particulate organic matter, another functional type (e.g., prey), use standard variable-based coupling. For example, register a dependence on a “pom” instance (couplable in
fabm.yaml) and then use therequest_coupling_to_modelAPI to couple (in code) to individual constituents such as total carbon, nitrogen, etc. Note that the resulting variables have specific defined units.
Providing source terms and diagnostics
Use the standard routines where possible: do for the pelagic, do_bottom for the bottom, do_surface for the water surface. These are designed to operate efficiently, and easy to implement as they always operate locally (given the local environment and state, calculate local sources and diagnostics). Only use do_column if there is no other way to achieve what you need, as it is relatively inefficient. If you do use it, consider doing so only for the minimum of calculations possible, by moving these into a stand-alone child module.
Vertical movement of pelagic state variables
To apply constant vertical velocities (e.g., sinking), register your state variable with the vertical_movement argument. To use time- and/or space varying velocities, implement the get_vertical_movement routine. This is also needed to add vertical velocities (constant or variable) to a state variable dependency, e.g., to add migration behaviour. Remember to apply the same vertical velocity to all of your registered state variables.
Specific component models
Phytoplankton
- Register your contribution to total chlorophyll, even if you do not normally track it, and would only assume it to be proportional to biomass. That is because chlorophyll is a crucial quantity in many models you may be coupled to (e.g., irradiance)
- Register you contribution to net primary production to support selected higher trophic level models (e.g., SEAPODYM)
Predators (e.g., zooplankton)
- Use particle conventions to obtain prey biomass (read-only) and destroy your prey by applying the same specific loss rate to all state variables
- Consider generalizing the zooplankton type of accept any number of prey, configurable and couplable in
fabm.yaml, instead of using a fixed set of prey types with hardcoded names. Together with the particle convention (previous item), this would enable your zooplankton implementation to work within other biogeochemical/lower trophic level models.
Carbonate system
- If you are using non-trivial logic to calculate alkalinity, place it in a stand-alone alkalinity module, separate from the rest of the carbonate system. That module can then be re-used with other carbonate system solvers. Your carbonate system itself can then be used with fully prognostic alkalinity too.
- Do not include state variables beyond total Dissolved Inorganic Carbon (DIC) and alkalinity. For instance, state variables for particulate inorganic carbon (total calcium carbonate, aragonite, calcite, free coccoliths, etc.) should not be included here but placed in a separate module.
- Allow for time/space varying atmospheric pCO2 by registered this as a surface dependency linked to
standard_variables%mole_fraction_of_carbon_dioxide_in_air - Register total alkalinity with standard variable identity
standard_variables%alkalinity_expressed_as_mole_equivalent, both when you are providing it as a diagnostic or state variable, and when you register dependencies on it. - If using parametrized alkalinity (e.g. alkalinity is a function of salinity), you could potentially register it with
act_as_state_variable=.true.to track biological pertubations of the background alkalinity
Irradiance
- For more complex models (e.g., spectrally resolving), consider separating the atmospheric component (if any), the underwater radiative transfer model, and the calculation of (broadband/wavelength-explicit) absorption/scattering/attenuation properties summed across Inherent Optical Properties (IOPs). This allows the first two components to work unmodified with new parametrisations (e.g., new absorption and scattering spectra) and new IOPs.
Higher trophic levels (2D)
This section discusses organisms that move fast in the vertical, to the extent that that they can be represented by depth-integrated biomass and a prescribed vertical distribution. This distribution may be variable, for example, dependent on time, depth, environmental variables such as temperature, or prey availability.
- If you are implementing such a model in FABM anew, we recommend you review the functionality introduced recently for this purpose. It provides a flexible method for mapping 2D predators over the pelagic, and ensures their interactions with pelagic variables are mass conserving.
- The above recommendations for generic predators apply: by permitting the number and names of prey to be defined at runtime in
fabm.yaml, and by accessing prey constituents through standard names (total_carbon, etc.), your HTL model will be compatible with a wide range of biogeochemical/lower trophic level models, and thus shareable across CMEMS Monitoring and Forecasting Centres.