cable_output_mod Module

This module provides the interface for interacting with the CABLE output system.

The output system is responsible for writing CABLE output variables to one or more netCDF output and/or restart files, and includes functionality for performing parallel I/O in MPI mode, grid cell reductions over sub-grid tiles, and time aggregations of diagnostic variables.

Using the output system involves the following steps:

  1. cable_output_mod_init must be called before any other procedures in this module to initialise the output system.

  2. Diagnostics should be registered with the output system via cable_output_register_output_variables. This involves creating an array of cable_output_variable_t instances which describe the available diagnostics and passing this array to cable_output_register_output_variables. For example, a 1-dimensional diagnostic variable defined on the patch dimension could be registered as follows:

    call cable_output_register_output_variables([ &
      cable_output_variable_t( &
        field_name="my_diagnostic", &
        data_shape=[cable_output_get_dimension("patch")], &
        aggregator=new_aggregator(my_diagnostic_working_variable) &
      ), &
      cable_output_variable_t( &
        ...
      ) &
    ])
    

    Note that registering an output variable does not necessarily mean that the variable will be written to an output stream - this can depend on whether the output variable is active, which often depends on the output configuration, or if the variable is a restart variable and whether we are writing to a restart file. There are additional properties which may be specified for each registered output variable - please see cable_output_variable_t for more details. In general, output variables should be registered if their associated diagnostic working variables are initialised in the model as this can help provide information on the diagnostics which are available.

  3. Output streams should be initialised via cable_output_init_streams. This should be done after registering output variables as the output stream initialisation involves determining which output variables are active in each output stream based on the current output configuration. Once an output stream has been initialised, data can be written to disk.

  4. Typically on the first time step of the simulation, cable_output_write_parameters should be called to write out any non-time varying parameter output variables.

  5. On each time step, cable_output_update should be called to update the time aggregation accumulation for any output variables that are active in an output stream. After cable_output_update is called, cable_output_write should be called to write out the output variables for any output streams with a sampling frequency that aligns with the current time step.

  6. If writing a CABLE restart file is required, then cable_output_write_restart should be called at the end of the simulation to write out the restart variables to the CABLE restart file.

  7. Lastly, after all output has been written, cable_output_mod_end should be called to close any open output streams and perform any necessary cleanup of resources.


Used by


Variables

Type Visibility Attributes Name Initial
integer, private, parameter :: CABLE_OUTPUT_VAR_TYPE_UNDEFINED = -1
character(len=32), public, parameter :: allowed_reduction_methods(3) = ["none                    ", "grid_cell_average       ", "first_patch_in_grid_cell"]

List of allowed reduction methods for output variables. Please refer to cable_grid_reductions_mod for more details on grid reductions.

character(len=32), public, parameter :: allowed_aggregation_methods(5) = ["point", "mean ", "max  ", "min  ", "sum  "]

List of allowed aggregation methods for output variables. Please refer to aggregator_mod for more details on aggregation methods.

character(len=32), public, parameter :: allowed_grid_types(3) = ["mask   ", "land   ", "restart"]

List of allowed grid types for an output stream.

integer(kind=int32), public, parameter :: CABLE_OUTPUT_FILL_VALUE_INT32 = -9999999_int32
real(kind=real32), public, parameter :: CABLE_OUTPUT_FILL_VALUE_REAL32 = -1.0e+33_real32
real(kind=real64), public, parameter :: CABLE_OUTPUT_FILL_VALUE_REAL64 = -1.0e+33_real64
character(len=64), private, parameter :: NATIVE_DIM_NAME_PATCH = "patch_native"
character(len=64), private, parameter :: NATIVE_DIM_NAME_PATCH_GLOBAL = "patch_global_native"
character(len=64), private, parameter :: NATIVE_DIM_NAME_PATCH_GRID_CELL = "patch_grid_cell_native"
character(len=64), private, parameter :: NATIVE_DIM_NAME_LAND = "land_native"
character(len=64), private, parameter :: NATIVE_DIM_NAME_LAND_GLOBAL = "land_global_native"

Interfaces

public interface cable_output_variable_t

  • private function cable_output_variable_constructor(field_name, aggregator, netcdf_name, accumulation_frequency, reduction_method, aggregation_method, active, parameter, distributed, restart, patchout, var_type, scale_by, divide_by, offset_by, range, data_shape, metadata) result(this)

    Custom constructor for cable_output_variable_t.

    This is a work-around for older gfortran compilers < 14 which require allocating polymorphic components, like aggregator, before assignment, which prevents the use of the default constructor for cable_output_variable_t with the aggregator argument.

    Arguments

    Type IntentOptional Attributes Name
    character(len=*), intent(in) :: field_name
    class(aggregator_t), intent(in) :: aggregator
    character(len=*), intent(in), optional :: netcdf_name
    character(len=*), intent(in), optional :: accumulation_frequency
    character(len=*), intent(in), optional :: reduction_method
    character(len=*), intent(in), optional :: aggregation_method
    logical, intent(in), optional :: active
    logical, intent(in), optional :: parameter
    logical, intent(in), optional :: distributed
    logical, intent(in), optional :: restart
    logical, intent(in), optional :: patchout
    integer, intent(in), optional :: var_type
    real, intent(in), optional :: scale_by
    real, intent(in), optional :: divide_by
    real, intent(in), optional :: offset_by
    real, intent(in), optional :: range(:)
    type(cable_output_dim_t), intent(in), optional :: data_shape(:)
    type(cable_output_attribute_t), intent(in), optional :: metadata(:)

    Return Value type(cable_output_variable_t)

public interface cable_output_mod_init

  • private module subroutine cable_output_impl_init()

    Module initialisation procedure for cable_output_mod.

    This procedure must be called before any other procedures in cable_output_mod.

    Arguments

    None

public interface cable_output_mod_end

  • private module subroutine cable_output_impl_end()

    Module finalization procedure for cable_output_mod.

    This procedure should be called at the end of the simulation after all output has been written.

    Arguments

    None
  • private module subroutine cable_output_impl_register_output_variables(output_variables)

    Registers output variables with the output module. Note that registering an output variable does not necessarily mean that the variable will be written to an output stream - this can depend on whether the output variable is active, or if it is a restart variable. Output variables should be registered if their associated diagnostic working variables are initialised in the model as this can help provide the information on the diagnostics which are available.

    Arguments

    Type IntentOptional Attributes Name
    type(cable_output_variable_t), intent(in), dimension(:) :: output_variables

    An array of output variable definitions to be registered.

public interface cable_output_init_streams

  • private module subroutine cable_output_impl_init_streams(dels)

    Initialise output streams based on the current output configuration.

    Arguments

    Type IntentOptional Attributes Name
    real, intent(in) :: dels

    The current time step size in seconds.

public interface cable_output_update

  • private module subroutine cable_output_impl_update(time_index, dels, met)

    Updates the time aggregation accumulation for any output variables that are active in an output stream with an accumulation frequency that matches the current time step.

    Arguments

    Type IntentOptional Attributes Name
    integer, intent(in) :: time_index

    The current time step index in the simulation.

    real, intent(in) :: dels

    The current time step size in seconds.

    type(met_type), intent(in) :: met

    Met variables at the current time step to provide informative error messages for CABLE range checks.

public interface cable_output_write

  • private module subroutine cable_output_impl_write(time_index, dels, met, patch, landpt)

    Writes output variables to disk for any output streams with a sampling frequency that matches the current time step.

    Arguments

    Type IntentOptional Attributes Name
    integer, intent(in) :: time_index

    The current time step index in the simulation.

    real, intent(in) :: dels

    The current time step size in seconds.

    type(met_type), intent(in) :: met

    Met variables at the current time step to provide informative error messages for CABLE range checks.

    type(patch_type), intent(in) :: patch(:)

    The patch type instance for performing grid reductions over the patch dimension if required.

    type(land_type), intent(in) :: landpt(:)

    The land type instance for performing grid reductions over the patch dimension if required.

  • private module subroutine cable_output_impl_write_parameters(time_index, patch, landpt)

    Writes non-time varying parameter output variables to disk. This is done on the first time step of the simulation after the output streams have been initialised.

    Arguments

    Type IntentOptional Attributes Name
    integer, intent(in) :: time_index

    The current time step index in the simulation.

    type(patch_type), intent(in) :: patch(:)

    The patch type instance for performing grid reductions over the patch dimension if required.

    type(land_type), intent(in) :: landpt(:)

    The land type instance for performing grid reductions over the patch dimension if required.

public interface cable_output_write_restart

  • private module subroutine cable_output_impl_write_restart(current_time)

    Writes variables to the CABLE restart file. This is done at the end of the simulation.

    Arguments

    Type IntentOptional Attributes Name
    real, intent(in) :: current_time

    Current simulation time


Derived Types

type, public ::  cable_output_dim_t

Type for describing both in-memory and netCDF variable dimensions used by the output module.

Read more…

Components

Type Visibility Attributes Name Initial
character(len=64), private :: dim_name

Dimension name.

integer, private :: dim_size

Dimension size.

Type-Bound Procedures

procedure, public :: name => cable_output_dim_get_name

Return the dimension name.

procedure, public :: size => cable_output_dim_get_size

Return the dimension size.

type, public ::  cable_output_attribute_t

Type for describing string valued netCDF file attributes.

Components

Type Visibility Attributes Name Initial
character(len=64), public :: name

Name of the attribute.

character(len=256), public :: value

Value of the attribute

type, public ::  cable_output_variable_t

Type for describing output variables.

Read more…

Components

Type Visibility Attributes Name Initial
character(len=64), public :: field_name

The name of the variable as used in the CABLE code. This name is used as the netCDF variable name when writing CABLE restart files.

character(len=64), public :: netcdf_name = ""

The name of the variable as it should appear in netCDF output files. If not specified, this defaults to field_name.

character(len=64), public :: accumulation_frequency = "all"

The frequency at which the variable is accumulated when computing time aggregations. Please refer to the cable_timing_frequency_matches procedure for more information on the available frequency settings. If not specified, this defaults to "all", meaning that the variable is accumulated at every CABLE time step.

character(len=64), public :: reduction_method = "none"

The grid cell reduction method to apply to the variable. The allowed reduction methods are specified in allowed_reduction_methods. Please refer to cable_grid_reductions_mod for more details on grid reductions.

character(len=64), public :: aggregation_method = "point"

The time aggregation method to apply when sampling a diagnostic. Please refer to allowed_aggregation_methods for more details on the available aggregation methods.

logical, public :: active = .true.

A flag indicating whether the variable is active in the default output stream.

logical, public :: parameter = .false.

A flag indicating whether the variable is a non-time varying parameter. Variables with parameter = .true. are written once on the first time step via cable_output_write_parameters.

logical, public :: distributed = .true.

A flag indicating whether the variable is distributed across multiple processes. If distributed = .true., the output module will infer an appropriate parallel I/O decomposition from data_shape to perform a distributed write to disk. If distributed = .false., it is assumed by the output module that each process has a copy of the data, and only the data on the root process will be written.

logical, public :: restart = .false.

A flag indicating whether the variable should be written to the CABLE restart file at the end of the run. Please see cable_output_write_restart for more details on how restart variables are written.

logical, public :: patchout = .false.

A flag indicating whether subgrid patch information should be included in the output variable output. If patchout = .true., this has the same effect as setting reduction_method = "none". This is a legacy flag for backward compatibility with the CABLE output namelist settings.

integer, public :: var_type = CABLE_OUTPUT_VAR_TYPE_UNDEFINED

The netCDF variable type using CABLE_NETCDF_<type> constants. If not specified, the output module will use the native type of the data as the netCDF variable type.

real, public :: scale_by = 1.0

A multiplicative factor to apply to the native diagnostic values when writing output.

real, public :: divide_by = 1.0

A divisional factor to apply to the native diagnostic values when writing output.

real, public :: offset_by = 0.0

An additive offset to apply to the native diagnostic values when writing output.

real, private :: range_native(2) = [-huge(0.0), huge(0.0)]

The valid range of physical values for the output variable in the units of the native diagnostic.

real, public, allocatable :: range(:)

The valid range of physical values for the output variable. If a unit conversion is applied to the native diagnostic via the scale_by, divide_by, or offset_by components, the range should be given in the units of the output variable after applying the unit conversion. If unspecified, all values are considered valid.

type(cable_output_dim_t), public, allocatable :: data_shape(:)

An array of in-memory dimensions describing the shape of the variable data. The dimensions must be created via cable_output_get_dimension to ensure that reserved dimension names are handled correctly by the output module. If not specified, the data shape is assumed to be a scalar.

class(aggregator_t), public, allocatable :: aggregator

The aggregator object associated with the diagnostic working variable to be written for this output variable. The aggregator object should not be initialised when registering output variables as this is done internally in the output module the output variable is active.

type(cable_output_attribute_t), public, allocatable :: metadata(:)

NetCDF variable attributes to be written with the variable.

Constructor

private function cable_output_variable_constructor (field_name, aggregator, netcdf_name, accumulation_frequency, reduction_method, aggregation_method, active, parameter, distributed, restart, patchout, var_type, scale_by, divide_by, offset_by, range, data_shape, metadata)

Custom constructor for cable_output_variable_t.

Read more…

Type-Bound Procedures

procedure, private :: get_netcdf_name => cable_output_variable_get_netcdf_name

Return the netCDF variable name, which defaults to field_name if not specified via netcdf_name.

type, private ::  cable_output_stream_t

Type for describing a netCDF file output stream.

Components

Type Visibility Attributes Name Initial
real, public :: previous_write_time = 0.0

The simulation time at which the output stream was last written.

integer, public :: frame = 0

The current index along the unlimited time dimension for the output stream.

character(len=64), public :: sampling_frequency

The frequency at which all output variables in the output stream are aggregated in time and written to disk. Please refer to the cable_timing_frequency_matches procedure for more information on the available frequency settings.

character(len=64), public :: grid_type

The grid type of the output stream. This controls the netCDF dimensions and coordinate variables used to describe non-vertical spatial coordinates in the netCDF file. Common grid types in CABLE include the compressed land grid, or the lat-lon mask grid. The allowed grid types are specified in allowed_grid_types.

character(len=256), public :: file_name

The name of the netCDF file to which the output stream is written.

class(cable_netcdf_file_t), public, allocatable :: output_file

The netCDF file object associated with the output stream.

type(cable_output_variable_t), public, allocatable :: coordinate_variables(:)

An array of coordinate variables to be written to the output stream.

type(cable_output_variable_t), public, allocatable :: output_variables(:)

An array of output variables to be written to the output stream.

type(cable_output_attribute_t), public, allocatable :: metadata(:)

Global netCDF file attributes to be written to the output stream.


Functions

public function cable_output_get_dimension(name) result(dim)

Returns an output variable dimension. This function contains the definitions of all dimensions used to describe the in-memory data shapes of CABLE variables.

Read more…

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: name

Name of the dimension. Please see the implementation of this function for the list of allowed dimension names and their meanings.

Return Value type(cable_output_dim_t)

The output dimension object corresponding to the requested dimension name.

private elemental function cable_output_dim_get_name(this) result(name)

Return the dimension name.

Arguments

Type IntentOptional Attributes Name
class(cable_output_dim_t), intent(in) :: this

Return Value character(len=64)

private elemental function cable_output_dim_get_size(this) result(size)

Return the dimension size.

Arguments

Type IntentOptional Attributes Name
class(cable_output_dim_t), intent(in) :: this

Return Value integer

private function cable_output_variable_constructor(field_name, aggregator, netcdf_name, accumulation_frequency, reduction_method, aggregation_method, active, parameter, distributed, restart, patchout, var_type, scale_by, divide_by, offset_by, range, data_shape, metadata) result(this)

Custom constructor for cable_output_variable_t.

Read more…

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: field_name
class(aggregator_t), intent(in) :: aggregator
character(len=*), intent(in), optional :: netcdf_name
character(len=*), intent(in), optional :: accumulation_frequency
character(len=*), intent(in), optional :: reduction_method
character(len=*), intent(in), optional :: aggregation_method
logical, intent(in), optional :: active
logical, intent(in), optional :: parameter
logical, intent(in), optional :: distributed
logical, intent(in), optional :: restart
logical, intent(in), optional :: patchout
integer, intent(in), optional :: var_type
real, intent(in), optional :: scale_by
real, intent(in), optional :: divide_by
real, intent(in), optional :: offset_by
real, intent(in), optional :: range(:)
type(cable_output_dim_t), intent(in), optional :: data_shape(:)
type(cable_output_attribute_t), intent(in), optional :: metadata(:)

Return Value type(cable_output_variable_t)

private elemental function cable_output_variable_get_netcdf_name(this) result(netcdf_name)

Return the netCDF variable name, which defaults to field_name if not specified via netcdf_name.

Arguments

Type IntentOptional Attributes Name
class(cable_output_variable_t), intent(in) :: this

Return Value character(len=64)