@@ -110,6 +110,92 @@ function initialise_all_as_hard_dependency_node(models, scale)
110110 return dep_graph
111111end
112112
113+ # Samuel : this requires the orchestrator, which requires the dependency graph
114+ # Leaving it in dependency_graph.jl causes forward declaration issues, moving it here as a quick protoyping hack, it might not be the ideal spot
115+ """
116+ variables_multiscale(node, organ, mapping, st=NamedTuple())
117+
118+ Get the variables of a HardDependencyNode, taking into account the multiscale mapping, *i.e.*
119+ defining variables as `MappedVar` if they are mapped to another scale. The default values are
120+ taken from the model if not given by the user (`st`), and are marked as `UninitializedVar` if
121+ they are inputs of the node.
122+
123+ Return a NamedTuple with the variables and their default values.
124+
125+ # Arguments
126+
127+ - `node::HardDependencyNode`: the node to get the variables from.
128+ - `organ::String`: the organ type, *e.g.* "Leaf".
129+ - `vars_mapping::Dict{String,T}`: the mapping of the models (see details below).
130+ - `st::NamedTuple`: an optional named tuple with default values for the variables.
131+
132+ # Details
133+
134+ The `vars_mapping` is a dictionary with the organ type as key and a dictionary as value. It is
135+ computed from the user mapping like so:
136+ """
137+ function variables_multiscale (node, organ, vars_mapping, st= NamedTuple (), orchestrator:: Orchestrator2 = Orchestrator2 ())
138+ node_vars = variables (node) # e.g. (inputs = (:var1=-Inf, :var2=-Inf), outputs = (:var3=-Inf,))
139+ ins = node_vars. inputs
140+ ins_variables = keys (ins)
141+ outs_variables = keys (node_vars. outputs)
142+ defaults = merge (node_vars... )
143+ map ((inputs= ins_variables, outputs= outs_variables)) do vars # Map over vars from :inputs and vars from :outputs
144+ vars_ = Vector {Pair{Symbol,Any}} ()
145+ for var in vars # e.g. var = :carbon_biomass
146+ if var in keys (st)
147+ # If the user has given a status, we use it as default value.
148+ default = st[var]
149+ elseif var in ins_variables
150+ # Otherwise, we use the default value given by the model:
151+ # If the variable is an input, we mark it as uninitialized:
152+ default = UninitializedVar (var, defaults[var])
153+ else
154+ # If the variable is an output, we use the default value given by the model:
155+ default = defaults[var]
156+ end
157+
158+ # TODO no idea how this meshes with refvector situations or previoustimestep
159+ if is_timestep_mapped (organ => var, orchestrator, search_inputs_only= true )
160+
161+ push! (vars_, var => default)
162+ else
163+
164+ if haskey (vars_mapping[organ], var)
165+ organ_mapped, organ_mapped_var = _node_mapping (vars_mapping[organ][var])
166+ push! (vars_, var => MappedVar (organ_mapped, var, organ_mapped_var, default))
167+ # * We still check if the variable also exists wrapped in PreviousTimeStep, because one model could use the current
168+ # * values, and another one the previous values.
169+ if haskey (vars_mapping[organ], PreviousTimeStep (var, node. process))
170+ organ_mapped, organ_mapped_var = _node_mapping (vars_mapping[organ][PreviousTimeStep (var, node. process)])
171+ push! (vars_, var => MappedVar (organ_mapped, PreviousTimeStep (var, node. process), organ_mapped_var, default))
172+ end
173+ elseif haskey (vars_mapping[organ], PreviousTimeStep (var, node. process))
174+ # If not found in the current time step, we check if the variable is mapped to the previous time step:
175+ organ_mapped, organ_mapped_var = _node_mapping (vars_mapping[organ][PreviousTimeStep (var, node. process)])
176+ push! (vars_, var => MappedVar (organ_mapped, PreviousTimeStep (var, node. process), organ_mapped_var, default))
177+ else
178+ # Else we take the default value:
179+ push! (vars_, var => default)
180+ end
181+ end
182+ end
183+ return (; vars_... ,)
184+ end
185+ end
186+
187+ function _node_mapping (var_mapping:: Pair{String,Symbol} )
188+ # One organ is mapped to the variable:
189+ return SingleNodeMapping (first (var_mapping)), last (var_mapping)
190+ end
191+
192+ function _node_mapping (var_mapping)
193+ # Several organs are mapped to the variable:
194+ organ_mapped = MultiNodeMapping ([first (i) for i in var_mapping])
195+ organ_mapped_var = [last (i) for i in var_mapping]
196+
197+ return organ_mapped, organ_mapped_var
198+ end
113199
114200# When we use a mapping (multiscale), we return the set of soft-dependencies (we put the hard-dependencies as their children):
115201function hard_dependencies (mapping:: Dict{String,T} ; verbose:: Bool = true , orchestrator:: Orchestrator2 = Orchestrator2 ()) where {T}
@@ -148,7 +234,7 @@ function hard_dependencies(mapping::Dict{String,T}; verbose::Bool=true, orchestr
148234 status_scale = Dict {Symbol,Vector{Pair{Symbol,NamedTuple}}} ()
149235 for (procname, node) in hard_deps[organ]. roots # procname = :leaf_surface ; node = hard_deps.roots[procname]
150236 var = Pair{Symbol,NamedTuple}[]
151- traverse_dependency_graph! (node, x -> variables_multiscale (x, organ, full_vars_mapping, st_scale_user), var)
237+ traverse_dependency_graph! (node, x -> variables_multiscale (x, organ, full_vars_mapping, st_scale_user, orchestrator ), var)
152238 push! (status_scale, procname => var)
153239 end
154240
0 commit comments