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).