Adding a Diagnostic¶
This is a five step process.
There are three changes to make in the Fortran code, all of which are made in marbl_diagnostics_mod.F90
.
There are also two steps to make sure the diagnostic is known the GCM so it is included in the output.
For this example, we follow the DIC Surface Gas Flux, which uses the DIC_GAS_FLUX
index.
Step 1. Add to MARBL diagnostic indexing type¶
To reduce the number of string comparisons inside routines called every time-step, MARBL uses integer indices to track many different variables.
These indices are packed into datatypes to group common indices together.
So the indices for diagnostics variables are split into marbl_surface_forcing_diagnostics_indexing_type
and marbl_interior_forcing_diagnostics_indexing_type
.
DIC_GAS_FLUX
is a surface forcing diagnostics.
type marbl_surface_forcing_diagnostics_indexing_type
integer(int_kind) :: ECOSYS_IFRAC
integer(int_kind) :: ECOSYS_XKW
integer(int_kind) :: ECOSYS_ATM_PRESS
.
.
.
integer(int_kind) :: DIC_GAS_FLUX
.
.
.
end type marbl_surface_forcing_diagnostics_indexing_type
Step 2. Add to diagnostic structure¶
Another common feature among MARBL datatypes is the idea of adding an element to a derived type to contain all the data.
Most derived types, including as marbl_diagnostics_type
, are “reallocating”:
when a field is added, a new array of size N+1
is created, the existing array is copied into the first N
elements and then deallocated, and the new entry becomes element N+1
.
In these situations, pointers are used instead of allocatable arrays so that marbl_instance%{surface,interior}_forcing_diags%diags
can point to the new array.
lname = 'DIC Surface Gas Flux'
sname = 'FG_CO2'
units = 'mmol/m^3 cm/s'
vgrid = 'none'
truncate = .false.
call diags%add_diagnostic(lname, sname, units, vgrid, truncate, &
ind%DIC_GAS_FLUX, marbl_status_log)
if (marbl_status_log%labort_marbl) then
call log_add_diagnostics_error(marbl_status_log, sname, subname)
return
end if
Step 3. Populate diagnostic type with data¶
The purpose of the marbl_diagnostics_type
structure is to allow an easy way to pass diagnostics through the interface.
This step copies data only available in MARBL into the datatype that is available to the GCM.
if (lflux_gas_co2) then
.
.
.
diags(ind_diag%DIC_GAS_FLUX)%field_2d(:) = flux_co2(:)
.
.
.
diags(ind_diag%pCO2SURF)%field_2d(:) = pco2surf(:)
.
.
.
end if ! lflux_gas_co2
Note
There are many different store_diagnostics_*
subroutines for diagnostics coming out of set_interior_forcing()
, surface forcing fields (like DIC_GAS_FLUX
) are stored in marbl_diagnostics_set_surface_forcing().
In a future release the ``store_diagnostics
routines will be condensed into a smaller subset of routines and there will be a clearer naming convention.
Regardless, find the routine that makes the most sense for your diagnostic variable.
Step 4. Update the Diagnostics YAML files¶
We use a YAML file to provide an easy-to-edit and human-readable text file containing a list of all diagnostics and the recommended frequency of output.
FG_CO2 : &FG_CO2 # rename ind%DIC_GAS_FLUX -> ind%FG_CO2
longname : DIC Surface Gas Flux
units : mmol/m^3 cm/s
vertical_grid : none
frequency :
- medium
- high
operator :
- average
- average
Note that FG_CO2
matches what we used for the shortname in Step 2. Add to diagnostic structure.
The frequencies of medium
and high
mean “we recommend outputting this variable both daily and monthly”, and the operators mean “average over both of those time periods.”
Step 5. Convert the YAML file to JSON¶
We prefer editing YAML files to editing JSON files because they are much easier to maintain (and allow user comments).
Unfortunately, python does not include a YAML parser in the default distributions.
Rather than require all users to install pyYAML
, we require that of MARBL developers and then ask them to convert the YAML files to JSON.
The MARBL_tools/yaml_to_json.py
script is provided to do just that:
$ cd MARBL_tools
$ ./yaml_to_json.py
The rest of the python scripts provided in the MARBL_tools/
subdirectory rely on the JSON file rather than the YAML.
MARBL_tools/MARBL_generate_diagnostics_file.py
will turn the JSON file into a list for the GCM to parse:
# This file contains a list of all diagnostics MARBL can compute for a given configuration,
# as well as the recommended frequency and operator for outputting each diagnostic.
# The format of this file is:
#
# DIAGNOSTIC_NAME : frequency_operator
#
# And fields that should be output at multiple different frequencies will be comma-separated:
#
# DIAGNOSTIC_NAME : frequency1_operator1, frequency2_operator2, ..., frequencyN_operatorN
#
# Frequencies are never, low, medium, and high.
# Operators are instantaneous, average, minimum, and maximum.
.
.
.
FG_CO2 : medium_average, high_average
It is then up to the GCM to convert this text file into a format it recognizes for output (e.g. POP will add to the tavg_contents
file).