diff --git a/dev/.documenter-siteinfo.json b/dev/.documenter-siteinfo.json
index fe0edec..aa56025 100644
--- a/dev/.documenter-siteinfo.json
+++ b/dev/.documenter-siteinfo.json
@@ -1 +1 @@
-{"documenter":{"julia_version":"1.6.7","generation_timestamp":"2024-11-30T17:16:07","documenter_version":"1.8.0"}}
\ No newline at end of file
+{"documenter":{"julia_version":"1.6.7","generation_timestamp":"2024-12-05T17:06:39","documenter_version":"1.8.0"}}
\ No newline at end of file
diff --git a/dev/CreateInitializeLoop/index.html b/dev/CreateInitializeLoop/index.html
index a9d43d5..8ac912d 100644
--- a/dev/CreateInitializeLoop/index.html
+++ b/dev/CreateInitializeLoop/index.html
@@ -1,2 +1,2 @@
-
A YAML format configuration file defines both the model structure (spatial domains containing biogeochemical variables and reactions that operate on them) and model parameter values. Reactions (subtypes of AbstractReaction) are identified by Type name (without module prefix) in the configuration file.
To create the model, the numerical solver or host should call create_model_from_config which reads the configuration file, and then:
creates model Domains and Reactions (subtypes of AbstractReaction), applying any Parameters settings from the parameters: sections in the config file.
store sorted lists of ReactionMethods and corresponding Variable array accessors in the ModelData struct. A ReactionMethod may include a prepare function to include additional buffers etc.
call create_dispatch_methodlists to compile default model-wide lists of initialize and do methods + corresponding Variable array accessors and CellRanges. This is stored as the in the dispatchlists_all of the ModelData struct.
call dispatch_setup with attribute_name = :setup, which calls Reaction setup methods (registered by add_method_setup!) to initialise any internal Reaction state and any non-state Variables (eg grid variables).
To initialise state Variables and perform any Reaction-specific initialisation, the numerical solver or host should:
call dispatch_setup with attribute_name = :norm_value. These Reaction setup methods should set state Variables according to the :norm_value Variable attribute (which can be set in the variable_attributes: section of the config file). Reactions may also use these values internally.
optionally (if normalisation values are required by a numerical solver), copy the Variable normalisation values from the arrays in ModelData to the solver.
optionally call dispatch_setup with attribute_name = :initial_value to set state Variables according to the :initial_value Variable attribute (which can be set in the variable_attributes: section of the config file).
The default initialisation described above calculates the model derivative for all model Reactions for all Domains, using the cellranges_all, and dispatchlists_all fields of the ModelData struct. A custom Vector of CellRanges can be used to select a subset of ReactionMethods by Domain and operatorID, eg to implement operator splitting. Tiles within Domain eg to implement Domain decomposition for a multithreaded model can be defined by specifying CellRanges with a subset of cell indices within Domains.
The custom Vector of CellRanges should then be supplied to
To use with a multithreaded solver eg for a spatially tiled model:
Set threadsafe=true when calling create_modeldata. The subsequent call to allocate_variables! will then allocate Julia Threads.Atomic variables for PALEO Variables with attribute atomic: = true (usually scalar accumulator variables for totals etc).
Supply a method_barrier implementing a thread barrier function to initialize_reactiondata!. Reactions are sorted into groups, where each group has no dependencies and later groups depend on earlier ones. The method_barrier will be inserted between these groups of independent Reactions.
Set eltype when calling create_modeldata to the appropriate dual number type for a (forward) automatic differentation implementation. All model arrays are held in the created ModelData struct and multiple ModelData instances can be created, allowing a combination of eg AD Jacobian and standard derivative calculations with different array types.
Settings
This document was generated with Documenter.jl version 1.8.0 on Saturday 30 November 2024. Using Julia version 1.6.7.
A YAML format configuration file defines both the model structure (spatial domains containing biogeochemical variables and reactions that operate on them) and model parameter values. Reactions (subtypes of AbstractReaction) are identified by Type name (without module prefix) in the configuration file.
To create the model, the numerical solver or host should call create_model_from_config which reads the configuration file, and then:
creates model Domains and Reactions (subtypes of AbstractReaction), applying any Parameters settings from the parameters: sections in the config file.
store sorted lists of ReactionMethods and corresponding Variable array accessors in the ModelData struct. A ReactionMethod may include a prepare function to include additional buffers etc.
call create_dispatch_methodlists to compile default model-wide lists of initialize and do methods + corresponding Variable array accessors and CellRanges. This is stored as the in the dispatchlists_all of the ModelData struct.
call dispatch_setup with attribute_name = :setup, which calls Reaction setup methods (registered by add_method_setup!) to initialise any internal Reaction state and any non-state Variables (eg grid variables).
To initialise state Variables and perform any Reaction-specific initialisation, the numerical solver or host should:
call dispatch_setup with attribute_name = :norm_value. These Reaction setup methods should set state Variables according to the :norm_value Variable attribute (which can be set in the variable_attributes: section of the config file). Reactions may also use these values internally.
optionally (if normalisation values are required by a numerical solver), copy the Variable normalisation values from the arrays in ModelData to the solver.
optionally call dispatch_setup with attribute_name = :initial_value to set state Variables according to the :initial_value Variable attribute (which can be set in the variable_attributes: section of the config file).
The default initialisation described above calculates the model derivative for all model Reactions for all Domains, using the cellranges_all, and dispatchlists_all fields of the ModelData struct. A custom Vector of CellRanges can be used to select a subset of ReactionMethods by Domain and operatorID, eg to implement operator splitting. Tiles within Domain eg to implement Domain decomposition for a multithreaded model can be defined by specifying CellRanges with a subset of cell indices within Domains.
The custom Vector of CellRanges should then be supplied to
To use with a multithreaded solver eg for a spatially tiled model:
Set threadsafe=true when calling create_modeldata. The subsequent call to allocate_variables! will then allocate Julia Threads.Atomic variables for PALEO Variables with attribute atomic: = true (usually scalar accumulator variables for totals etc).
Supply a method_barrier implementing a thread barrier function to initialize_reactiondata!. Reactions are sorted into groups, where each group has no dependencies and later groups depend on earlier ones. The method_barrier will be inserted between these groups of independent Reactions.
Set eltype when calling create_modeldata to the appropriate dual number type for a (forward) automatic differentation implementation. All model arrays are held in the created ModelData struct and multiple ModelData instances can be created, allowing a combination of eg AD Jacobian and standard derivative calculations with different array types.
Settings
This document was generated with Documenter.jl version 1.8.0 on Thursday 5 December 2024. Using Julia version 1.6.7.
A PALEO Model contains Domains, each of which contain Variables defining Fields containing Data arrays, and Reactions with ReactionMethods that operate on the Variables to calculate model time evolution.
The PALEOboxes Julia package (abbreviated to PB in the PALEO code) implements a coupler that provides a unified mechanism for
‘low-level’ coupling (e.g. linking individual redox Reactions within a Domain), on which is built
‘module-level’ coupling (linking e.g. atmosphere and ocean components) based on standardising names for communicating fluxes, and which enables
separation of biogeochemical reaction and transport.
A YAML format configuration file then defines both the model structure (spatial domains containing biogeochemical variables and reactions that operate on them) and model parameter values.
The PALEOboxes object model illustrated by a fragment of a marine biogeochemical model representing two phytoplankton populations competing for the same nutrient. The Ocean Domain contains two Reactions phytA and phytB, and three state Variables P, phytA and phytB with paired time derivatives P_sms, phytA_sms and phytB_sms. The Reactions are both instances of the same class PaleoReactionSimplePhyt, with a Parameter k_P, and a single method. The ReactionMethod defines interactions with a nutrient P via a Variable Dependency P and a Variable Contributor P_sms, and a population represented by Variable Dependency phyt and Contributor phyt_sms. P and P_sms from each PaleoReactionSimplePhyt instance are linked at run time to the same Domain Variables P and P_sms, using the default names from the PaleoReactionSimplePhyt code. phyt and phyt_sms are renamed in the configuration file to two different pairs of Domain Variables phytA, phytA_sms and phytB, phytB_sms, hence representing two distinct phytoplankton populations.
Reactions contain Parameters and are implemented as subtypes of AbstractReaction along with associated methods. ReactionMethods and VariableReactions are created by Reactions during model initialization. All PALEO model time evolution (including external prescribed forcing, biogeochemistry, transport within eg an ocean Domain) is then implemented by the ReactionMethods as they are called during the model main loop.
Variables defined as VariableReactions are then linked within (or across) Domains, creating corresponding VariableDomains. Linking of Variables is based on names (as text strings). Default names are encoded in the Reaction implementations (with standard names for e.g. chemical species such as O2, DIC marine tracers), and can be overridden in the configuration file. This is analogous to the use of ‘dummy variables’ in a Fortran or Python function call, and allows (i) a combination of default names for commonly-used biogeochemical variables (‘P’, ‘SO4’ etc), with (ii) renamed variables to allow multiple Reaction instances (e.g. two phytoplankton populations with state variable names and parameter choices for the same Reaction implementation), or (iii) enable rerouting of fluxes and dependencies that are specific to the model configuration, or (iv) sort out name conflicts where no default names have been established.
Variables are classified into two pairings: Properties with Dependencies (shown shaded green in Figure 1, linked at run time to DomainVariableDomPropDeps), or flux Targets and Contributors (shaded pink in Figure 1, linked at run-time to DomainVariableDomContribTargets). This classification retains flexibility while providing sufficient information to allow automatic detection of errors in model specification (for example, a Dependency with no Property, or a flux Contributor with no Target), and automatic scheduling of Reactions within the model main loop (as a Reaction that defines a Property must be executed before a Reaction that Depends on this property).
Variables can specify metadata as an extensible list of attributes which can then be queried (using get_attribute) and filtered on (using get_variables) during model configuration and initialisation. This enables the labelling of groups of variables (e.g. the :advect and :vertical_motion attributes are used by a Reaction implementing ocean transport to identify those state variables representing solutes that should be transported; the :vfunction attribute is used by numerical solvers to identify state variables and their time derivatives).
Domains may contain a Grid (a subtype of AbstractMesh) to define a spatially-resolved Domain containing multiple cells.
Three-dimensional Domains (eg ocean) are associated with two-dimensional boundary Domains (eg oceansurface, oceanfloor), and also provide Subdomains (subtypes of AbstractSubdomain, eg ocean.oceansurface, ocean.oceanfloor) that specify the subset of 3D ocean cells adjacent to the 2D boundaries.
Variables contain Fields which represent data (a subtype of AbstractData defined by the :field_data ttribute) in a function space (a subtype of AbstractSpace defined by the :space attribute).
The AbstractSpace subtype (see Spaces) can define a per-Domain (ScalarSpace) or per-cell (CellSpace) quantity, where the number of cells is defined by the Domain grid.
Defining and coupling spatial Domains. The four Domains atm, oceansurface, ocean and fluxAtmOceansurface are defined in the model configuration file. The first three of these contain arbitrary biogeochemical Reactions and Variables. Domain fluxAtmOceansurface contains only a FluxTarget Reaction and a set of Target Variables fluxO2. Exchange fluxes are accumulated into these flux Variables (in this case, produced by air-sea exchange reactions in the oceansurface Domain), and then redistributed to atm and ocean by the FluxTransfer Reactions taking account of mapping between Domain dimensions.
Variable text names may be referred to from other Domains by prefixing with Domain and Subdomain names (eg ocean.P_conc links to the 3D ocean interior Variable P_conc, ocean.oceansurface.O2_conc links to the ocean oxygen concentration for the 2D subset of ocean cells adjacent to the oceansurface boundary).
Examples of model configurations with different reaction/transport partitioning: a) a configuration with offline transport and forcing provided by Reactions within the PALEO framework. The only external dependencies are state variables and derivatives, with time integration provided by a standard ODE solver such as CVODE and the overall model workflow (initialisation, solution, output) managed by the PALEOmodel package. b) an ocean-only model embedded in a GCM host which provides transport and physical properties such as temperature and sequences the model workflow.
The :vfunction Variable attribute is used to identify pairs of state variables (labelled with :vfunction = VF_StateExplicit) and their corresponding time derivatives (labelled with :vfunction = VF_Deriv). Algebraic constraints are defined by Variables labelled with :vfunction = VF_Constraint, with a corresponding number of state variables labelled with :vfunction = VF_State. Implicit variables are defined by pairs of variables and time derivatives labelled with :vfunction = VF_Total and :vfunction = VF_Deriv, with a corresponding number of state variables labelled with :vfunction = VF_State.
To access variables, a numerical ODE or DAE solver can use VariableAggregator to implement a high-level interface to aggregated lists. A host dynamical model can alternatively use get_variables during model configuration and initialisation to link to individual host data arrays.
The abstractions described above enable a natural separation of biogeochemical reaction and transport, which can then either be provided by a host dynamical model e.g. implemented in C or Fortran, or as offline transport implemented by PALEO “reactions” within the framework (Figure 3). This enables both rapid, interactive development and experimentation in a PC/workstation environment using offline transport, and deployment of the same model code as a component embedded in a larger GCM model.
Settings
This document was generated with Documenter.jl version 1.8.0 on Saturday 30 November 2024. Using Julia version 1.6.7.
A PALEO Model contains Domains, each of which contain Variables defining Fields containing Data arrays, and Reactions with ReactionMethods that operate on the Variables to calculate model time evolution.
The PALEOboxes Julia package (abbreviated to PB in the PALEO code) implements a coupler that provides a unified mechanism for
‘low-level’ coupling (e.g. linking individual redox Reactions within a Domain), on which is built
‘module-level’ coupling (linking e.g. atmosphere and ocean components) based on standardising names for communicating fluxes, and which enables
separation of biogeochemical reaction and transport.
A YAML format configuration file then defines both the model structure (spatial domains containing biogeochemical variables and reactions that operate on them) and model parameter values.
The PALEOboxes object model illustrated by a fragment of a marine biogeochemical model representing two phytoplankton populations competing for the same nutrient. The Ocean Domain contains two Reactions phytA and phytB, and three state Variables P, phytA and phytB with paired time derivatives P_sms, phytA_sms and phytB_sms. The Reactions are both instances of the same class PaleoReactionSimplePhyt, with a Parameter k_P, and a single method. The ReactionMethod defines interactions with a nutrient P via a Variable Dependency P and a Variable Contributor P_sms, and a population represented by Variable Dependency phyt and Contributor phyt_sms. P and P_sms from each PaleoReactionSimplePhyt instance are linked at run time to the same Domain Variables P and P_sms, using the default names from the PaleoReactionSimplePhyt code. phyt and phyt_sms are renamed in the configuration file to two different pairs of Domain Variables phytA, phytA_sms and phytB, phytB_sms, hence representing two distinct phytoplankton populations.
Reactions contain Parameters and are implemented as subtypes of AbstractReaction along with associated methods. ReactionMethods and VariableReactions are created by Reactions during model initialization. All PALEO model time evolution (including external prescribed forcing, biogeochemistry, transport within eg an ocean Domain) is then implemented by the ReactionMethods as they are called during the model main loop.
Variables defined as VariableReactions are then linked within (or across) Domains, creating corresponding VariableDomains. Linking of Variables is based on names (as text strings). Default names are encoded in the Reaction implementations (with standard names for e.g. chemical species such as O2, DIC marine tracers), and can be overridden in the configuration file. This is analogous to the use of ‘dummy variables’ in a Fortran or Python function call, and allows (i) a combination of default names for commonly-used biogeochemical variables (‘P’, ‘SO4’ etc), with (ii) renamed variables to allow multiple Reaction instances (e.g. two phytoplankton populations with state variable names and parameter choices for the same Reaction implementation), or (iii) enable rerouting of fluxes and dependencies that are specific to the model configuration, or (iv) sort out name conflicts where no default names have been established.
Variables are classified into two pairings: Properties with Dependencies (shown shaded green in Figure 1, linked at run time to DomainVariableDomPropDeps), or flux Targets and Contributors (shaded pink in Figure 1, linked at run-time to DomainVariableDomContribTargets). This classification retains flexibility while providing sufficient information to allow automatic detection of errors in model specification (for example, a Dependency with no Property, or a flux Contributor with no Target), and automatic scheduling of Reactions within the model main loop (as a Reaction that defines a Property must be executed before a Reaction that Depends on this property).
Variables can specify metadata as an extensible list of attributes which can then be queried (using get_attribute) and filtered on (using get_variables) during model configuration and initialisation. This enables the labelling of groups of variables (e.g. the :advect and :vertical_motion attributes are used by a Reaction implementing ocean transport to identify those state variables representing solutes that should be transported; the :vfunction attribute is used by numerical solvers to identify state variables and their time derivatives).
Domains may contain a Grid (a subtype of AbstractMesh) to define a spatially-resolved Domain containing multiple cells.
Three-dimensional Domains (eg ocean) are associated with two-dimensional boundary Domains (eg oceansurface, oceanfloor), and also provide Subdomains (subtypes of AbstractSubdomain, eg ocean.oceansurface, ocean.oceanfloor) that specify the subset of 3D ocean cells adjacent to the 2D boundaries.
Variables contain Fields which represent data (a subtype of AbstractData defined by the :field_data ttribute) in a function space (a subtype of AbstractSpace defined by the :space attribute).
The AbstractSpace subtype (see Spaces) can define a per-Domain (ScalarSpace) or per-cell (CellSpace) quantity, where the number of cells is defined by the Domain grid.
Defining and coupling spatial Domains. The four Domains atm, oceansurface, ocean and fluxAtmOceansurface are defined in the model configuration file. The first three of these contain arbitrary biogeochemical Reactions and Variables. Domain fluxAtmOceansurface contains only a FluxTarget Reaction and a set of Target Variables fluxO2. Exchange fluxes are accumulated into these flux Variables (in this case, produced by air-sea exchange reactions in the oceansurface Domain), and then redistributed to atm and ocean by the FluxTransfer Reactions taking account of mapping between Domain dimensions.
Variable text names may be referred to from other Domains by prefixing with Domain and Subdomain names (eg ocean.P_conc links to the 3D ocean interior Variable P_conc, ocean.oceansurface.O2_conc links to the ocean oxygen concentration for the 2D subset of ocean cells adjacent to the oceansurface boundary).
Examples of model configurations with different reaction/transport partitioning: a) a configuration with offline transport and forcing provided by Reactions within the PALEO framework. The only external dependencies are state variables and derivatives, with time integration provided by a standard ODE solver such as CVODE and the overall model workflow (initialisation, solution, output) managed by the PALEOmodel package. b) an ocean-only model embedded in a GCM host which provides transport and physical properties such as temperature and sequences the model workflow.
The :vfunction Variable attribute is used to identify pairs of state variables (labelled with :vfunction = VF_StateExplicit) and their corresponding time derivatives (labelled with :vfunction = VF_Deriv). Algebraic constraints are defined by Variables labelled with :vfunction = VF_Constraint, with a corresponding number of state variables labelled with :vfunction = VF_State. Implicit variables are defined by pairs of variables and time derivatives labelled with :vfunction = VF_Total and :vfunction = VF_Deriv, with a corresponding number of state variables labelled with :vfunction = VF_State.
To access variables, a numerical ODE or DAE solver can use VariableAggregator to implement a high-level interface to aggregated lists. A host dynamical model can alternatively use get_variables during model configuration and initialisation to link to individual host data arrays.
The abstractions described above enable a natural separation of biogeochemical reaction and transport, which can then either be provided by a host dynamical model e.g. implemented in C or Fortran, or as offline transport implemented by PALEO “reactions” within the framework (Figure 3). This enables both rapid, interactive development and experimentation in a PC/workstation environment using offline transport, and deployment of the same model code as a component embedded in a larger GCM model.
Settings
This document was generated with Documenter.jl version 1.8.0 on Thursday 5 December 2024. Using Julia version 1.6.7.
diff --git a/dev/DomainsVariablesFields/index.html b/dev/DomainsVariablesFields/index.html
index 06702f4..b6bbd77 100644
--- a/dev/DomainsVariablesFields/index.html
+++ b/dev/DomainsVariablesFields/index.html
@@ -1,9 +1,9 @@
-Domains, Variables, Fields, and Data arrays. · PALEOboxes Documentation
A Model contains Domains, each of which contain Variables defining Fields which contain Data arrays, and Reactions with ReactionMethods that operate on the Fields to calculate model time evolution.
A model region containing Variables and Reactions that act on them.
Domain spatial size is defined by grid, which may be nothing to define a scalar Domain, or an AbstractMesh to define a spatially-resolved Domain with multiple cells.
Named data_dims may be set by set_data_dimension! to allow Variables with additional non-spatial dimensions, eg to represent quantities on a wavelength grid.
nD grid with netcdf CF1.0 coordinates, using Vectors for PALEO internal representation of Variables, with a mapping linear indices <–> some subset of grid indices.
The linear indices mapping should be set with set_linear_index. Conversion of Field values between the PALEO internal representation (a Vector with a linear index) and a Cartesian Array with multiple dimensions (for import and export of model output) is then implemented by cartesian_to_internal and internal_to_cartesian.
Fields
ncells::Int64: number of cells in Domain = length(linear_index) (may be subset of total points in prod(dims))
dimnames::Vector{String}: names of dimensions (ordered list)
dims::Vector{Int}: sizes of dimensions (ordered list)
coords::Vector{Vector{Float64}}: attached cell-centre coordinates for each dimension (ordered list)
coords_edges::Vector{Vector{Float64}}: attached cell-edge coordinates for each dimension (ordered list)
Defines the relationship between two PB.Domains by mapping indices in one Domain to related indices in the other, eg interior cells adjacent to a boundary.
subdomain_indices(subdomain::InteriorSubdomain) -> indices
Return indices to access Variables in a boundary Domain from interior Domain (will have missing entries where interior cells do not correspond to boundary)
Return the subset of values given by selectargs (Grid-specific keywords eg cell=, column=, ...) and corresponding dimensions (with attached coordinates).
internalvalues are transformed if needed from internal Field representation as a Vector length ncells, to an Array (2D if neither i, j arguments present, 1D if i or j present, 0D ie one cell if both present)
internalvalues are transformed if needed from internal Field representation as a Vector length ncells, to an Array (3D if neither i, j, k arguments present, 2D if one of i, j or k present, 1D if two present, 0D ie one cell if i, j, k all specified).
Grids may define name dimensions and attach coordinates for the convenience of output visualisation. Any coordinate information required by Reactions should be supplied as Variables.
PALEO Variables exist in Domains and represent biogeochemical or other quantities. They are defined by Reactions as VariableReactions which are then linked to create VariableDomains, and contain Fields which represent data (a subtype of AbstractData) in a function space (a subtype of AbstractSpace) with dimensions defined by the Domain grid (a subtype of AbstractMesh)
Dataflow dependency between Variables is represented by two pairings:
Model (Domain) VariableDomain linking a single VariableReaction{VT_ReactTarget} to multiple VariableReaction{VT_ReactContributor} and VariableReaction{VT_ReactDependency}.
Definition for Variable attribute name. Defines a data type T, a default_value, required (true if always present ie added with default_value when Variable is created), units, and an optional description.
Note that Variable attributes are stored as a per-Variable Dict(name => value), these definitions are only used to provide defaults, check types, and provide descriptive metadata.
ParseFromString should usually be Nothing: a value of Type T is then required when calling set_attribute!. If ParseFromString is true, then set_attribute! will accept an AbstractString and call Base.parse(T, strvalue) to convert to T. This allows eg an enum-valued Attribute to be defined by Attribute{EnumType, true} and implementing parse(EnumType, rawvalue::AbstractString)
A Model contains Domains, each of which contain Variables defining Fields which contain Data arrays, and Reactions with ReactionMethods that operate on the Fields to calculate model time evolution.
A model region containing Variables and Reactions that act on them.
Domain spatial size is defined by grid, which may be nothing to define a scalar Domain, or an AbstractMesh to define a spatially-resolved Domain with multiple cells.
Named data_dims may be set by set_data_dimension! to allow Variables with additional non-spatial dimensions, eg to represent quantities on a wavelength grid.
nD grid with netcdf CF1.0 coordinates, using Vectors for PALEO internal representation of Variables, with a mapping linear indices <–> some subset of grid indices.
The linear indices mapping should be set with set_linear_index. Conversion of Field values between the PALEO internal representation (a Vector with a linear index) and a Cartesian Array with multiple dimensions (for import and export of model output) is then implemented by cartesian_to_internal and internal_to_cartesian.
Fields
ncells::Int64: number of cells in Domain = length(linear_index) (may be subset of total points in prod(dims))
dimnames::Vector{String}: names of dimensions (ordered list)
dims::Vector{Int}: sizes of dimensions (ordered list)
coords::Vector{Vector{Float64}}: attached cell-centre coordinates for each dimension (ordered list)
coords_edges::Vector{Vector{Float64}}: attached cell-edge coordinates for each dimension (ordered list)
Defines the relationship between two PB.Domains by mapping indices in one Domain to related indices in the other, eg interior cells adjacent to a boundary.
subdomain_indices(subdomain::InteriorSubdomain) -> indices
Return indices to access Variables in a boundary Domain from interior Domain (will have missing entries where interior cells do not correspond to boundary)
Return the subset of values given by selectargs (Grid-specific keywords eg cell=, column=, ...) and corresponding dimensions (with attached coordinates).
internalvalues are transformed if needed from internal Field representation as a Vector length ncells, to an Array (2D if neither i, j arguments present, 1D if i or j present, 0D ie one cell if both present)
internalvalues are transformed if needed from internal Field representation as a Vector length ncells, to an Array (3D if neither i, j, k arguments present, 2D if one of i, j or k present, 1D if two present, 0D ie one cell if i, j, k all specified).
Grids may define name dimensions and attach coordinates for the convenience of output visualisation. Any coordinate information required by Reactions should be supplied as Variables.
PALEO Variables exist in Domains and represent biogeochemical or other quantities. They are defined by Reactions as VariableReactions which are then linked to create VariableDomains, and contain Fields which represent data (a subtype of AbstractData) in a function space (a subtype of AbstractSpace) with dimensions defined by the Domain grid (a subtype of AbstractMesh)
Dataflow dependency between Variables is represented by two pairings:
Model (Domain) VariableDomain linking a single VariableReaction{VT_ReactTarget} to multiple VariableReaction{VT_ReactContributor} and VariableReaction{VT_ReactDependency}.
Definition for Variable attribute name. Defines a data type T, a default_value, required (true if always present ie added with default_value when Variable is created), units, and an optional description.
Note that Variable attributes are stored as a per-Variable Dict(name => value), these definitions are only used to provide defaults, check types, and provide descriptive metadata.
ParseFromString should usually be Nothing: a value of Type T is then required when calling set_attribute!. If ParseFromString is true, then set_attribute! will accept an AbstractString and call Base.parse(T, strvalue) to convert to T. This allows eg an enum-valued Attribute to be defined by Attribute{EnumType, true} and implementing parse(EnumType, rawvalue::AbstractString)
32×5 DataFrame
name default_value required units description
Symbol Any Bool String String
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
@@ -38,26 +38,26 @@
standard_name false netcdf CF conventions standard name
totalnames String[] false Vector of total Variable names for this species
vertical_movement 0.0 false m d-1 vertical advective transport (+ve upwards) in column
- vphase VP_Undefined false phase for concentrations in multiphase cells
Allowed values of :vfunction Variable Attribute, defining the Variable function to the host ODE or DAE solver.
Explicit ODE problems with dS/dt = F(S) consist of pairs of S::VFStateExplicit, F::VFDeriv Variables.
An implicit ODE problem with dU/dt = F(U) where Total variables U are functions U(S) of State variables S will consist of pairs of U::VFTotal and F::VFDeriv Variables, and also the same number of S::VF_StateTotal (in no particular order).
Algebraic constraints C(S) = 0 include variables C::VFConstraint and the same number of S::VFState, with no corresponding VF_Deriv.
:field_data = ScalarData, :space = CellSpace defines a per-cell quantity in a spatial Domain.
:field_data = ArrayScalarData, :data_dims =("wgrid",):space = ScalarSpace defines a Domain scalar (0D) quantity on a wavelength grid, a Vector of length given by the value of the Domain "wgrid" data dimension (see set_data_dimension!)
Allowed values of :vfunction Variable Attribute, defining the Variable function to the host ODE or DAE solver.
Explicit ODE problems with dS/dt = F(S) consist of pairs of S::VFStateExplicit, F::VFDeriv Variables.
An implicit ODE problem with dU/dt = F(U) where Total variables U are functions U(S) of State variables S will consist of pairs of U::VFTotal and F::VFDeriv Variables, and also the same number of S::VF_StateTotal (in no particular order).
Algebraic constraints C(S) = 0 include variables C::VFConstraint and the same number of S::VFState, with no corresponding VF_Deriv.
:field_data = ScalarData, :space = CellSpace defines a per-cell quantity in a spatial Domain.
:field_data = ArrayScalarData, :data_dims =("wgrid",):space = ScalarSpace defines a Domain scalar (0D) quantity on a wavelength grid, a Vector of length given by the value of the Domain "wgrid" data dimension (see set_data_dimension!)
Optional: sanitize values for storing as model output. Default implementation is usually OK - only implement eg for Atomic types that should be converted to standard types for storage
Optional: sanitize values for storing as model output. Default implementation is usually OK - only implement eg for Atomic types that should be converted to standard types for storage
Initialize values at model start to init_value over region cellrange using information from Variable attribv attributes, scaled by convertfn and convertvalues.
Optional: only required if this field_data type is used for a model (state) Variable that requires initialisation.
Arguments:
values: data to be zeroed
init_value::Symbol: one of :initialvalue, :normvalue, requesting type of initial value required
attribv::VariableBase: Variable with attributes to use for initialisation
convertfn::Function: apply multiplier convertfn(convertvalues, i) to initialisation value for cell i. Typically this is used to convert units eg concentration to mol.
convertvalues: parameters (if any) required by convertfn, eg a volume measure.
cellrange: range of cells to initialise
info::::NTuple{3, String}: Tuple (varinfo, convertinfo, trsfrinfo) of identifier strings to use for log messages
Initialize values at model start to init_value over region cellrange using information from Variable attribv attributes, scaled by convertfn and convertvalues.
Optional: only required if this field_data type is used for a model (state) Variable that requires initialisation.
Arguments:
values: data to be zeroed
init_value::Symbol: one of :initialvalue, :normvalue, requesting type of initial value required
attribv::VariableBase: Variable with attributes to use for initialisation
convertfn::Function: apply multiplier convertfn(convertvalues, i) to initialisation value for cell i. Typically this is used to convert units eg concentration to mol.
convertvalues: parameters (if any) required by convertfn, eg a volume measure.
cellrange: range of cells to initialise
info::::NTuple{3, String}: Tuple (varinfo, convertinfo, trsfrinfo) of identifier strings to use for log messages
An IsotopeScalar represents a quantity or flux with isotopic composition. Can be added, subtracted, multiplied by a scalar, and decomposed into components with the same (bulk) transport properties.
Implementation
Each IsotopeScalar should be added to IsotopeTypes, and implement:
get_total(is::IsotopeScalar) -> total
arithmetic operations +/- (ie IsotopeScalars can be added and subtracted) and *number, /number (IsotopeScalars can be scaled by a real number).
An IsotopeScalar represents a quantity or flux with isotopic composition. Can be added, subtracted, multiplied by a scalar, and decomposed into components with the same (bulk) transport properties.
Implementation
Each IsotopeScalar should be added to IsotopeTypes, and implement:
get_total(is::IsotopeScalar) -> total
arithmetic operations +/- (ie IsotopeScalars can be added and subtracted) and *number, /number (IsotopeScalars can be scaled by a real number).
Parameters with external=true may be set from the Model-level Parameters list, if name is present in that list.
ParseFromString should usually be Nothing: a value of Type T is then required when calling setvalue!. If ParseFromString is not Nothing, then setvalue! will accept an AbstractString and call Base.parse(ParseFromString, strvalue). This allows eg an enum-valued Parameter to be defined by Parameter{EnumType, EnumType} and implementing parse(EnumType, rawvalue::AbstractString)
Add a single parameter or parameters from fields of objectwithpars to a new Reaction.
Not usually needed: Parameters in pars::ParametersTuplewill be added automatically, only needed if there are additional Parameters that are not members ofpars`.
All subtypes of AbstractReaction that are present in loaded modules are available to the PALEO framework. Available Reactions can be listed with find_reaction and find_all_reactions. The default create_reaction is called to create Reactions when the model is created (this method can be overridden if needed).
Look up "class" in list of Reactions available in currently loaded modules (using find_all_reactions), and return fully-qualified Reaction Type (including module prefixes).
Use InteractiveUtils.subtypes(AbstractReaction) to find all currently loaded subtypes off AbstractReaction, and create a Dict with last part of the name of the Type as key (ie without the module prefix) and Type as value.
Any Types that generate non-unique keys (eg Module1.MyReactionType and Module2.MyReactionType) will generate a warning, and no entry will be added to the Dict (so if this Reaction is present in a config file, it will not be found and will error).
Parameters with external=true may be set from the Model-level Parameters list, if name is present in that list.
ParseFromString should usually be Nothing: a value of Type T is then required when calling setvalue!. If ParseFromString is not Nothing, then setvalue! will accept an AbstractString and call Base.parse(ParseFromString, strvalue). This allows eg an enum-valued Parameter to be defined by Parameter{EnumType, EnumType} and implementing parse(EnumType, rawvalue::AbstractString)
Add a single parameter or parameters from fields of objectwithpars to a new Reaction.
Not usually needed: Parameters in pars::ParametersTuplewill be added automatically, only needed if there are additional Parameters that are not members ofpars`.
All subtypes of AbstractReaction that are present in loaded modules are available to the PALEO framework. Available Reactions can be listed with find_reaction and find_all_reactions. The default create_reaction is called to create Reactions when the model is created (this method can be overridden if needed).
Look up "class" in list of Reactions available in currently loaded modules (using find_all_reactions), and return fully-qualified Reaction Type (including module prefixes).
Use InteractiveUtils.subtypes(AbstractReaction) to find all currently loaded subtypes off AbstractReaction, and create a Dict with last part of the name of the Type as key (ie without the module prefix) and Type as value.
Any Types that generate non-unique keys (eg Module1.MyReactionType and Module2.MyReactionType) will generate a warning, and no entry will be added to the Dict (so if this Reaction is present in a config file, it will not be found and will error).
Reactions define AbstractVarLists of VariableReactions when creating a ReactionMethod. Within a ReactionMethod, a VariableReaction is referred to by localname. When the model is initialised, VariableDomain variables are created that link together VariableReactions with the same link_namestr, and data Arrays are allocated. views on the VariableDomain data Arrays are then passed to the ReactionMethod function at each timestep.
Subtypes
The Type parameter VT is one of VT_ReactProperty, VT_ReactDependency, VT_ReactContributor, VT_ReactTarget, where short names are defined for convenience:
There are two pairings of VariableReactions with VariableDomains:
Reaction Property and Dependency Variables, linked to a VariableDomPropDep. These are used to represent a quantity calculated in one Reaction that is then used by other Reactions.
Reaction Target and Contributor Variables, linked to a VariableDomContribTarget. These are used to represent a flux-like quantity, with one Reaction definining the Target and multiple Reactions adding contributions.
Variable Attributes and constructor convenience functions
Variable attributes are used to define Variable :spaceAbstractSpace (scalar, per-cell, etc) and data content :field_dataAbstractData, and to label state Variables for use by numerical solvers.
VariableReaction is usually not called directly, instead convenience functions are defined that provide commonly-used combinations of VT and attributes:
short name
VT
attributes
:space
:field_data
:vfunction
:initialize_to_zero
:datatype
:is_constant
VarProp
VT_ReactProperty
CellSpace
ScalarData
VF_Undefined
-
-
false
VarPropScalar
VT_ReactProperty
ScalarSpace
ScalarData
VF_Undefined
-
-
false
VarPropStateIndep
VT_ReactProperty
CellSpace
ScalarData
VF_Undefined
-
Float64
true
VarPropScalarStateIndep
VT_ReactProperty
ScalarSpace
ScalarData
VF_Undefined
-
Float64
true
VarDep
VT_ReactDependency
CellSpace
UndefinedData
VF_Undefined
-
-
false
VarDepColumn
VT_ReactDependency
ColumnSpace
UndefinedData
VF_Undefined
-
-
false
VarDepScalar
VT_ReactDependency
ScalarSpace
UndefinedData
VF_Undefined
-
-
false
VarDepStateIndep
VT_ReactDependency
CellSpace
UndefinedData
VF_Undefined
-
Float64
true
VarDepColumnStateIndep
VT_ReactDependency
ColumnSpace
UndefinedData
VF_Undefined
-
Float64
true
VarDepScalarStateIndep
VT_ReactDependency
ScalarSpace
UndefinedData
VF_Undefined
-
Float64
true
VarTarget
VT_ReactTarget
CellSpace
ScalarData
VF_Undefined
true
-
false
VarTargetScalar
VT_ReactTarget
ScalarSpace
ScalarData
VF_Undefined
true
-
false
VarContrib
VT_ReactContributor
CellSpace
UndefinedData
VF_Undefined
-
-
false
VarContribColumn
VT_ReactContributor
ColumnSpace
UndefinedData
VF_Undefined
-
-
false
VarContribScalar
VT_ReactContributor
ScalarSpace
UndefinedData
VF_Undefined
-
-
false
VarStateExplicit
VT_ReactDependency
CellSpace
ScalarData
VF_StateExplicit
-
-
false
VarStateExplicitScalar
VT_ReactDependency
ScalarSpace
ScalarData
VF_StateExplicit
-
-
false
VarDeriv
VT_ReactContributor
CellSpace
ScalarData
VF_Deriv
true
-
false
VarDerivScalar
VT_ReactContributor
ScalarSpace
ScalarData
VF_Deriv
true
-
false
VarState
VT_ReactDependency
CellSpace
ScalarData
VF_State
-
-
false
VarStateScalar
VT_ReactDependency
ScalarSpace
ScalarData
VF_State
-
-
false
VarConstraint
VT_ReactContributor
CellSpace
ScalarData
VF_Constraint
true
-
false
VarConstraintScalar
VT_ReactContributor
ScalarSpace
ScalarData
VF_Constraint
true
-
false
This illustrates some general principles for the use of attributes:
All Variables must define the :space VariableAttribute (a subtype of AbstractSpace) to specify whether they are Domain scalars, per-cell quantities, etc. This is used to define array dimensions, and to check that dimensions match when variables are linked.
The :field_data attribute (a subtype of AbstractData) specifies the quantity that Property and Target Variables represent. This defaults to ScalarData to represent a scalar value. To eg represent a single isotope the :field_data attribute should be set to IsotopeLinear. Dependency and Contributor Variables with :field_data = UndefinedData then acquire this value when they are linked, or may specify :field_data to constrain allowed links.
The :initialize_to_zero attribute is set for Target variables, this is than used (by the ReactionMethod created by add_method_initialize_zero_vars_default!) to identify variables that should be initialised to zero at the start of each timestep.
The :vfunction attribute is used to label state Variables and corresponding time derivatives, for access by a numerical solver.
An ODE-like combination of a state variable and time derivative are defined by a paired VarStateExplicit and VarDeriv. Note that that these are just VarDep and VarContrib with the :vfunction attribute set, and that there is no VarProp and VarTarget defined in the model (these are effectively provided by the numerical solver). The pairing is defined by the naming convention of varname and varname_sms.
An algebraic constraint (for a DAE) is defined by a VarState and VarConstraint. Note that that these are just VarDep and VarContrib with the :vfunction attribute set, and that there is no VarProp and VarTarget defined in the model (these are effectively provided by the numerical solver). These variables are not paired.
The :initializetozero attribute is also set for Contributor variables VarDeriv and VarConstraint (as there is no corresponding Target variable in the model).
The :field_data attribute should be set on labelled state etc Variables (as there are no corresponding Property or Target variables in the model to define this).
The :is_constant attribute is used to identify constant Property Variables (not modified after initialisation). A Dependency Variable with :is_constant = true can only link to a constant Property Variable.
The :datatype attribute is used both to provide a concrete datatype for constant Variables, and to exclude a non-constant Variable from automatic differentiation (TODO document that usage).
Additional attributes can be specified to provide model-specific information, with defaults defined in the Reaction .jl code that can often then be overridden in the .yaml configuration file, see StandardAttributes. Examples include:
:initial_value, :norm_value, :initial_delta for state variables or constant variables. NB: the Reaction creating these variables is responsible for implementing a setup method to read the attributes and set the variable data array appropriately at model initialisation.
An :advect attribute is used to label tracer variables to indicate that they should have advective transport applied by a transport Reaction included in the model.
NB: after Variables are linked to Domain Variables, the attributes used are those from the master Variable (either a Property or Target variable, or a labelled state variable Dependency or Contributor with no corresponding Property or Target). Additional attributes must therefore be set on this master Variable.
Specifying links
localname identifies the VariableReaction within the Reaction, and can be used to set variable_attributes: and variable_links: in the .yaml configuration file.
linkreq_domain.linkreq_subdomain.linkreq_name defines the Domain, Subdomain and name for run-time linking to VariableDomain variables.
Arguments
VT::VariableType: one of VT_ReactProperty, VT_ReactDependency, VT_ReactContributor, VT_ReactTarget
localname::AbstractString: Reaction-local Variable name
link_namestr::AbstractString: <linkreq_domain>.[linkreq_subdomain.]linkreq_name. Parsed by parse_variablereaction_namestr to define the requested linking to Domain Variable.
linklocal_namestr::AbstractString: <linkreq_domain>.[linkreq_subdomain.]localname. Convenience form to define both localname and requested linking to Domain Variable, for the common case where linkreq_name == localname.
units::AbstractString: units ("" if not applicable)
description::AbstractString: text describing the variable
There are two pairings of VariableReactions with VariableDomains:
Reaction Property and Dependency Variables, linked to a VariableDomPropDep. These are used to represent a quantity calculated in one Reaction that is then used by other Reactions.
Reaction Target and Contributor Variables, linked to a VariableDomContribTarget. These are used to represent a flux-like quantity, with one Reaction definining the Target and multiple Reactions adding contributions.
Variable Attributes and constructor convenience functions
Variable attributes are used to define Variable :spaceAbstractSpace (scalar, per-cell, etc) and data content :field_dataAbstractData, and to label state Variables for use by numerical solvers.
VariableReaction is usually not called directly, instead convenience functions are defined that provide commonly-used combinations of VT and attributes:
short name
VT
attributes
:space
:field_data
:vfunction
:initialize_to_zero
:datatype
:is_constant
VarProp
VT_ReactProperty
CellSpace
ScalarData
VF_Undefined
-
-
false
VarPropScalar
VT_ReactProperty
ScalarSpace
ScalarData
VF_Undefined
-
-
false
VarPropStateIndep
VT_ReactProperty
CellSpace
ScalarData
VF_Undefined
-
Float64
true
VarPropScalarStateIndep
VT_ReactProperty
ScalarSpace
ScalarData
VF_Undefined
-
Float64
true
VarDep
VT_ReactDependency
CellSpace
UndefinedData
VF_Undefined
-
-
false
VarDepColumn
VT_ReactDependency
ColumnSpace
UndefinedData
VF_Undefined
-
-
false
VarDepScalar
VT_ReactDependency
ScalarSpace
UndefinedData
VF_Undefined
-
-
false
VarDepStateIndep
VT_ReactDependency
CellSpace
UndefinedData
VF_Undefined
-
Float64
true
VarDepColumnStateIndep
VT_ReactDependency
ColumnSpace
UndefinedData
VF_Undefined
-
Float64
true
VarDepScalarStateIndep
VT_ReactDependency
ScalarSpace
UndefinedData
VF_Undefined
-
Float64
true
VarTarget
VT_ReactTarget
CellSpace
ScalarData
VF_Undefined
true
-
false
VarTargetScalar
VT_ReactTarget
ScalarSpace
ScalarData
VF_Undefined
true
-
false
VarContrib
VT_ReactContributor
CellSpace
UndefinedData
VF_Undefined
-
-
false
VarContribColumn
VT_ReactContributor
ColumnSpace
UndefinedData
VF_Undefined
-
-
false
VarContribScalar
VT_ReactContributor
ScalarSpace
UndefinedData
VF_Undefined
-
-
false
VarStateExplicit
VT_ReactDependency
CellSpace
ScalarData
VF_StateExplicit
-
-
false
VarStateExplicitScalar
VT_ReactDependency
ScalarSpace
ScalarData
VF_StateExplicit
-
-
false
VarDeriv
VT_ReactContributor
CellSpace
ScalarData
VF_Deriv
true
-
false
VarDerivScalar
VT_ReactContributor
ScalarSpace
ScalarData
VF_Deriv
true
-
false
VarState
VT_ReactDependency
CellSpace
ScalarData
VF_State
-
-
false
VarStateScalar
VT_ReactDependency
ScalarSpace
ScalarData
VF_State
-
-
false
VarConstraint
VT_ReactContributor
CellSpace
ScalarData
VF_Constraint
true
-
false
VarConstraintScalar
VT_ReactContributor
ScalarSpace
ScalarData
VF_Constraint
true
-
false
This illustrates some general principles for the use of attributes:
All Variables must define the :space VariableAttribute (a subtype of AbstractSpace) to specify whether they are Domain scalars, per-cell quantities, etc. This is used to define array dimensions, and to check that dimensions match when variables are linked.
The :field_data attribute (a subtype of AbstractData) specifies the quantity that Property and Target Variables represent. This defaults to ScalarData to represent a scalar value. To eg represent a single isotope the :field_data attribute should be set to IsotopeLinear. Dependency and Contributor Variables with :field_data = UndefinedData then acquire this value when they are linked, or may specify :field_data to constrain allowed links.
The :initialize_to_zero attribute is set for Target variables, this is than used (by the ReactionMethod created by add_method_initialize_zero_vars_default!) to identify variables that should be initialised to zero at the start of each timestep.
The :vfunction attribute is used to label state Variables and corresponding time derivatives, for access by a numerical solver.
An ODE-like combination of a state variable and time derivative are defined by a paired VarStateExplicit and VarDeriv. Note that that these are just VarDep and VarContrib with the :vfunction attribute set, and that there is no VarProp and VarTarget defined in the model (these are effectively provided by the numerical solver). The pairing is defined by the naming convention of varname and varname_sms.
An algebraic constraint (for a DAE) is defined by a VarState and VarConstraint. Note that that these are just VarDep and VarContrib with the :vfunction attribute set, and that there is no VarProp and VarTarget defined in the model (these are effectively provided by the numerical solver). These variables are not paired.
The :initializetozero attribute is also set for Contributor variables VarDeriv and VarConstraint (as there is no corresponding Target variable in the model).
The :field_data attribute should be set on labelled state etc Variables (as there are no corresponding Property or Target variables in the model to define this).
The :is_constant attribute is used to identify constant Property Variables (not modified after initialisation). A Dependency Variable with :is_constant = true can only link to a constant Property Variable.
The :datatype attribute is used both to provide a concrete datatype for constant Variables, and to exclude a non-constant Variable from automatic differentiation (TODO document that usage).
Additional attributes can be specified to provide model-specific information, with defaults defined in the Reaction .jl code that can often then be overridden in the .yaml configuration file, see StandardAttributes. Examples include:
:initial_value, :norm_value, :initial_delta for state variables or constant variables. NB: the Reaction creating these variables is responsible for implementing a setup method to read the attributes and set the variable data array appropriately at model initialisation.
An :advect attribute is used to label tracer variables to indicate that they should have advective transport applied by a transport Reaction included in the model.
NB: after Variables are linked to Domain Variables, the attributes used are those from the master Variable (either a Property or Target variable, or a labelled state variable Dependency or Contributor with no corresponding Property or Target). Additional attributes must therefore be set on this master Variable.
Specifying links
localname identifies the VariableReaction within the Reaction, and can be used to set variable_attributes: and variable_links: in the .yaml configuration file.
linkreq_domain.linkreq_subdomain.linkreq_name defines the Domain, Subdomain and name for run-time linking to VariableDomain variables.
Arguments
VT::VariableType: one of VT_ReactProperty, VT_ReactDependency, VT_ReactContributor, VT_ReactTarget
localname::AbstractString: Reaction-local Variable name
link_namestr::AbstractString: <linkreq_domain>.[linkreq_subdomain.]linkreq_name. Parsed by parse_variablereaction_namestr to define the requested linking to Domain Variable.
linklocal_namestr::AbstractString: <linkreq_domain>.[linkreq_subdomain.]localname. Convenience form to define both localname and requested linking to Domain Variable, for the common case where linkreq_name == localname.
units::AbstractString: units ("" if not applicable)
description::AbstractString: text describing the variable
linkstr is of format: [(][<linkreq_domain>.][<linkreq_subdomain>.]<linkreq_name>[)]
Optional brackets ( ... ) set link_optional=true
linkreq_name may contain %reaction% which will later be substituted with <Reaction name>/
Examples:
julia> PALEOboxes.parse_variablereaction_namestr("foo") # Common case eg for a property that should be public
("", "", "foo", false)
@@ -38,7 +38,7 @@
("ocean", "", "foo", false)
julia> PALEOboxes.parse_variablereaction_namestr("(ocean.oceansurface.goo)") # Full syntax
-("ocean", "oceansurface", "goo", true)
Variables required by a ReactionMethodmethodfn are specified by a Tuple of VarList_xxx <: AbstractVarList, each containing a collection of VariableReaction.
These are then converted (by the create_accessors method) to a corresponding Tuple of collections of views on Domain data arrays , which are then be passed to the ReactionMethodmethodfn.
NB: creates and uses a copy of supplied Variables including metadata, so set / modify Variable attributes before creating a VarList.
Implementation
Subtypes of AbstractVarList should implement:
a constructor that takes a collection of VariableReactions
create_accessors, returning the views on Domain data arrays in a subtype-specific collection.
get_variables, returning the collection of VariableReactions (as a flat list).
Create a VarList_namedtuple describing a collection of VariableReactions, create_accessors will then return a NamedTuple with field names = VariableReaction.localname and field values = corresponding data arrays.
If components = true, each NamedTuple field will be a Vector of data array components.
Create a VarList_ttuple describing a collection of collections of VariableReactions, create_accessors will then return a Tuple of Tuples of data arrays.
Create a VarList_vector describing a collection of VariableReactions, create_accessors will then return a Vector of data arrays.
If components = true, each Vector element will be a Vector of data array components.
If forceview = true, each accessor will be a 1-D view to help type stability, even if this is redundant (ie no view required, v::Vector -> view(v, 1:length(v)))
Reaction method functions should iterate over the cells in the Domain supplied by cellrange argument and calculate appropriate biogeochemical fluxes etc (which may include the model time derivative and any intermediate or diagnostic output).
Variables required by a ReactionMethodmethodfn are specified by a Tuple of VarList_xxx <: AbstractVarList, each containing a collection of VariableReaction.
These are then converted (by the create_accessors method) to a corresponding Tuple of collections of views on Domain data arrays , which are then be passed to the ReactionMethodmethodfn.
NB: creates and uses a copy of supplied Variables including metadata, so set / modify Variable attributes before creating a VarList.
Implementation
Subtypes of AbstractVarList should implement:
a constructor that takes a collection of VariableReactions
create_accessors, returning the views on Domain data arrays in a subtype-specific collection.
get_variables, returning the collection of VariableReactions (as a flat list).
Create a VarList_namedtuple describing a collection of VariableReactions, create_accessors will then return a NamedTuple with field names = VariableReaction.localname and field values = corresponding data arrays.
If components = true, each NamedTuple field will be a Vector of data array components.
Create a VarList_ttuple describing a collection of collections of VariableReactions, create_accessors will then return a Tuple of Tuples of data arrays.
Create a VarList_vector describing a collection of VariableReactions, create_accessors will then return a Vector of data arrays.
If components = true, each Vector element will be a Vector of data array components.
If forceview = true, each accessor will be a 1-D view to help type stability, even if this is redundant (ie no view required, v::Vector -> view(v, 1:length(v)))
Reaction method functions should iterate over the cells in the Domain supplied by cellrange argument and calculate appropriate biogeochemical fluxes etc (which may include the model time derivative and any intermediate or diagnostic output).
The simplest case is a method function that iterates over individual cells, with skeleton form:
function do_something_cellwise(m::PB.AbstractReactionMethod, pars, (vars, ), cellrange::PB.AbstractCellRange, deltat)
@inbounds for i in cellrange.indices
vars.A[i] = something*vars.B[i]*vars.C[i] # in general A is some function of B, C, etc
@@ -104,7 +104,7 @@
x = vgatherind(ST, v_a, i) # x is a packed SIMD vector with type conversion to Float32
vscatterind!(x, v_b, i)
-end
Defines a callback function methodfn with Variables varlists, to be called from the Model framework either during setup or as part of the main loop.
Fields
methodfn: callback from Model framework
reaction: the Reaction that created this ReactionMethod
name: a descriptive name, eg generated from the name of methodfn
varlists: Tuple of VarLists, each representing a list of VariableReactions. Corresponding Variable accessors vardata (views on Arrays) will be provided to the methodfn callback. NB: not concretely typed to reduce compile time, as not performance-critical
p: optional context field (of arbitrary type) to store data needed by methodfn.
operatorID
domain
preparefn: preparefn(m::ReactionMethod, vardata::Tuple) -> modified_vardata::Tuple optionally modify vardata to eg add buffers. NB: not concretely typed as not performance-critical
m::ReactionMethod: context is available as m.reaction::AbstractReaction (the Reaction that defined the ReactionMethod), and m.p (an arbitrary extra context field supplied when ReactionMethod created).
pars: a struct with Parameters as fields (current just the ParametersTuple defined as reaction.pars)
vardata: A Tuple of collections of views on Domain data arrays corresponding to VariableReactions defined by varlists
cellrange::AbstractCellRange: range of cells to calculate.
modelctxt:
for a setup method, :setup, :initial_value or :norm_value defining the type of setup requested
for a main loop method deltat providing timestep information eg for rate throttling.
preparefn
An optional preparefn callback can be supplied eg to allocate buffers that require knowledge of the data types of vardata or to cache expensive calculations:
Add or create-and-add a setup method (called before main loop) eg to set persistent data or initialize state variables. methodfn, vars, kwargs are passed to ReactionMethod.
Add or create-and-add an initialize method (called at start of each main loop iteration) eg to zero out accumulator Variables. methodfn, vars, kwargs are passed to ReactionMethod.
Create and add a default method to initialize Variables matching filterfn (defaults to state Variables) at beginning of integration.
Setup callbacks used
State Variables and similar (:vfunction != VF_Undefined) are initialized in a setup callback with attribute_name in (:initial_value, :norm_value), with values from those Variable attributes.
If force_state_norm_value=false, other Variables (with :vfunction == VF_Undefined) are initialized in a setup callback with attribute_name=:setup, with values from the :initial_value Variable attribute. NB: filterfn must be set to include these Variables.
If force_initial_norm_value=true, all Variables (including those with :vfunction == VF_Undefined) are initialised as state Variables
Keywords
filterfn: set to f(var)::Bool to override the default selection for state variables only (Variables with :vfunction in (VF_StateExplicit, VF_State, VF_Total, VF_StateTotal, VF_Constraint))
force_initial_norm_value=false: true to always use :initial_value, :norm_value, even for variables with :vfunction=VF_Undefined
transfer_attribute_vars=[]: Set to a list of the same length as variables to initialise variables from attributes of transfer_attribute_vars.
setup_callback=(method, attribute_name, var, vardata) -> nothing: Set to a function that is called after each Variable initialisation eg to store norm values.
convertvars=[]
convertfn = (convertvars_tuple, i) -> 1.0
convertinfo = ""
Including volume etc conversion
Set convertvars to a Vector of Variables (eg for cell volume) and supply convertfn and convertinfo to initialize to :initial_value*convertfn(convertvars_tuple, i) where the argument of convertfn is the Tuple generated by VarList_tuple(convertvars).
Example: To interpret :initial_value as a concentration-like quantity:
convertvars = [volume],
+) -> m::ReactionMethod
Defines a callback function methodfn with Variables varlists, to be called from the Model framework either during setup or as part of the main loop.
Fields
methodfn: callback from Model framework
reaction: the Reaction that created this ReactionMethod
name: a descriptive name, eg generated from the name of methodfn
varlists: Tuple of VarLists, each representing a list of VariableReactions. Corresponding Variable accessors vardata (views on Arrays) will be provided to the methodfn callback. NB: not concretely typed to reduce compile time, as not performance-critical
p: optional context field (of arbitrary type) to store data needed by methodfn.
operatorID
domain
preparefn: preparefn(m::ReactionMethod, vardata::Tuple) -> modified_vardata::Tuple optionally modify vardata to eg add buffers. NB: not concretely typed as not performance-critical
m::ReactionMethod: context is available as m.reaction::AbstractReaction (the Reaction that defined the ReactionMethod), and m.p (an arbitrary extra context field supplied when ReactionMethod created).
pars: a struct with Parameters as fields (current just the ParametersTuple defined as reaction.pars)
vardata: A Tuple of collections of views on Domain data arrays corresponding to VariableReactions defined by varlists
cellrange::AbstractCellRange: range of cells to calculate.
modelctxt:
for a setup method, :setup, :initial_value or :norm_value defining the type of setup requested
for a main loop method deltat providing timestep information eg for rate throttling.
preparefn
An optional preparefn callback can be supplied eg to allocate buffers that require knowledge of the data types of vardata or to cache expensive calculations:
Add or create-and-add a setup method (called before main loop) eg to set persistent data or initialize state variables. methodfn, vars, kwargs are passed to ReactionMethod.
Add or create-and-add an initialize method (called at start of each main loop iteration) eg to zero out accumulator Variables. methodfn, vars, kwargs are passed to ReactionMethod.
Create and add a default method to initialize Variables matching filterfn (defaults to state Variables) at beginning of integration.
Setup callbacks used
State Variables and similar (:vfunction != VF_Undefined) are initialized in a setup callback with attribute_name in (:initial_value, :norm_value), with values from those Variable attributes.
If force_state_norm_value=false, other Variables (with :vfunction == VF_Undefined) are initialized in a setup callback with attribute_name=:setup, with values from the :initial_value Variable attribute. NB: filterfn must be set to include these Variables.
If force_initial_norm_value=true, all Variables (including those with :vfunction == VF_Undefined) are initialised as state Variables
Keywords
filterfn: set to f(var)::Bool to override the default selection for state variables only (Variables with :vfunction in (VF_StateExplicit, VF_State, VF_Total, VF_StateTotal, VF_Constraint))
force_initial_norm_value=false: true to always use :initial_value, :norm_value, even for variables with :vfunction=VF_Undefined
transfer_attribute_vars=[]: Set to a list of the same length as variables to initialise variables from attributes of transfer_attribute_vars.
setup_callback=(method, attribute_name, var, vardata) -> nothing: Set to a function that is called after each Variable initialisation eg to store norm values.
convertvars=[]
convertfn = (convertvars_tuple, i) -> 1.0
convertinfo = ""
Including volume etc conversion
Set convertvars to a Vector of Variables (eg for cell volume) and supply convertfn and convertinfo to initialize to :initial_value*convertfn(convertvars_tuple, i) where the argument of convertfn is the Tuple generated by VarList_tuple(convertvars).
Example: To interpret :initial_value as a concentration-like quantity:
Create and add a default method to initialize Variables to zero at beginning of each timestep. Defaults to adding all Variables from react with :initialize_to_zero attribute true.
NB: TODO variables are converted to VarDep (no dependency checking or sorting needed, could define a VarInit or similar?)
Create and add a method to add total variables (Scalar Properties), for Variables in collection total_candidates that match filterfn (defaults to those that are Array Variables and have attribute `:calc_total == true).
Create and add a default method to initialize Variables to zero at beginning of each timestep. Defaults to adding all Variables from react with :initialize_to_zero attribute true.
NB: TODO variables are converted to VarDep (no dependency checking or sorting needed, could define a VarInit or similar?)
Create and add a method to add total variables (Scalar Properties), for Variables in collection total_candidates that match filterfn (defaults to those that are Array Variables and have attribute `:calc_total == true).
A Property Variable should be set to provide the reaction rate (often this is implemented by another method of the same Reaction). This method will then link to that (using the local and link names supplied by ratevartemplate) and calculate the appropriate product rates, omitting products that are not present (VariableReaction not linked) in the Model configuration. Metadata for use when analysing model output should be added to the rate variable using add_rate_stoichiometry!, in the usual case where this Variable is supplied as ratevartemplate this will happen automatically.
Arguments:
ratevartemplate::Union{VarPropT, VarDepT}: used to define the rate variable local and link names.
deltavarname_eta: optional tuple of variable delta + eta ("SO4_delta", -30.0) or ("SO4_delta", rj.pars.delta). If a Parameter is supplied, this is read in do_react_ratestoich to allow modification.
processname::String: optional tag to identify the type of reaction in model output
add_rate_stoichiometry=true: true to add call add_rate_stoichiometry! to add metadata to ratevartemplate.
Examples:
Create a RateStoich representing the reaction 2 O2 + H2S -> H2SO4
if var is linked, an accessor or Tuple (accessor, subdomain_indices) that provides a view on variable data.
if var is not linked, nothing if var is optional, or errors and doesn't return if var is non-optional.
Mapping of indices for Subdomains <–> Domains:
if no Subdomain, returns unmodified indices (if forceview=false), or an equivalent view (if forceview=true, this is to help type stability)
if Variable is a Domain interior and Subdomain is a Domain boundary, accessor is a view with a subset of Domain indices.
if Variable is a Domain boundary and Subdomain is the Domain interior, returns a Tuple with subdomain_indices, length(Subdomain size), with missing for interior points.
Mapping of multi-component (Isotope) Variables:
If components=false:
map multi-component Variable to accessor::IsotopeArray
return a single-component Variable as a accessor::AbstractArray.
If components=true:
variable data as a accessor::Vector{Array}, length=number of components