Skip to content

FABM 1.0

Jorn Bruggeman edited this page Nov 25, 2021 · 8 revisions

FABM 1.0 is designed as the first long-term stable release: it standardises the application programming interfaces (APIs) that have been developed over the past 11 years and eliminates any inconsistencies and duplication of functionality. This affects the host API, that is, the set of routines that link FABM and its host (typically a hydrodynamic model). The FABM couplers developed for most hydrodynamic models will require small changes to become compatible with FABM 1.0. Biogeochemical models included in/linked to FABM do not require changes, provided they follow the coding conventions that have been in place since 2015. However, some functionality that has been deprecated for a long time (e.g., namelists-based configuration) is now removed. Biogeochemical models that rely on that will need an update.

Biogeochemical API

FABM 1.0 drops support for reading its configuration from namelists (fabm.nml); this functionality has been superseded by a yaml-based system (fabm.yaml) in 2014. Biogeochemical models that exclusively support namelist-based configuration will need an update to use yaml. Without this update they will still compile but not be configurable (argument configunit will always be -1).

In addition, FABM 1.0 drops a large number of long-deprecated aliases for preprocessor macros. This includes for instance _SET_ODE_BEN_, which has been replaced by _SET_BOTTOM_ODE_ in 2013.

Host API

Backward compatibility

Most changes are name changes of existing variables and procedures. To facilitate migration to the new FABM version, a new fabm_v0_compatibility module has been created that makes many host APIs available under their original names. By adding use fabm_v0_compatibility you can minimize the changes needed to get your host working with FABM 1.0. However, this is not a long-term solution. The compatibility module will ultimately be removed. We therefore recommend you adopt the conventions outlined below as soon as possible.

You can detect which FABM version is used at compile time: preprocessor symbol _FABM_API_VERSION_ will be 1 for FABM 1.0, and 0 for earlier versions. Thus, after migrating your coupler to FABM 1.0, you can include something like this:

#include fabm_version.h
#if _FABM_API_VERSION_ < 1
#  error You need FABM 1.0 or later
#endif

By placing that early in your source code, users with a pre-1.0 FABM version will be told about the need to upgrade to a new version, instead of getting a large number of errors about undefined symbols. The above code segment depends on fabm_version.h, which has been provided with FABM since July 2019.

Renamed public methods and types

To guarantee that use fabm does not import names that already exist in the host namespace, all public FABM types are prefixed with type_fabm_, just like public methods and variables are prefixed with fabm_. A few additional names are changed for consistency and simplicity.

Old name New name
type_model type_fabm_model
type_external_variable type_fabm_variable
type_horizontal_state_variable_info type_fabm_horizontal_state_variable
type_bulk_variable_id type_fabm_interior_variable_id
type_horizontal_variable_id type_fabm_horizontal_variable_id
type_scalar_variable_id type_fabm_scalar_variable_id
standard_variables fabm_standard_variables

Note that fabm_standard_variables in the above is the object with all of FABM's predefined standard variables (e.g, fabm_standard_variables%temperature). fabm_standard_variables is also the name of a module. However, all relevant variables in that module are exposed by the fabm and fabm_types modules, which means you should not need to use fabm_standard_variables. Thus there is no risk of name clashes.

Model creation

To improve the performance of object-oriented access to a FABM model, it needs to be declared as class pointer, for instance:

class (type_fabm_model), pointer :: model

At the same time, the name and syntax of the model creation function is changed from

call fabm_create_model_from_yaml_file(model, ...)

to

model => fabm_create_model(...)

The fabm_create_model function is available from the main fabm module. You no longer need to import fabm_config.

Access API methods through the model object

As soon as the model object is created (by calling fabm_create_model), FABM APIs should be accessed through the model's type-bound procedures. Typically, this means that calls such as call fabm_set_domain(model, ...) need to be replaced by call model%set_domain(...).

Old syntax New syntax
fabm_initialize(model, ...) model%initialize(...)
fabm_finalize(model, ...) model%finalize(...)
fabm_set_domain(model, ...) model%set_domain(...)
fabm_set_mask(model, ...) model%set_mask(...)
fabm_check_ready(model, ...) model%start(...)
fabm_initialize_state(model, ...) model%initialize_interior_state(...)
fabm_initialize_surface_state(model, ...) model%initialize_surface_state(...)
fabm_initialize_bottom_state(model, ...) model%initialize_bottom_state(...)
fabm_do(model, ...) model%get_interior_sources(...)
fabm_do_surface(model, ...) model%get_surface_sources(...)
fabm_do_bottom(model, ...) model%get_bottom_sources(...)
fabm_get_vertical_movement(model, ...) model%get_vertical_movement(...)
fabm_check_state(model, ...) model%check_interior_state(...)
fabm_check_surface_state(model, ...) model%check_surface_state(...)
fabm_check_bottom_state(model, ...) model%check_bottom_state(...)
fabm_get_conserved_quantities(model, ...) model%get_interior_conserved_quantities(...)
fabm_get_horizontal_conserved_quantities(model, ...) model%get_horizontal_conserved_quantities(...)
fabm_link_interior_data(model, ...) model%link_interior_data(...)
fabm_link_horizontal_data(model, ...) model%link_horizontal_data(...)
fabm_link_scalar(model, ...) model%link_scalar(...)
fabm_link_interior_state_data(model, ...) model%link_interior_state_data(...)
fabm_link_bottom_state_data(model, ...) model%link_bottom_state_data(...)
fabm_link_surface_state_data(model, ...) model%link_surface_state_data(...)
fabm_get_interior_data(model, ...) model%get_interior_data(...)
fabm_get_horizontal_data(model, ...) model%get_horizontal_data(...)
fabm_get_scalar_data(model, ...) model%get_scalar_data(...)
fabm_get_interior_diagnostic_data(model, ...) model%get_interior_diagnostic_data(...)
fabm_get_horizontal_diagnostic_data(model, ...) model%get_horizontal_diagnostic_data(...)

The following are removed altogether:

  • fabm_get_light_extinction
  • fabm_get_albedo
  • fabm_get_drag
  • fabm_get_light
  • model%set_surface_index
  • model%set_bottom_index (unless _FABM_BOTTOM_INDEX_ is -1)

Domain extents and set_bottom_index/set_surface_index

As before, the extents of the spatial domain are set with model%set_domain. Optionally, you can now also set the active domain by calling model%set_domain_start with the first active index for each dimension (default: 1) and calling model%set_domain_stop with the last active index for each dimension (default: the dimension size provided to set_domain). The extents of the active domain are used to infer the index of the surface and bottom layers, which is why model%set_surface_index and model%set_bottom_index have been removed (the latter only if FABM_BOTTOM_INDEX_ is not -1).

The full domain extents provided to set_domain determine the shape of all arrays provided to the link_data family of routines and the shape of all diagnostics provided by FABM. Conversely, the active domain determines for which grid cells FABM will compute biogeochemical properties (e.g., sources). This distinction can be useful: for instance, the full domain may include halo zones that need to be present for FABM diagnostics, but can be excluded from the active domain (i.e., from computation).

Call order when retrieving source terms

Calls to FABM within a single model time step must be encapsulated between a call to prepare_inputs and a call to finalize_outputs.

  1. Before you retrieve model source terms (model%get_interior_sources, model%get_bottom_sources, model%get_surface_sources), you must call model%prepare_inputs. This ensures that all variables that the source routines depend on are computed. This replaces calls to fabm_update_time, fabm_get_light_extinction, fabm_get_light, which together achieved the same in the past. model%prepare_inputs optionally takes arguments for the current time, year, month, day, just like fabm_update_time did before.
  2. The routines that return sources (model%get_interior_sources, model%get_bottom_sources, model%get_surface_sources) can be called in any order.
  3. After you retrieve model source terms, you must call model%finalize_outputs. This ensures that diagnostics unrelated to source routines are computed.

Both model%prepare_inputs and model%finalize_outputs operate on the entire active model domain. They therefore do not take spatial indices as argument and should be placed outside any spatial loops.

Before you can use any of these calls, you must call model%start (previously fabm_check_ready) at the start of the simulation. That was optional before, but now it is required.

Clone this wiki locally