cable_output_mod Module

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

The output system writes 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.

What is written is described by an output configuration file (YAML) made of streams (a file and a write frequency) and the variables directed to them. See the user guide for the file format.

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. Output variable definitions are built from the output catalogue and the bindings to model state (see cable_output_catalogue_mod) and registered with cable_output_register_output_variables. A definition (cable_output_variable_definition_t) says what a variable is; it does not say whether or how it is written. Registering a variable does not mean it is written: that is decided by the configuration. Variables that the current model configuration cannot provide are registered as unavailable.

  3. The output configuration is read and checked (see cable_output_config_mod), then cable_output_init_streams creates the files, defines their contents and writes their coordinate variables. Every use of a definition (cable_output_variable_t) owns its own aggregator, so one variable can appear in several streams.

  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 the output variables, followed by cable_output_write, which writes the streams whose write frequency matches 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 definitions that have a restart name, as they are.

  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(4) = [character(32)::"none", "grid_cell_average", "first_tile_on_cell", "dominant_tile"]

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) = [character(32)::"instant", "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"
integer, public, parameter :: CABLE_OUTPUT_CONFIG_LENGTH = 256
character(len=*), public, parameter :: CABLE_OUTPUT_DEFAULT_NETCDF_NAME = "{field_name}"

Interfaces

public interface cable_output_variable_t

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

    Constructor for cable_output_variable_t.

    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 :: parameter
    logical, intent(in), optional :: distributed
    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 function cable_output_variable_from_definition(definition, aggregation, reduction, netcdf_name, metadata) result(this)

    Constructs the use of a variable definition described by the arguments: the definition says what the variable is, the arguments say how it is written. The result owns its own copy of the aggregator, so one definition can be used in several streams.

    Arguments

    Type IntentOptional Attributes Name
    type(cable_output_variable_definition_t), intent(in) :: definition
    character(len=*), intent(in) :: aggregation

    One of allowed_aggregation_methods.

    character(len=*), intent(in) :: reduction

    One of allowed_reduction_methods.

    character(len=*), intent(in) :: netcdf_name

    Name of the variable in the NetCDF file.

    type(cable_output_attribute_t), intent(in), optional :: metadata(:)

    Attributes to add to those of the definition.

    Return Value type(cable_output_variable_t)

public interface cable_output_binding_t

  • private function cable_output_binding_constructor(name, aggregator, scale_by, divide_by, offset_by, range, available) result(this)

    Constructor for cable_output_binding_t.

    Arguments

    Type IntentOptional Attributes Name
    character(len=*), intent(in) :: name
    class(aggregator_t), intent(in), optional :: aggregator

    Absent for variables that do not exist in the current model configuration.

    real, intent(in), optional :: scale_by
    real, intent(in), optional :: divide_by
    real, intent(in), optional :: offset_by
    real, intent(in), optional :: range(:)
    logical, intent(in), optional :: available

    Return Value type(cable_output_binding_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_definitions(definitions)

    Registers output variable definitions with the output module. A definition says what a variable is; whether and how it is written is decided by the output configuration passed to cable_output_init_streams.

    Arguments

    Type IntentOptional Attributes Name
    type(cable_output_variable_definition_t), intent(in), dimension(:) :: definitions

    The output variable definitions to register.

public interface cable_output_build_streams

  • private module function cable_output_impl_build_streams(config, definitions, grid_type) result(streams)

    Works out which files the configuration produces and which variables go into each, without creating any files.

    Arguments

    Type IntentOptional Attributes Name
    type(cable_output_config_t), intent(in) :: config

    The output configuration.

    type(cable_output_variable_definition_t), intent(in) :: definitions(:)

    The output variable definitions the configuration refers to.

    character(len=*), intent(in) :: grid_type

    The grid type of every output file, one of allowed_grid_types.

    Return Value type(cable_output_stream_t), allocatable, (:)

public interface cable_output_init_streams

  • private module subroutine cable_output_impl_init_streams_from_config(config, grid_type, dels)

    Creates the output files described by the configuration, defines their contents and writes their coordinate variables. Definitions must have been registered first.

    Arguments

    Type IntentOptional Attributes Name
    type(cable_output_config_t), intent(in) :: config

    The output configuration.

    character(len=*), intent(in) :: grid_type

    The grid type of every output file, one of allowed_grid_types.

    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 one use of an output variable in an output stream.

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 = "timestep"

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 "timestep", 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 = "instant"

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

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, public :: range(2) = [-huge(0.0), huge(0.0)]

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 by the caller; this is done internally in the output module when the stream containing the variable is started.

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, parameter, distributed, var_type, scale_by, divide_by, offset_by, range, data_shape, metadata)

Constructor for cable_output_variable_t.

private function cable_output_variable_from_definition (definition, aggregation, reduction, netcdf_name, metadata)

Constructs the use of a variable definition described by the arguments: the definition says what the variable is, the arguments say how it is written. The result owns its own copy of the aggregator, so one definition can be used in several streams.

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, public ::  cable_output_binding_t

Ties an output catalogue name to the CABLE model state it describes.

Read more…

Components

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

Catalogue name of the variable this binding belongs to.

class(aggregator_t), public, allocatable :: aggregator

Aggregator wrapping the model working variable. Unallocated if the variable is not available.

real, public :: scale_by = 1.0

Multiply the working variable by this to obtain the output value.

real, public :: divide_by = 1.0

Divide the working variable by this to obtain the output value.

real, public :: offset_by = 0.0

Add this to the working variable to obtain the output value.

real, public, allocatable :: range(:)

Valid range of the variable in output units. Unallocated if unchecked.

logical, public :: available = .true.

Whether the variable exists in the current model configuration.

Constructor

private function cable_output_binding_constructor (name, aggregator, scale_by, divide_by, offset_by, range, available)

Constructor for cable_output_binding_t.

Everything about an output variable that does not depend on how it is written: what it is, where its data comes from and how it is converted. Aggregation, reduction, frequency, stream and NetCDF name are chosen per use by the output configuration.

Components

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

User-facing name, also the default NetCDF variable name.

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

Name used in restart files. Empty if the variable is not restarted.

logical, public :: outputtable = .true.

False for variables that are only written to restart files.

logical, public :: available = .true.

Whether the variable exists in the current model configuration.

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

In-memory shape of the working variable. Empty for scalars.

integer, public :: var_type = CABLE_OUTPUT_VAR_TYPE_UNDEFINED

NetCDF type of the output.

logical, public :: parameter = .false.

True for non-time-varying variables, written once without a time axis.

logical, public :: distributed = .true.

False if every process holds a full copy of the data.

character(len=64), public :: native_frequency = "timestep"

How often the model itself updates the working variable.

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

Convenience group the variable belongs to. Empty for none.

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

Convenience module the variable belongs to. Empty for none.

real, public :: scale_by = 1.0
real, public :: divide_by = 1.0
real, public :: offset_by = 0.0
real, public :: range(2) = [-huge(0.0), huge(0.0)]

Valid range in the units of the working variable.

class(aggregator_t), public, allocatable :: aggregator

Aggregator wrapping the working variable. Copied for each use.

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

NetCDF variable attributes, e.g. units and long_name.

type, public ::  cable_output_stream_config_t

Settings of one output stream.

Components

Type Visibility Attributes Name Initial
integer, public :: stream_id = 0
character(len=CABLE_OUTPUT_CONFIG_LENGTH), public :: file_name = ""
character(len=16), public :: frequency = ""
character(len=CABLE_OUTPUT_CONFIG_LENGTH), public :: netcdf_name = CABLE_OUTPUT_DEFAULT_NETCDF_NAME

Template for NetCDF variable names in this stream.

logical, public :: shuffle = .true.
integer, public :: compression_level = 1

Deflate level 0 to 9. Zero means no compression.

logical, public :: separate_file_per_variable = .false.
type(cable_output_attribute_t), public, allocatable :: metadata(:)

Global attributes, with templates filled in.

type, public ::  cable_output_variable_config_t

One requested use of an output variable, after expansion of groups and modules.

Components

Type Visibility Attributes Name Initial
character(len=64), public :: field_name = ""
integer, public :: stream_id = 0
character(len=16), public :: aggregation = ""
character(len=32), public :: reduction = "none"
character(len=CABLE_OUTPUT_CONFIG_LENGTH), public :: netcdf_name = ""

NetCDF variable name, with templates filled in.

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

Variable attributes from the file, with templates filled in.

type, public ::  cable_output_config_t

Components

Type Visibility Attributes Name Initial
type(cable_output_stream_config_t), public, allocatable :: streams(:)
type(cable_output_variable_config_t), public, allocatable :: variables(:)

type, public ::  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.

logical, public :: shuffle = .false.

Whether to apply the shuffle filter to the variables in the file.

integer, public :: compression_level = 0

Deflate level 0 to 9 for the variables in the file. Zero means no compression.

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, parameter, distributed, var_type, scale_by, divide_by, offset_by, range, data_shape, metadata) result(this)

Constructor for cable_output_variable_t.

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 :: parameter
logical, intent(in), optional :: distributed
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 function cable_output_binding_constructor(name, aggregator, scale_by, divide_by, offset_by, range, available) result(this)

Constructor for cable_output_binding_t.

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: name
class(aggregator_t), intent(in), optional :: aggregator

Absent for variables that do not exist in the current model configuration.

real, intent(in), optional :: scale_by
real, intent(in), optional :: divide_by
real, intent(in), optional :: offset_by
real, intent(in), optional :: range(:)
logical, intent(in), optional :: available

Return Value type(cable_output_binding_t)

private function cable_output_variable_from_definition(definition, aggregation, reduction, netcdf_name, metadata) result(this)

Constructs the use of a variable definition described by the arguments: the definition says what the variable is, the arguments say how it is written. The result owns its own copy of the aggregator, so one definition can be used in several streams.

Arguments

Type IntentOptional Attributes Name
type(cable_output_variable_definition_t), intent(in) :: definition
character(len=*), intent(in) :: aggregation

One of allowed_aggregation_methods.

character(len=*), intent(in) :: reduction

One of allowed_reduction_methods.

character(len=*), intent(in) :: netcdf_name

Name of the variable in the NetCDF file.

type(cable_output_attribute_t), intent(in), optional :: metadata(:)

Attributes to add to those of the definition.

Return Value type(cable_output_variable_t)

public function cable_output_restart_variable(definition) result(this)

Constructs the variable that writes a definition to the restart file: the working variable is written as it is, without aggregation or reduction, under its restart name.

Arguments

Type IntentOptional Attributes Name
type(cable_output_variable_definition_t), intent(in) :: definition

Return Value type(cable_output_variable_t)

public function cable_output_grid_type(output_grid, met_grid) result(grid_type)

The grid type of the output files, from the output%grid setting and the grid type of the meteorological forcing.

Arguments

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

default, land, mask or ALMA.

character(len=*), intent(in) :: met_grid

land or mask.

Return Value character(len=32)

private pure function cell_methods(aggregation, reduction) result(text)

The CF cell_methods attribute for a variable aggregated and reduced as given.

Arguments

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

Return Value character(len=:), allocatable

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)