Reference Guide: Structures - Definitions

Model Definition

Models are composed of two separate structures, which we refer to as the "definition" side and the "instance" or "instantiated" side. The definition side is operated on by the user via the @defcomp and @defcomposite macros, and the public API (add_comp!, update_param!, connect_param!, etc.).

The instantiated model can be thought of as a "compiled" version of the model definition, with its data structures oriented toward run-time efficiency. It is constructed by Mimi in the build() function, which is called by the run() function.

The public API sets a flag whenever the user modifies the model definition, and the instance is rebuilt before it is run if the model definition has changed. Otherwise, the model instance is re-run.

The model definition is constructed from the following elements.

Leaf components

Leaf components are defined using the @defcomp macro which generates a component definition of the type ComponentDef which has the following fields:

# ComponentDef
comp_id::Union{Nothing, ComponentId}   
comp_path::Union{Nothing, ComponentPath}
dim_dict::OrderedDict{Symbol, Union{Nothing, Dimension}}
namespace::OrderedDict{Symbol, Any}       
first::Union{Nothing, Int}
last::Union{Nothing, Int}

The namespace of a leaf component can hold ParameterDefs and VariableDefs, both which are subclasses of DatumDef (see below for more details on these types).

Composite components

Composite components are defined using the @defcomposite macro which generates a composite component definition of the type CompositeComponentDef which has the following fields, in addition to the fields of a ComponentDef:

# CompositeComponentDef <: ComponentDef 

The namespace of a composite component can hold CompositeParameterDefs andCompositeVariableDefs, as well as AbstractComponentDefs (which can be other leaf or composite component definitions).

Datum definitions

Note: we use "datum" to refer collectively to parameters and variables. Parameters are values that are fed into a component, and variables are values calculated by a component's run_timestep function.

Datum are defined with the @defcomp and @defcomposite macros, and have the following fields:

# DatumDef
comp_path::Union{Nothing, ComponentPath}

The only difference between a ParameterDef and a VariableDef is that parameters can have default values.

# ParameterDef <: DatumDef

# VariableDef <: DatumDef
# (This class adds no new fields. It exists to differentiate variables from parameters.)

CompositeParameterDefs and CompositeVariableDefs are defined in the @defcomposite macro, and point to datum from their subcomponents. (Remember, composite components do not have run_timestep functions, so no values are actually calculated in a composite component.) Thus, CompositeParameterDefs and CompositeVariableDefs inherit all the fields from ParameterDefs and VariableDefs, and have an additional field to record which subcomponent(s)' datum they reference.

# CompositeParameterDef <: ParameterDef

# CompositeVariableDef <: VariableDef

Note: a CompositeParameterDef can reference multiple subcomponents' parameters, but a CompositeVariableDef can only reference a variable from one subcomponent.

The reference(s) stored in CompositeParameterDefs and CompositeVariableDefs are of type UnnamedReference, which has the following fields:

# UnnamedReference
comp_name::Symbol   # name of the referenced subcomponent
datum_name::Symbol  # name of the parameter or variable in the subcomponent's namespace


A ModelDef is a top-level composite that also stores model parameters and a list of model parameter connections. It contains the following additional fields:

# ModelDef <: CompositeComponentDef
model_params::Dict{Symbol, ModelParameter}

Note: a ModelDef's namespace will only hold AbstractComponentDefs.

Parameter Connections

InternalParameterConnection Internal parameters are defined by connecting a parameter in one component to a variable in another component. This struct holds the names and ComponentPaths of the parameter and variable, and other information such as the "backup" data source. At build time, internal parameter connections result in direct references from the parameter to the storage allocated for the variable.

ExternalParameterConnection Values that are exogenous to the model are defined in model parameters whose values are assigned using the public API function update_param!(), or by setting default values in @defcomp or @defcomposite, in which case, the default values are assigned via an internal call to update_param!().

External connections are stored in the ModelDef, along with the actual ModelParameters, which may be scalar values or arrays, as described below.

# AbstractConnection

# InternalParameterConnection <: AbstractConnection
backup::Union{Symbol, Nothing} # a Symbol identifying the model param providing backup data, or nothing
backup_offset::Union{Int, Nothing}

# ExternalParameterConnection  <: AbstractConnection
param_name::Symbol      # name of the parameter in the component
model_param_name::Symbol  # name of the parameter stored in the model's model_params

Model parameters

ModelParameter This is an abstract type that is the supertype of both ScalarModelParameter{T} and ArrayModelParameter{T}. These two parameterized types are used to store values set for model parameters.