Sindbad.Simulation Module
SimulationThe Simulation module provides the core functionality for running the SINDBAD Terrestrial Ecosystem Model (TEM). It includes utilities for preparing model-ready objects, managing spinup processes and running models.
Purpose
This module integrates various components and utilities required to execute the SINDBAD TEM, including precomputations, spinup, and time loop simulations. It supports parallel execution and efficient handling of large datasets.
Dependencies
Related (SINDBAD ecosystem)
TimeSamplers: Temporal helpers used in time-loop workflows.OmniTools: Shared utilities used during simulation and output handling.
External (third-party)
ComponentArrays: Hierarchical state/parameter containers.ProgressMeter: Progress bars for long-running simulations.ThreadPools: Threaded parallelism helpers.
Internal (within Sindbad)
Sindbad.DataLoadersSindbad.SetupSindbad.TypesSindbadTEM
Included Files
utilsSimulation.jl: Core helpers for forcing slices, output handling, progress/logging, and simulation orchestration.deriveSpinupForcing.jl: Derive spinup forcing data for steady-state initialization.prepTEMOut.jl: Prepare output containers/structures for efficient writing.prepTEM.jl: Prepare model-ready inputs and configuration for runs.runTEMForLocation.jl: Run the TEM for a single location (optional spinup + main loop).runTEMInSpace.jl: Run the TEM across spatial grids (parallel execution).runTEMOnCube.jl: Run the TEM on 3DYAXArrayscubes (large-scale spatial runs).spinupTEM.jl: Spinup routines to initialize the model to steady state.spinupSequence.jl: Sequential spinup loops for iterative refinement.
Notes
The package is designed to be modular and extensible, allowing users to customize and extend its functionality for specific use cases.
It integrates tightly with the SINDBAD framework, leveraging shared types and utilities from
Setup.Some spinup solvers are enabled via an optional extension:
NLsolve→SindbadNLsolveExt(seeext/SindbadNLsolveExt/).
Functions
TEMYax
Sindbad.Simulation.TEMYax Function
TEMYax(map_cubes; loc_land::NamedTuple, tem::NamedTuple, selected_models::Tuple, forcing_vars::AbstractArray)Arguments:
map_cubes: collection/tuple of all input and output cubes from mapCubeloc_land: initial SINDBAD land with all fields and subfieldstem: a nested NT with necessary information of helpers, models, and spinup needed to run SINDBAD TEM and modelsselected_models: a tuple of all models selected in the given model structureforcing_vars: forcing variables
Code
function TEMYax(map_cubes...;selected_models::Tuple, forcing_vars::AbstractArray, loc_land::NamedTuple, output_vars, tem::NamedTuple)
outputs, inputs = unpackYaxForward(map_cubes; output_vars, forcing_vars)
loc_forcing = (; Pair.(forcing_vars, inputs)...)
land_out = coreTEMYax(selected_models, loc_forcing, loc_land, tem)
i = 1
foreach(output_vars) do var_pair
# @show i, var_pair
data = land_out[first(var_pair)][last(var_pair)]
fillOutputYax(outputs[i], data)
i += 1
end
endcoreTEM
Sindbad.Simulation.coreTEM Function
coreTEM(selected_models, loc_forcing, loc_spinup_forcing, loc_forcing_t, loc_land, tem_info, spinup_mode)Runs the SINDBAD Terrestrial Ecosystem Model (TEM) for a single location, with or without spinup, based on the specified spinup_mode.
Arguments:
selected_models: A tuple of all models selected in the given model structure.loc_forcing: A forcing NamedTuple containing the time series of environmental drivers for a single location.loc_spinup_forcing: A forcing NamedTuple for spinup, used to initialize the model to a steady state (only used if spinup is enabled).loc_forcing_t: A forcing NamedTuple for a single location and a single time step.loc_land: Initial SINDBAD land NamedTuple with all fields and subfields.tem_info: A helper NamedTuple containing necessary objects for model execution and type consistencies.spinup_mode: A type that determines whether spinup is included or excluded
Returns:
land_time_series: A vector of SINDBAD land states for each time step after the model simulation.
Code
function coreTEM end
function coreTEM(selected_models, loc_forcing, loc_spinup_forcing, loc_forcing_t, loc_land, tem_info, spinup_mode)
land_prec = precomputeTEM(selected_models, loc_forcing_t, loc_land, tem_info.model_helpers)
land_spin = spinupTEM(selected_models, loc_spinup_forcing, loc_forcing_t, land_prec, tem_info, spinup_mode)
land_time_series = timeLoopTEM(selected_models, loc_forcing, loc_forcing_t, land_spin, tem_info, tem_info.run.debug_model)
return land_time_series
end
function coreTEM(selected_models, loc_forcing, loc_spinup_forcing, loc_forcing_t, loc_land, tem_info, spinup_mode)
land_prec = precomputeTEM(selected_models, loc_forcing_t, loc_land, tem_info.model_helpers)
land_spin = spinupTEM(selected_models, loc_spinup_forcing, loc_forcing_t, land_prec, tem_info, spinup_mode)
land_time_series = timeLoopTEM(selected_models, loc_forcing, loc_forcing_t, land_spin, tem_info, tem_info.run.debug_model)
return land_time_series
end
function coreTEM(selected_models, loc_forcing, loc_spinup_forcing, loc_forcing_t, land_time_series, loc_land, tem_info, spinup_mode)
land_prec = precomputeTEM(selected_models, loc_forcing_t, loc_land, tem_info.model_helpers)
land_spin = spinupTEM(selected_models, loc_spinup_forcing, loc_forcing_t, land_prec, tem_info, spinup_mode)
timeLoopTEM(selected_models, loc_forcing, loc_forcing_t, land_time_series, land_spin, tem_info, tem_info.run.debug_model)
return nothing
endcoreTEM!
Sindbad.Simulation.coreTEM! Function
coreTEM!(selected_models, loc_forcing, loc_spinup_forcing, loc_forcing_t, loc_output, loc_land, tem_info)Executes the core SINDBAD Terrestrial Ecosystem Model (TEM) for a single location, including precomputations, spinup, and the main time loop.
Arguments:
selected_models: A tuple of all models selected in the given model structure.loc_forcing: A forcing NamedTuple containing the time series of environmental drivers for a single location.loc_spinup_forcing: A forcing NamedTuple for spinup, used to initialize the model to a steady state (only used if spinup is enabled).loc_forcing_t: A forcing NamedTuple for a single location and a single time step.loc_output: An output array or view for storing the model outputs for a single location.loc_land: Initial SINDBAD land NamedTuple with all fields and subfields.tem_info: A helper NamedTuple containing necessary objects for model execution and type consistencies.
Details
Executes the main TEM simulation logic with the provided parameters and data. Handles both regular simulation and spinup modes based on the spinup_mode flag.
Extended help
- Precomputations:
- The function runs
precomputeTEMto prepare the land state for the simulation.
- The function runs
Code
function coreTEM!(selected_models, loc_forcing, loc_spinup_forcing, loc_forcing_t, loc_output, loc_land, tem_info)
# update the loc_forcing with the actual location
loc_forcing_t = getForcingForTimeStep(loc_forcing, loc_forcing_t, 1, tem_info.vals.forcing_types)
# run precompute
land_prec = precomputeTEM(selected_models, loc_forcing_t, loc_land, tem_info.model_helpers)
# run spinup
land_spin = spinupTEM(selected_models, loc_spinup_forcing, loc_forcing_t, land_prec, tem_info, tem_info.run.spinup_TEM)
timeLoopTEM!(selected_models, loc_forcing, loc_forcing_t, loc_output, land_spin, tem_info.vals.forcing_types, tem_info.model_helpers, tem_info.vals.output_vars, tem_info.n_timesteps, tem_info.run.debug_model)
return nothing
endgetAllSpinupForcing
Sindbad.Simulation.getAllSpinupForcing Function
getAllSpinupForcing(forcing, spin_seq, tem_helpers)prepare the spinup forcing all forcing setups in the spinup sequence
Arguments:
forcing: a forcing NT that contains the forcing time series set for ALL locationsspin_seq: a sequence of information to carry out spinup at different steps with information on models to use, forcing, stopping critera, etc.tem_helpers: helper NT with necessary objects for model run and type consistencies
Returns:
spinup_forcing::NamedTuple: A NamedTuple containing aggregated forcing data for each spinup sequence
Examples
julia> using Sindbad
julia> # Prepare spinup forcing for all sequences
julia> # spinup_forcing = getAllSpinupForcing(forcing, spin_sequences, tem_helpers)Code
function getAllSpinupForcing(forcing, spin_sequences::Vector{SpinupSequenceWithAggregator}, tem_helpers)
spinup_forcing = (;)
for seq ∈ spin_sequences
forc = getfield(seq, :forcing)
forc_name = forc
if forc_name ∉ keys(spinup_forcing)
seq_forc = getSpinupForcing(forcing, seq, tem_helpers.vals.forcing_types)
spinup_forcing = set_namedtuple_field(spinup_forcing, (forc_name, seq_forc))
end
end
return spinup_forcing
endgetForcingForTimeStep
Sindbad.Simulation.getForcingForTimeStep Function
getForcingForTimeStep(forcing, loc_forcing_t, ts, Val{forc_with_type})Get forcing values for a specific time step based on the forcing type.
Arguments:
forcing: a forcing NT that contains the forcing time series set for ALL locationsloc_forcing_t: a forcing NT for a single timestep to be reused in every time stepts: time step to get the forcing forforc_with_type: Value type parameter specifying the forcing type
getLocData
Sindbad.Simulation.getLocData Function
getLocData(forcing, output_array, loc_ind)Arguments:
forcing: a forcing NT that contains the forcing time series set for ALL locationsoutput_array: an output array/view for ALL locationsloc_ind: a tuple with the spatial indices of the data for a given location
getLocData(forcing, output_array, loc_ind)Arguments:
output_array: an output array/view for ALL locationsloc_ind: a tuple with the spatial indices of the data for a given location
getLocData(forcing, output_array, loc_ind)Arguments:
forcing: a forcing NT that contains the forcing time series set for ALL locationsloc_ind: a tuple with the spatial indices of the data for a given location
Code
function getLocData(forcing::NamedTuple, output_array::AbstractArray, loc_ind)
loc_forcing = getLocData(forcing, loc_ind)
loc_output = getLocData(output_array, loc_ind)
return loc_forcing, loc_output
end
function getLocData(output_array::AbstractArray, loc_ind)
loc_output = map(output_array) do a
view_at_trailing_indices(a, loc_ind)
end
return loc_output
end
function getLocData(forcing::NamedTuple, loc_ind)
loc_forcing = map(forcing) do a
view_at_trailing_indices(a, loc_ind) |> Array
end
return loc_forcing
endgetOutDims
Sindbad.Simulation.getOutDims Function
getOutDims(info, forcing_helpers[, ::OutputArray | ::OutputMArray | ::OutputSizedArray | ::OutputYAXArray])Retrieves the dimensions for SINDBAD output based on the specified array backend.
Arguments:
info: A SINDBAD NamedTuple containing all information needed for setup and execution of an experiment.forcing_helpers: A NamedTuple with information on forcing sizes and dimensions.::OutputArray: (Optional) A type dispatch for using a base Array as the array backend.::OutputMArray: (Optional) A type dispatch for using MArray as the array backend.::OutputSizedArray: (Optional) A type dispatch for using SizedArray as the array backend.::OutputYAXArray: (Optional) A type dispatch for using YAXArray as the array backend.
Returns:
- A vector of output dimensions, where each dimension is represented as a tuple of
Dimobjects.
Notes:
For
OutputArray,OutputMArray, andOutputSizedArray, all dimensions are included.For
OutputYAXArray, spatial dimensions are excluded, and metadata is added for each variable.
Examples
julia> using Sindbad
julia> # Get output dimensions with default array type
julia> # outdims = getOutDims(info, forcing_helpers)
julia> # Get output dimensions with YAXArray
julia> # outdims = getOutDims(info, forcing_helpers, OutputYAXArray())Code
function getOutDims end
function getOutDims(info, forcing_helpers)
outdims = getOutDims(info, forcing_helpers, info.helpers.run.output_array_type)
return outdims
end
function getOutDims(info, forcing_helpers)
outdims = getOutDims(info, forcing_helpers, info.helpers.run.output_array_type)
return outdims
end
function getOutDims(info, forcing_helpers, ::Union{OutputArray, OutputMArray, OutputSizedArray})
outdims_pairs = getOutDimsPairs(info.output, forcing_helpers)
outdims = map(outdims_pairs) do dim_pairs
od = []
for _dim in dim_pairs
push!(od, YAXArrays.Dim{first(_dim)}(last(_dim)))
end
Tuple(od)
end
return outdims
end
function getOutDims(info, forcing_helpers, ::OutputYAXArray)
outdims_pairs = getOutDimsPairs(info.output, forcing_helpers);
space_dims = Symbol.(info.experiment.data_settings.forcing.data_dimension.space)
var_dims = map(outdims_pairs) do dim_pairs
od = []
for _dim in dim_pairs
if first(_dim) ∉ space_dims
push!(od, YAXArrays.Dim{first(_dim)}(last(_dim)))
end
end
Tuple(od)
end
v_index = 1
outdims = map(info.output.variables) do vname_full
vname = string(last(vname_full))
_properties = collectMetadata(info, vname_full)
vdims = var_dims[v_index]
outformat = info.settings.experiment.model_output.format
backend = outformat == "nc" ? :netcdf : :zarr
out_dim = YAXArrays.OutDims(vdims...;
properties = _properties,
path=info.output.file_info.file_prefix * "_$(vname).$(outformat)",
backend=backend,
overwrite=true)
v_index += 1
out_dim
end
return outdims
end
function getOutDimsArrays end
function getOutDimsArrays(info, forcing_helpers)
outdims, outarray = getOutDimsArrays(info, forcing_helpers, info.helpers.run.output_array_type)
return outdims, outarray
end
function getOutDimsArrays(info, forcing_helpers)
outdims, outarray = getOutDimsArrays(info, forcing_helpers, info.helpers.run.output_array_type)
return outdims, outarray
end
function getOutDimsArrays(info, forcing_helpers, oarr::OutputArray)
outdims = getOutDims(info, forcing_helpers, oarr)
outarray = getNumericArrays(info, forcing_helpers.sizes)
return outdims, outarray
end
function getOutDimsArrays(info, forcing_helpers, omarr::OutputMArray)
outdims = getOutDims(info, forcing_helpers, omarr)
outarray = getNumericArrays(info, forcing_helpers.sizes)
marray = MArray{Tuple{size(outarray)...},eltype(outarray)}(undef)
return outdims, marray
end
function getOutDimsArrays(info, forcing_helpers, osarr::OutputSizedArray)
outdims = getOutDims(info, forcing_helpers, osarr)
outarray = getNumericArrays(info, forcing_helpers.sizes)
sized_array = SizedArray{Tuple{size(outarray)...},eltype(outarray)}(undef)
return outdims, sized_array
end
function getOutDimsArrays(info, forcing_helpers, oayax::OutputYAXArray)
outdims = getOutDims(info, forcing_helpers, oayax)
outarray = nothing
return outdims, outarray
end
function getOutDimsPairs(tem_output, forcing_helpers; dthres=1)
forcing_axes = forcing_helpers.axes
dim_loops = first.(forcing_axes)
axes_dims_pairs = []
if !isnothing(forcing_helpers.dimensions.permute)
dim_perms = Symbol.(forcing_helpers.dimensions.permute)
if dim_loops !== dim_perms
for ix in eachindex(dim_perms)
dp_i = dim_perms[ix]
dl_ind = findall(x -> x == dp_i, dim_loops)[1]
f_a = forcing_axes[dl_ind]
ax_dim = Pair(first(f_a), last(f_a))
push!(axes_dims_pairs, ax_dim)
end
end
else
axes_dims_pairs = map(x -> Pair(first(x), last(x)), forcing_axes)
end
opInd = 1
outdims_pairs = map(tem_output.variables) do vname_full
depth_info = tem_output.depth_info[opInd]
depth_size = first(depth_info)
depth_name = last(depth_info)
od = []
push!(od, axes_dims_pairs[1])
if depth_size > dthres
if depth_size == 1
depth_name = "idx"
end
push!(od, Pair(Symbol(depth_name), (1:depth_size)))
end
foreach(axes_dims_pairs[2:end]) do f_d
push!(od, f_d)
end
opInd += 1
Tuple(od)
end
return outdims_pairs
endgetOutDimsArrays
Sindbad.Simulation.getOutDimsArrays Function
getOutDimsArrays(info, forcing_helpers[, ::OutputArray | ::OutputMArray | ::OutputSizedArray | ::OutputYAXArray])Retrieves the dimensions and corresponding data for SINDBAD output based on the specified array backend.
Arguments:
info: A SINDBAD NamedTuple containing all information needed for setup and execution of an experiment.forcing_helpers: A NamedTuple with information on forcing sizes and dimensions.::OutputArray: (Optional) A type dispatch for using a base Array as the array backend.::OutputMArray: (Optional) A type dispatch for using MArray as the array backend.::OutputSizedArray: (Optional) A type dispatch for using SizedArray as the array backend.::OutputYAXArray: (Optional) A type dispatch for using YAXArray as the array backend.
Returns:
- A tuple
(outdims, outarray):outdims: A vector of output dimensions, where each dimension is represented as a tuple ofDimobjects.outarray: The corresponding data array, initialized based on the specified array backend.
Notes:
For
OutputArray,OutputMArray, andOutputSizedArray, the data array is initialized with the appropriate backend type.For
OutputYAXArray, the data array is set tonothing, as YAXArray handles data differently.
Examples:
- Using a base Array:
outdims, outarray = getOutDimsArrays(info, forcing_helpers, OutputArray())- Using MArray:
outdims, outarray = getOutDimsArrays(info, forcing_helpers, OutputMArray())- Using SizedArray:
outdims, outarray = getOutDimsArrays(info, forcing_helpers, OutputSizedArray())- Using YAXArray:
outdims, outarray = getOutDimsArrays(info, forcing_helpers, OutputYAXArray())- Default behavior:
outdims, outarray = getOutDimsArrays(info, forcing_helpers)Code
function getOutDimsArrays end
function getOutDimsArrays(info, forcing_helpers)
outdims, outarray = getOutDimsArrays(info, forcing_helpers, info.helpers.run.output_array_type)
return outdims, outarray
end
function getOutDimsArrays(info, forcing_helpers)
outdims, outarray = getOutDimsArrays(info, forcing_helpers, info.helpers.run.output_array_type)
return outdims, outarray
end
function getOutDimsArrays(info, forcing_helpers, oarr::OutputArray)
outdims = getOutDims(info, forcing_helpers, oarr)
outarray = getNumericArrays(info, forcing_helpers.sizes)
return outdims, outarray
end
function getOutDimsArrays(info, forcing_helpers, omarr::OutputMArray)
outdims = getOutDims(info, forcing_helpers, omarr)
outarray = getNumericArrays(info, forcing_helpers.sizes)
marray = MArray{Tuple{size(outarray)...},eltype(outarray)}(undef)
return outdims, marray
end
function getOutDimsArrays(info, forcing_helpers, osarr::OutputSizedArray)
outdims = getOutDims(info, forcing_helpers, osarr)
outarray = getNumericArrays(info, forcing_helpers.sizes)
sized_array = SizedArray{Tuple{size(outarray)...},eltype(outarray)}(undef)
return outdims, sized_array
end
function getOutDimsArrays(info, forcing_helpers, oayax::OutputYAXArray)
outdims = getOutDims(info, forcing_helpers, oayax)
outarray = nothing
return outdims, outarray
endgetSequence
Sindbad.Simulation.getSequence Function
getSequence(year_disturbance, nrepeat_base=200, year_start = 1979)Arguments:
year_disturbance: a year date, as an stringnrepeat_base=200 [default]year_start: 1979 [default] start year, as an interger
Outputs
- new spinup sequence object
Code
function getSequence(year_disturbance, info_helpers_dates; nrepeat_base=200, year_start = 1979)
nrepeat_age = nrepeatYearsAge(year_disturbance; year_start)
sequence = [
Dict("spinup_mode" => "sel_spinup_models", "forcing" => "all_years", "n_repeat" => 1),
Dict("spinup_mode" => "sel_spinup_models", "forcing" => "day_MSC", "n_repeat" => nrepeat_base),
Dict("spinup_mode" => "eta_scale_AH", "forcing" => "day_MSC", "n_repeat" => 1),
]
if nrepeat_age == 0
sequence = [
Dict("spinup_mode" => "sel_spinup_models", "forcing" => "all_years", "n_repeat" => 1),
Dict("spinup_mode" => "sel_spinup_models", "forcing" => "day_MSC", "n_repeat" => nrepeat_base),
Dict("spinup_mode" => "eta_scale_A0H", "forcing" => "day_MSC", "n_repeat" => 1),
]
elseif nrepeat_age > 0
sequence = [
Dict("spinup_mode" => "sel_spinup_models", "forcing" => "all_years", "n_repeat" => 1),
Dict("spinup_mode" => "sel_spinup_models", "forcing" => "day_MSC", "n_repeat" => nrepeat_base),
Dict("spinup_mode" => "eta_scale_A0H", "forcing" => "day_MSC", "n_repeat" => 1),
Dict("spinup_mode" => "sel_spinup_models", "forcing" => "day_MSC", "n_repeat" => nrepeat_age),
]
end
new_sequence = getSpinupTemLite(getSpinupSequenceWithTypes(sequence, info_helpers_dates))
return new_sequence
endgetSpatialInfo
Sindbad.Simulation.getSpatialInfo Function
getSpatialInfo(forcing_helpers)
getSpatialInfo(forcing, filterNanPixels)get the information of the indices of the data to run the model for. The second variant additionally filter pixels with all nan data
Arguments:
forcing: a forcing NT that contains the forcing time series set for ALL locations
Code
function getSpatialInfo end
function getSpatialInfo(forcing_helpers)
@debug " getting the space locations to run the model loop"
forcing_sizes = forcing_helpers.sizes
loopvars = collect(keys(forcing_sizes))
additionaldims = setdiff(loopvars, [Symbol(forcing_helpers.dimensions.time)])
spacesize = values(forcing_sizes[additionaldims])
loc_space_maps = vec(collect(Iterators.product(Base.OneTo.(spacesize)...)))
loc_space_maps = map(loc_space_maps) do loc_names
map(zip(loc_names, additionaldims)) do (loc_index, lv)
lv => loc_index
end
end
loc_space_maps = Tuple(loc_space_maps)
space_ind = Tuple([Tuple(last.(loc_space_map)) for loc_space_map ∈ loc_space_maps])
return space_ind, loc_space_maps
end
function getSpatialInfo(forcing_helpers)
@debug " getting the space locations to run the model loop"
forcing_sizes = forcing_helpers.sizes
loopvars = collect(keys(forcing_sizes))
additionaldims = setdiff(loopvars, [Symbol(forcing_helpers.dimensions.time)])
spacesize = values(forcing_sizes[additionaldims])
loc_space_maps = vec(collect(Iterators.product(Base.OneTo.(spacesize)...)))
loc_space_maps = map(loc_space_maps) do loc_names
map(zip(loc_names, additionaldims)) do (loc_index, lv)
lv => loc_index
end
end
loc_space_maps = Tuple(loc_space_maps)
space_ind = Tuple([Tuple(last.(loc_space_map)) for loc_space_map ∈ loc_space_maps])
return space_ind, loc_space_maps
end
function getSpatialInfo(forcing, filter_nan_pixels)
space_ind, loc_space_maps = getSpatialInfo(forcing.helpers)
loc_space_maps = filterNanPixels(forcing, loc_space_maps, filter_nan_pixels)
space_ind = Tuple([Tuple(last.(loc_space_map)) for loc_space_map ∈ loc_space_maps])
return space_ind
endprepTEM
Sindbad.Simulation.prepTEM Function
prepTEM(forcing::NamedTuple, info::NamedTuple)
prepTEM(selected_models, forcing::NamedTuple, info::NamedTuple)
prepTEM(selected_models, forcing::NamedTuple, observations::NamedTuple, info::NamedTuple)Prepares the SINDBAD Terrestrial Ecosystem Model (TEM) for execution by setting up the necessary inputs, outputs, and configurations with different variants for different experimental setups.
Arguments:
selected_models: A tuple of all models selected in the given model structure.forcing::NamedTuple: A forcing NamedTuple containing the time series of environmental drivers for all locations.observations::NamedTuple: A NamedTuple containing observational data for model validation.info::NamedTuple: A nested NamedTuple containing necessary information, including:Helpers for running the model.
Model configurations.
Spinup settings.
Returns:
run_helpers: A NamedTuple containing preallocated data and configurations required to run the TEM, including:Spatial forcing data.
Spinup forcing data.
Output arrays.
Land variables.
Temporal and spatial indices.
Model and helper configurations.
Notes:
The function dynamically prepares the required data structures based on the specified
PreAllocputTypeininfo.helpers.run.land_output_type.It handles spatial and temporal data preparation, including filtering NaN pixels, initializing land variables, and setting up forcing and output arrays.
This function is a key step in preparing the SINDBAD TEM for execution.
Examples:
- Preparing TEM with observations:
selected_models = (model1, model2)
forcing = (data = ..., variables = ...)
observations = (data = ..., variables = ...)
info = (helpers = ..., models = ..., spinup = ...)
run_helpers = prepTEM(selected_models, forcing, observations, info)- Preparing TEM without observations:
selected_models = (model1, model2)
forcing = (data = ..., variables = ...)
info = (helpers = ..., models = ..., spinup = ...)
run_helpers = prepTEM(selected_models, forcing, info)Code
function prepTEM end
function prepTEM(forcing::NamedTuple, info::NamedTuple)
selected_models = info.models.forward
return prepTEM(selected_models, forcing, info)
end
function prepTEM(forcing::NamedTuple, info::NamedTuple)
selected_models = info.models.forward
return prepTEM(selected_models, forcing, info)
end
function prepTEM(selected_models, forcing::NamedTuple, info::NamedTuple)
print_info(prepTEM, @__FILE__, @__LINE__, "preparing to run terrestrial ecosystem model (TEM)", n_f=1)
output = prepTEMOut(info, forcing.helpers)
print_info(prepTEM, @__FILE__, @__LINE__, " preparing helpers for running model experiment", n_f=4)
run_helpers = helpPrepTEM(selected_models, info, forcing, output, info.helpers.run.land_output_type)
print_info_separator()
return run_helpers
end
function prepTEM(selected_models, forcing::NamedTuple, observations::NamedTuple, info::NamedTuple)
print_info(prepTEM, @__FILE__, @__LINE__, "preparing to run terrestrial ecosystem model (TEM)", n_f=1)
output = prepTEMOut(info, forcing.helpers)
run_helpers = helpPrepTEM(selected_models, info, forcing, observations, output, info.helpers.run.land_output_type)
print_info_separator()
return run_helpers
endprepTEMOut
Sindbad.Simulation.prepTEMOut Function
prepTEMOut(info::NamedTuple, forcing_helpers::NamedTuple)Prepares the output NamedTuple required for running the Terrestrial Ecosystem Model (TEM) in SINDBAD.
Arguments:
info: A SINDBAD NamedTuple containing all information needed for setup and execution of an experiment.forcing_helpers: A NamedTuple with information on forcing sizes and dimensions.
Returns:
A NamedTuple output_tuple containing:
land_init: The initial land state frominfo.land_init.dims: A vector of output dimensions, where each dimension is represented as a tuple ofDimobjects.data: A vector of numeric arrays initialized for output variables.variables: A list of output variable names.Additional fields for optimization output if optimization is enabled.
Notes:
The function initializes the output dimensions and data arrays based on the specified array backend (
info.helpers.run.output_array_type).If optimization is enabled (
info.helpers.run.run_optimization), additional fields for optimized parameters are added to the output.The function uses helper functions like
getOutDimsArraysandsetupOptiOutputto prepare the output.
Examples:
- Basic usage:
output_tuple = prepTEMOut(info, forcing_helpers)- Accessing output fields:
dims = output_tuple.dims
data = output_tuple.data
variables = output_tuple.variablesCode
function prepTEMOut(info::NamedTuple, forcing_helpers::NamedTuple)
print_info(prepTEMOut, @__FILE__, @__LINE__, "preparing output helpers for Terrestrial Ecosystem Model (TEM)", n_f=4)
land = info.helpers.land_init
output_tuple = (;)
output_tuple = set_namedtuple_field(output_tuple, (:land_init, land))
@debug " prepTEMOut: getting out variables, dimension and arrays..."
outdims, outarray = getOutDimsArrays(info, forcing_helpers, info.helpers.run.output_array_type)
output_tuple = set_namedtuple_field(output_tuple, (:dims, outdims))
output_tuple = set_namedtuple_field(output_tuple, (:data, outarray))
output_tuple = set_namedtuple_field(output_tuple, (:variables, info.output.variables))
output_tuple = setupOptiOutput(info, output_tuple, info.helpers.run.run_optimization)
@debug "\n----------------------------------------------\n"
return output_tuple
endrunTEM
Sindbad.Simulation.runTEM Function
runTEM(forcing::NamedTuple, info::NamedTuple)
runTEM(selected_models::Tuple, forcing::NamedTuple, loc_spinup_forcing, loc_forcing_t, loc_land::NamedTuple, tem_info::NamedTuple)
runTEM(selected_models::Tuple, loc_forcing::NamedTuple, loc_spinup_forcing, loc_forcing_t, land_time_series, loc_land::NamedTuple, tem_info::NamedTuple)Runs the SINDBAD Terrestrial Ecosystem Model (TEM) for a single location, with or without spinup, based on the provided configurations. The two main variants are the ones with and without the preallocated land time series. The shorthand version with two input arguments calls the one without preallocated land time series.
Arguments:
selected_models: A tuple of all models selected in the given model structure.forcing::NamedTuple: A forcing NamedTuple containing the time series of environmental drivers for all locations.loc_spinup_forcing: A forcing NamedTuple for spinup, used to initialize the model to a steady state.loc_forcing_t: A forcing NamedTuple for a single location and a single time step.loc_land::NamedTuple: Initial SINDBAD land NamedTuple with all fields and subfields.tem_info::NamedTuple: A nested NamedTuple containing necessary information, including:Model helpers.
Spinup configurations.
Debugging options.
Output configurations.
Returns:
LandWrapper: A wrapper containing the time series of SINDBAD land states for each time step after the model simulation.
Notes:
The function internally calls
coreTEMto handle the main simulation logic.If spinup is enabled (
DoSpinupTEM), the function runs the spinup process before the main simulation.If spinup is disabled (
DoNotSpinupTEM), the function directly runs the main simulation.The function prepares the necessary inputs and configurations using
prepTEMbefore executing the simulation.
Examples
julia> using Sindbad
julia> # Run TEM with spinup (shorthand version)
julia> # land_time_series = runTEM(forcing, info)
julia> # Run TEM with spinup (detailed version)
julia> # land_time_series = runTEM(selected_models, forcing, loc_spinup_forcing, loc_forcing_t, loc_land, tem_info)
julia> # Run TEM without spinup
julia> # land_time_series = runTEM(selected_models, forcing, nothing, loc_forcing_t, loc_land, tem_info)Code
function runTEMOne(selected_models, loc_forcing, land_init, tem)
loc_forcing_t = getForcingForTimeStep(loc_forcing, loc_forcing, 1, tem.vals.forcing_types)
loc_land = definePrecomputeTEM(selected_models, loc_forcing_t, land_init,
tem.model_helpers)
loc_land = computeTEM(selected_models, loc_forcing_t, loc_land, tem.model_helpers)
# loc_land = drop_empty_namedtuple_fields(loc_land)
loc_land = addSpinupLog(loc_land, tem.spinup_sequence, tem.run.store_spinup)
# loc_land = definePrecomputeTEM(selected_models, loc_forcing_t, loc_land,
# tem.model_helpers)
# loc_land = precomputeTEM(selected_models, loc_forcing_t, loc_land,
# tem.model_helpers)
# loc_land = computeTEM(selected_models, loc_forcing_t, loc_land, tem.model_helpers)
return loc_forcing_t, loc_land
endrunTEM!
Sindbad.Simulation.runTEM! Function
runTEM!(selected_models, forcing::NamedTuple, info::NamedTuple)
runTEM!(forcing::NamedTuple, info::NamedTuple)
runTEM!(selected_models, space_forcing, space_spinup_forcing, loc_forcing_t, space_output, space_land, tem_info::NamedTuple)Runs the SINDBAD Terrestrial Ecosystem Model (TEM) for all locations and time steps using preallocated arrays as the model data backend. This function supports multiple configurations for efficient execution.
Arguments:
- For the first variant:
selected_models: A tuple of all models selected in the given model structure.forcing::NamedTuple: A forcing NamedTuple containing the time series of environmental drivers for all locations.info::NamedTuple: A SINDBAD NamedTuple containing all information needed for setup and execution of an experiment.
- For the second variant:
forcing::NamedTuple: A forcing NamedTuple containing the time series of environmental drivers for all locations.info::NamedTuple: A SINDBAD NamedTuple containing all information needed for setup and execution of an experiment.
- For the third variant:
selected_models: A tuple of all models selected in the given model structure.space_forcing: A collection of forcing NamedTuples for multiple locations, replicated to avoid data races during parallel execution.space_spinup_forcing: A collection of spinup forcing NamedTuples for multiple locations, replicated to avoid data races during parallel execution.loc_forcing_t: A forcing NamedTuple for a single location and a single time step.space_output: A collection of output arrays/views for multiple locations, replicated to avoid data races during parallel execution.space_land: A collection of initial SINDBAD land NamedTuples for multiple locations, ensuring that the model states for one location do not overwrite those of another.tem_info::NamedTuple: A helper NamedTuple containing necessary objects for model execution and type consistencies.
Returns:
output_array: A preallocated array containing the simulation results for all locations and time steps.
Notes:
Precomputations:
- The function uses
prepTEMto prepare the necessary inputs and configurations for the simulation.
- The function uses
Parallel Execution:
- The function uses
parallelizeTEM!to distribute the simulation across multiple locations using the specified parallelization backend (Threads.@threadsorqbmap).
- The function uses
Core Execution:
- For each location, the function calls
coreTEM!to execute the TEM simulation, including spinup (if enabled) and the main time loop.
- For each location, the function calls
Data Safety:
- The function ensures data safety by replicating forcing, output, and land data for each location, avoiding data races during parallel execution.
Examples
julia> using Sindbad
julia> # Run TEM with preallocated arrays (shorthand)
julia> # output_array = runTEM!(forcing, info)
julia> # Run TEM with preallocated arrays (detailed)
julia> # output_array = runTEM!(selected_models, forcing, info)
julia> # Run TEM with precomputed helpers
julia> # runTEM!(selected_models, space_forcing, space_spinup_forcing, loc_forcing_t, space_output, space_land, tem_info)Code
function runTEM! end
function runTEM!(selected_models, forcing::NamedTuple, info::NamedTuple)
run_helpers = prepTEM(selected_models, forcing, info)
runTEM!(run_helpers.space_selected_models, run_helpers.space_forcing, run_helpers.space_spinup_forcing, run_helpers.loc_forcing_t, run_helpers.space_output, run_helpers.space_land, run_helpers.tem_info)
return run_helpers.output_array
end
function runTEM!(selected_models, forcing::NamedTuple, info::NamedTuple)
run_helpers = prepTEM(selected_models, forcing, info)
runTEM!(run_helpers.space_selected_models, run_helpers.space_forcing, run_helpers.space_spinup_forcing, run_helpers.loc_forcing_t, run_helpers.space_output, run_helpers.space_land, run_helpers.tem_info)
return run_helpers.output_array
end
function runTEM!(forcing::NamedTuple, info::NamedTuple)
run_helpers = prepTEM(forcing, info)
runTEM!(run_helpers.space_selected_models, run_helpers.space_forcing, run_helpers.space_spinup_forcing, run_helpers.loc_forcing_t, run_helpers.space_output, run_helpers.space_land, run_helpers.tem_info)
return run_helpers.output_array
end
function runTEM!(space_selected_models, space_forcing, space_spinup_forcing, loc_forcing_t, space_output, space_land, tem_info::NamedTuple)
parallelizeTEM!(space_selected_models, space_forcing, space_spinup_forcing, loc_forcing_t, space_output, space_land, tem_info, tem_info.run.parallelization)
return nothing
endrunTEMYax
Sindbad.Simulation.runTEMYax Function
runTEMYax(forcing::NamedTuple, output::NamedTuple, tem::NamedTuple, selected_models::Tuple; max_cache = 1.0e9)Arguments:
forcing: a forcing NT that contains the forcing time series set for ALL locationsoutput: an output NT including the data arrays, as well as information of variables and dimensionstem: a nested NT with necessary information of helpers, models, and spinup needed to run SINDBAD TEM and modelsselected_models: a tuple of all models selected in the given model structuremax_cache: cache size to use for mapCube
Code
function runTEMYax(selected_models::Tuple, forcing::NamedTuple, info::NamedTuple)
# forcing/input information
incubes = forcing.data;
indims = forcing.dims;
# information for running model
run_helpers = prepTEM(forcing, info);
loc_land = deepcopy(run_helpers.loc_land);
outcubes = mapCube(TEMYax,
(incubes...,);
selected_models=selected_models,
forcing_vars=forcing.variables,
output_vars = run_helpers.output_vars,
loc_land=loc_land,
tem=run_helpers.tem_info,
indims=indims,
outdims=run_helpers.output_dims,
max_cache=info.settings.experiment.exe_rules.yax_max_cache,
ispar=true)
return outcubes
endsetOutputForTimeStep!
Sindbad.Simulation.setOutputForTimeStep! Function
setOutputForTimeStep!(outputs, land, ts, Val{output_vars})Arguments:
outputs: vector of model output vectorsland: a core SINDBAD NT that contains all variables for a given time step that is overwritten at every timestepts: time step::Val{output_vars}: a dispatch for vals of the output variables to generate the function
setSequence
Sindbad.Simulation.setSequence Function
setSequence(tem_info, new_sequence)Arguments:
tem_info: Tuple with the fieldspinup_sequencenew_sequence
Outputs
- an updated tem_info object with new spinup sequence modes
Code
function setSequence(tem_info, new_sequence)
return @set tem_info.spinup_sequence = new_sequence
endsetupOptiOutput
Sindbad.Simulation.setupOptiOutput Function
setupOptiOutput(info::NamedTuple, output::NamedTuple[, ::DoRunOptimization | ::DoNotRunOptimization])Creates the output fields needed for the optimization experiment.
Arguments:
info: A SINDBAD NamedTuple containing all information needed for setup and execution of an experiment.output: A base output NamedTuple to which optimization-specific fields will be added.::DoRunOptimization: (Optional) A type dispatch indicating that optimization is enabled. Adds fields for optimized parameters.::DoNotRunOptimization: (Optional) A type dispatch indicating that optimization is not enabled. Returns the base output unchanged.
Returns:
- A NamedTuple containing the base output fields, with additional fields for optimization if enabled.
Notes:
When optimization is enabled, the function:
Adds a
parameter_dimfield to the output, which includes the parameter dimension and metadata.Creates an
OutDimsobject for storing optimized parameters, with the appropriate backend and file path.
When optimization is not enabled, the function simply returns the input
outputNamedTuple unchanged.
Examples:
- With optimization enabled:
output = setupOptiOutput(info, output, DoRunOptimization())- Without optimization:
output = setupOptiOutput(info, output, DoNotRunOptimization())Code
function setupOptiOutput end
function setupOptiOutput(info::NamedTuple, output::NamedTuple, ::DoRunOptimization)
@debug " setupOptiOutput: getting parameter output for optimization..."
params = info.optimization.parameter_table.name_full
paramaxis = YAXArrays.Dim{:parameter}(params)
outformat = info.output.format
backend = outformat == "nc" ? :netcdf : :zarr
od = YAXArrays.OutDims(paramaxis;
path=joinpath(info.output.dirs.optimization,
"optimized_parameters.$(outformat)"),
backend=backend,
overwrite=true)
# list of parameter
output = set_namedtuple_field(output, (:parameter_dim, od))
return output
end
function setupOptiOutput(info::NamedTuple, output::NamedTuple, ::DoRunOptimization)
@debug " setupOptiOutput: getting parameter output for optimization..."
params = info.optimization.parameter_table.name_full
paramaxis = YAXArrays.Dim{:parameter}(params)
outformat = info.output.format
backend = outformat == "nc" ? :netcdf : :zarr
od = YAXArrays.OutDims(paramaxis;
path=joinpath(info.output.dirs.optimization,
"optimized_parameters.$(outformat)"),
backend=backend,
overwrite=true)
# list of parameter
output = set_namedtuple_field(output, (:parameter_dim, od))
return output
end
function setupOptiOutput(info::NamedTuple, output::NamedTuple, ::DoNotRunOptimization)
return output
endspinup
Sindbad.Simulation.spinup Function
spinup(spinup_models, spinup_forcing, loc_forcing_t, land, tem_info, n_timesteps, spinup_mode::SpinupMode)Runs the spinup process for the SINDBAD Terrestrial Ecosystem Model (TEM) to initialize the model to a steady state. The spinup process updates the state variables (e.g., pools) using various spinup methods.
Arguments:
spinup_models: A tuple of a subset of all models in the given model structure that are selected for spinup.spinup_forcing: A forcing NamedTuple containing the time series of environmental drivers for the spinup process.loc_forcing_t: A forcing NamedTuple for a single location and a single time step.land: A SINDBAD NamedTuple containing all variables for a given time step, which is overwritten at every timestep.tem_info: A helper NamedTuple containing necessary objects for model execution and type consistencies.n_timesteps: The number of timesteps for the spinup process.spinup_mode::SpinupMode: A type dispatch that determines the spinup method to be used.
Returns:
land: The updated SINDBAD NamedTuple containing the final state of the model after the spinup process.
SpinupMode
Abstract type for model spinup modes in SINDBAD
Available methods/subtypes:
AllForwardModels: Use all forward models for spinupEtaScaleA0H: scale carbon pools using diagnostic scalars for ηH and c_remainEtaScaleA0HCWD: scale carbon pools of CWD (cLitSlow) using ηH and set vegetation pools to c_remainEtaScaleAH: scale carbon pools using diagnostic scalars for ηH and ηAEtaScaleAHCWD: scale carbon pools of CWD (cLitSlow) using ηH and scale vegetation pools by ηANlsolveFixedpointTrustregionCEco: use a fixed-point nonlinear solver with trust region for carbon pools (cEco)NlsolveFixedpointTrustregionCEcoTWS: use a fixed-point nonlinear solver with trust region for both cEco and TWSNlsolveFixedpointTrustregionTWS: use a fixed-point nonlinearsolver with trust region for Total Water Storage (TWS)ODEAutoTsit5Rodas5: use the AutoVern7(Rodas5) method from DifferentialEquations.jl for solving ODEsODEDP5: use the DP5 method from DifferentialEquations.jl for solving ODEsODETsit5: use the Tsit5 method from DifferentialEquations.jl for solving ODEsSSPDynamicSSTsit5: use the SteadyState solver with DynamicSS and Tsit5 methodsSSPSSRootfind: use the SteadyState solver with SSRootfind methodSelSpinupModels: run only the models selected for spinup in the model structureSpinup_TWS: Spinup spinup_mode for Total Water Storage (TWS)Spinup_cEco: Spinup spinup_mode for cEcoSpinup_cEco_TWS: Spinup spinup_mode for cEco and TWS
Extended help
Notes:
The spinup process can use different methods depending on the
spinup_mode, including fixed-point solvers, ODE solvers, and steady-state solvers.The function dynamically selects the appropriate spinup method based on the
spinup_modedispatch type.For ODE-based methods, the function uses DifferentialEquations.jl to solve the spinup equations.
For steady-state solvers, the function uses methods like
DynamicSSorSSRootfindto find equilibrium states.
Examples:
- Running spinup with selected models:
land = spinup(spinup_models, spinup_forcing, loc_forcing_t, land, tem_info, n_timesteps, SelSpinupModels())- Running spinup with ODE solver (Tsit5):
land = spinup(spinup_models, spinup_forcing, loc_forcing_t, land, tem_info, n_timesteps, ODETsit5())- Running spinup with fixed-point solver for cEco and TWS:
land = spinup(spinup_models, spinup_forcing, loc_forcing_t, land, tem_info, n_timesteps, NlsolveFixedpointTrustregionCEcoTWS())- Running spinup with steady-state solver (SSRootfind):
land = spinup(spinup_models, spinup_forcing, loc_forcing_t, land, tem_info, n_timesteps, SSPSSRootfind())Code
function spinup(::Any, ::Any, ::Any, land, ::Any, ::Any, x::SpinupMode)
@warn "
Spinup mode `$(nameof(typeof(x)))` not implemented.
To implement a new spinup mode:
- First add a new type as a subtype of `SpinupMode` in `src/Types/SimulationTypes.jl`.
- Then, add a corresponding method.
- if it can be implemented as an internal Sindbad method without additional dependencies, implement the method in `src/Simulation/spinupTEM.jl`.
- if it requires additional dependencies, implement the method in `ext/<extension_name>/SimulationSpinup.jl` extension.
As a fallback, this function will return the land as is.
"
return land
end
function spinup(spinup_models, spinup_forcing, loc_forcing_t, land, tem_info, n_timesteps, ::SelSpinupModels)
land = timeLoopTEMSpinup(spinup_models, spinup_forcing, loc_forcing_t, land, tem_info, n_timesteps)
return land
end
function spinup(all_models, spinup_forcing, loc_forcing_t, land, tem_info, n_timesteps, ::AllForwardModels)
land = timeLoopTEMSpinup(all_models, spinup_forcing, loc_forcing_t, land, tem_info, n_timesteps)
return land
end
function spinup(_, _, _, land, helpers, _, ::EtaScaleAH)
@unpack_nt cEco ⇐ land.pools
helpers = helpers.model_helpers
cEco_prev = copy(cEco)
ηH = one(eltype(cEco))
if :ηH ∈ propertynames(land.diagnostics)
ηH = land.diagnostics.ηH
end
ηA = one(eltype(cEco))
if :ηA ∈ propertynames(land.diagnostics)
ηA = land.diagnostics.ηA
end
for cSoilZix ∈ helpers.pools.zix.cSoil
cSoilNew = cEco[cSoilZix] * ηH
@rep_elem cSoilNew ⇒ (cEco, cSoilZix, :cEco)
end
for cLitZix ∈ helpers.pools.zix.cLit
cLitNew = cEco[cLitZix] * ηH
@rep_elem cLitNew ⇒ (cEco, cLitZix, :cEco)
end
for cVegZix ∈ helpers.pools.zix.cVeg
cVegNew = cEco[cVegZix] * ηA
@rep_elem cVegNew ⇒ (cEco, cVegZix, :cEco)
end
@pack_nt cEco ⇒ land.pools
land = SindbadTEM.adjustPackPoolComponents(land, helpers, land.models.c_model)
@pack_nt cEco_prev ⇒ land.states
return land
end
function spinup(_, _, _, land, helpers, _, ::EtaScaleAHCWD)
@unpack_nt cEco ⇐ land.pools
helpers = helpers.model_helpers
cEco_prev = copy(cEco)
ηH = one(eltype(cEco))
if :ηH ∈ propertynames(land.diagnostics)
ηH = land.diagnostics.ηH
end
ηA = one(eltype(cEco))
if :ηA ∈ propertynames(land.diagnostics)
ηA = land.diagnostics.ηA
end
for cLitZix ∈ helpers.pools.zix.cLitSlow
cLitNew = cEco[cLitZix] * ηH
@rep_elem cLitNew ⇒ (cEco, cLitZix, :cEco)
end
for cVegZix ∈ helpers.pools.zix.cVeg
cVegNew = cEco[cVegZix] * ηA
@rep_elem cVegNew ⇒ (cEco, cVegZix, :cEco)
end
@pack_nt cEco ⇒ land.pools
land = SindbadTEM.adjustPackPoolComponents(land, helpers, land.models.c_model)
@pack_nt cEco_prev ⇒ land.states
return land
end
function spinup(_, _, _, land, helpers, _, ::EtaScaleA0H)
@unpack_nt cEco ⇐ land.pools
helpers = helpers.model_helpers
cEco_prev = copy(cEco)
ηH = one(eltype(cEco))
c_remain = one(eltype(cEco))
if :ηH ∈ propertynames(land.diagnostics)
ηH = land.diagnostics.ηH
c_remain = land.states.c_remain
end
for cSoilZix ∈ helpers.pools.zix.cSoil
cSoilNew = cEco[cSoilZix] * ηH
@rep_elem cSoilNew ⇒ (cEco, cSoilZix, :cEco)
end
for cLitZix ∈ helpers.pools.zix.cLit
cLitNew = cEco[cLitZix] * ηH
@rep_elem cLitNew ⇒ (cEco, cLitZix, :cEco)
end
for cVegZix ∈ helpers.pools.zix.cVeg
cLoss = at_least_zero(cEco[cVegZix] - c_remain)
cVegNew = cEco[cVegZix] - cLoss
@rep_elem cVegNew ⇒ (cEco, cVegZix, :cEco)
end
@pack_nt cEco ⇒ land.pools
land = SindbadTEM.adjustPackPoolComponents(land, helpers, land.models.c_model)
@pack_nt cEco_prev ⇒ land.states
return land
end
function spinup(_, _, _, land, helpers, _, ::EtaScaleA0HCWD)
@unpack_nt cEco ⇐ land.pools
helpers = helpers.model_helpers
cEco_prev = copy(cEco)
ηH = one(eltype(cEco))
c_remain = one(eltype(cEco))
if :ηH ∈ propertynames(land.diagnostics)
ηH = land.diagnostics.ηH
c_remain = land.states.c_remain
end
for cLitZix ∈ helpers.pools.zix.cLitSlow
cLitNew = cEco[cLitZix] * ηH
@rep_elem cLitNew ⇒ (cEco, cLitZix, :cEco)
end
for cVegZix ∈ helpers.pools.zix.cVeg
cLoss = at_least_zero(cEco[cVegZix] - c_remain)
cVegNew = cEco[cVegZix] - cLoss
@rep_elem cVegNew ⇒ (cEco, cVegZix, :cEco)
end
@pack_nt cEco ⇒ land.pools
land = SindbadTEM.adjustPackPoolComponents(land, helpers, land.models.c_model)
@pack_nt cEco_prev ⇒ land.states
return land
end
function spinupSequence(spinup_models, sel_forcing, loc_forcing_t, land, tem_info, n_timesteps, log_index, n_repeat, spinup_mode)
land = spinupSequenceLoop(spinup_models, sel_forcing, loc_forcing_t, land, tem_info, n_timesteps, log_index, n_repeat, spinup_mode)
# end
return land
end
function spinupSequenceLoop(spinup_models, sel_forcing, loc_forcing_t, land, tem_info, n_timesteps, log_loop, n_repeat, spinup_mode)
for loop_index ∈ 1:n_repeat
@debug " Loop: $(loop_index)/$(n_repeat)"
land = spinup(spinup_models,
sel_forcing,
loc_forcing_t,
land,
tem_info,
n_timesteps,
spinup_mode)
land = setSpinupLog(land, log_loop, tem_info.run.store_spinup)
log_loop += 1
end
return land
end
function spinupTEM end
function spinupTEM(selected_models, spinup_forcings, loc_forcing_t, land, tem_info, ::DoSpinupTEM)
land = setSpinupLog(land, 1, tem_info.run.store_spinup)
log_index = 2
for spin_seq ∈ tem_info.spinup_sequence
forc_name = spin_seq.forcing
n_timesteps = spin_seq.n_timesteps
n_repeat = spin_seq.n_repeat
spinup_mode = spin_seq.spinup_mode
@debug "Spinup: \n spinup_mode: $(nameof(typeof(spinup_mode))), forcing: $(forc_name)"
sel_forcing = sequenceForcing(spinup_forcings, forc_name)
land = spinupSequence(selected_models, sel_forcing, loc_forcing_t, land, tem_info, n_timesteps, log_index, n_repeat, spinup_mode)
log_index += n_repeat
end
return land
end
function spinupTEM(selected_models, spinup_forcings, loc_forcing_t, land, tem_info, ::DoSpinupTEM)
land = setSpinupLog(land, 1, tem_info.run.store_spinup)
log_index = 2
for spin_seq ∈ tem_info.spinup_sequence
forc_name = spin_seq.forcing
n_timesteps = spin_seq.n_timesteps
n_repeat = spin_seq.n_repeat
spinup_mode = spin_seq.spinup_mode
@debug "Spinup: \n spinup_mode: $(nameof(typeof(spinup_mode))), forcing: $(forc_name)"
sel_forcing = sequenceForcing(spinup_forcings, forc_name)
land = spinupSequence(selected_models, sel_forcing, loc_forcing_t, land, tem_info, n_timesteps, log_index, n_repeat, spinup_mode)
log_index += n_repeat
end
return land
end
function spinupTEM(selected_models, spinup_forcings, loc_forcing_t, land, tem_info, ::DoNotSpinupTEM)
return land
endspinupTEM
Sindbad.Simulation.spinupTEM Function
spinupTEM(selected_models, forcing, loc_forcing_t, land, tem_info, spinup_mode)The main spinup function that handles the spinup method based on inputs from spinup.json. Either the spinup is loaded or/and run using spinup functions for different spinup methods.
Arguments:
selected_models: a tuple of all models selected in the given model structureforcing: a forcing NT that contains the forcing time series set for ALL locationsloc_forcing_t: a forcing NT for a single location and a single time stepland: SINDBAD NT input to the spinup of TEM during which subfield(s) of pools are overwrittentem_info: helper NT with necessary objects for model run and type consistenciestem_spinup: a NT with information/instruction on spinning up the TEMspinup_mode: A type dispatch that determines whether spinup is included or excluded:::DoSpinupTEM: Runs the spinup process before the main simulation. Setspinup_TEMtotruein the flag section of experiment_json.::DoNotSpinupTEM: Skips the spinup process and directly runs the main simulation. Setspinup_TEMtofalsein the flag section of experiment_json.
Examples
julia> using Sindbad
julia> # Run spinup with DoSpinupTEM
julia> # land_spinup = spinupTEM(selected_models, forcing, loc_forcing_t, land, tem_info, DoSpinupTEM())
julia> # Skip spinup with DoNotSpinupTEM
julia> # land = spinupTEM(selected_models, forcing, loc_forcing_t, land, tem_info, DoNotSpinupTEM())Notes:
When
DoSpinupTEMis used:- The function runs the spinup sequences
When
DoNotSpinupTEMis used:- The function skips the spinup process returns the land as is`
Code
function spinupTEM end
function spinupTEM(selected_models, spinup_forcings, loc_forcing_t, land, tem_info, ::DoSpinupTEM)
land = setSpinupLog(land, 1, tem_info.run.store_spinup)
log_index = 2
for spin_seq ∈ tem_info.spinup_sequence
forc_name = spin_seq.forcing
n_timesteps = spin_seq.n_timesteps
n_repeat = spin_seq.n_repeat
spinup_mode = spin_seq.spinup_mode
@debug "Spinup: \n spinup_mode: $(nameof(typeof(spinup_mode))), forcing: $(forc_name)"
sel_forcing = sequenceForcing(spinup_forcings, forc_name)
land = spinupSequence(selected_models, sel_forcing, loc_forcing_t, land, tem_info, n_timesteps, log_index, n_repeat, spinup_mode)
log_index += n_repeat
end
return land
end
function spinupTEM(selected_models, spinup_forcings, loc_forcing_t, land, tem_info, ::DoSpinupTEM)
land = setSpinupLog(land, 1, tem_info.run.store_spinup)
log_index = 2
for spin_seq ∈ tem_info.spinup_sequence
forc_name = spin_seq.forcing
n_timesteps = spin_seq.n_timesteps
n_repeat = spin_seq.n_repeat
spinup_mode = spin_seq.spinup_mode
@debug "Spinup: \n spinup_mode: $(nameof(typeof(spinup_mode))), forcing: $(forc_name)"
sel_forcing = sequenceForcing(spinup_forcings, forc_name)
land = spinupSequence(selected_models, sel_forcing, loc_forcing_t, land, tem_info, n_timesteps, log_index, n_repeat, spinup_mode)
log_index += n_repeat
end
return land
end
function spinupTEM(selected_models, spinup_forcings, loc_forcing_t, land, tem_info, ::DoNotSpinupTEM)
return land
endtimeLoopTEMSpinup
Sindbad.Simulation.timeLoopTEMSpinup Function
timeLoopTEMSpinup(spinup_models, spinup_forcing, loc_forcing_t, land, tem_info, n_timesteps)do/run the time loop of the spinup models to update the pool. Note that, in this function, the time series is not stored and the land/land is overwritten with every iteration. Only the state at the end is returned
Arguments:
spinup_models: a tuple of a subset of all models in the given model structure that is selected for spinupspinup_forcing: a selected/sliced/computed forcing time series for running the spinup sequence for a locationloc_forcing_t: a forcing NT for a single location and a single time stepland: SINDBAD NT input to the spinup of TEM during which subfield(s) of pools are overwrittentem_info: helper NT with necessary objects for model run and type consistenciesn_timesteps: number of time steps
Code
function timeLoopTEMSpinup(spinup_models, spinup_forcing, loc_forcing_t, land, tem_info, n_timesteps)
for ts ∈ 1:n_timesteps
f_ts = getForcingForTimeStep(spinup_forcing, loc_forcing_t, ts, tem_info.vals.forcing_types)
land = computeTEM(spinup_models, f_ts, land, tem_info.model_helpers)
end
return land
end