@@ -22,12 +22,15 @@ multi-threaded way (`executor=ThreadedEx()`, the default), or in a distributed w
2222- `outputs`: the outputs to get in dynamic for each node type of the MTG.
2323- `multirate`: experimental feature flag enabling temporal cache-based input resolution for multiscale simulations.
2424Current implementation supports `HoldLast` resolution only.
25+ - `return_requested_outputs`: when `true` in MTG multi-rate runs, return requested resampled outputs directly
26+ as second return value.
27+ - `requested_outputs_sink`: sink used to materialize requested outputs when `return_requested_outputs=true`.
2528
2629# Returns
2730
28- Modifies the status of the object in-place. Users may retrieve the results from the object using
29- the [`status`](https://virtualplantlab.github.io/PlantSimEngine.jl/stable/API/#PlantSimEngine.status-Tuple{Any})
30- function (see examples) .
31+ Returns status outputs (and optionally requested exports).
32+ For MTG multi-rate runs with `return_requested_outputs=true`, returns
33+ `(status_outputs, requested_outputs)` .
3134
3235# Details
3336
@@ -124,7 +127,9 @@ function run!(
124127 tracked_outputs= nothing ,
125128 check= true ,
126129 executor= ThreadedEx (),
127- multirate= false
130+ multirate= false ,
131+ return_requested_outputs= false ,
132+ requested_outputs_sink= DataFrames. DataFrame
128133)
129134 run! (
130135 DataFormat (object),
@@ -135,7 +140,9 @@ function run!(
135140 tracked_outputs,
136141 check,
137142 executor,
138- multirate
143+ multirate,
144+ return_requested_outputs,
145+ requested_outputs_sink
139146 )
140147end
141148
@@ -153,11 +160,14 @@ function run!(
153160 tracked_outputs= nothing ,
154161 check= true ,
155162 executor= ThreadedEx (),
156- multirate= false
163+ multirate= false ,
164+ return_requested_outputs= false ,
165+ requested_outputs_sink= DataFrames. DataFrame
157166) where {T<: Union{AbstractArray,AbstractDict} ,A}
158167
159168 tracked_outputs isa OutputRequest && error (" `OutputRequest` is only supported for MTG multi-rate simulations." )
160169 tracked_outputs isa AbstractVector{<: OutputRequest } && error (" `OutputRequest` is only supported for MTG multi-rate simulations." )
170+ return_requested_outputs && error (" `return_requested_outputs=true` is only supported for MTG multi-rate simulations." )
161171
162172 if executor != SequentialEx ()
163173 @warn string (
@@ -191,11 +201,14 @@ function run!(
191201 tracked_outputs= nothing ,
192202 check= true ,
193203 executor= ThreadedEx (),
194- multirate= false
204+ multirate= false ,
205+ return_requested_outputs= false ,
206+ requested_outputs_sink= DataFrames. DataFrame
195207) where {T<: ModelList }
196208
197209 tracked_outputs isa OutputRequest && error (" `OutputRequest` is only supported for MTG multi-rate simulations." )
198210 tracked_outputs isa AbstractVector{<: OutputRequest } && error (" `OutputRequest` is only supported for MTG multi-rate simulations." )
211+ return_requested_outputs && error (" `return_requested_outputs=true` is only supported for MTG multi-rate simulations." )
199212
200213 meteo_adjusted = adjust_weather_timesteps_to_given_length (get_status_vector_max_length (object. status), meteo)
201214 nsteps = get_nsteps (meteo_adjusted)
@@ -286,11 +299,14 @@ function run!(
286299 tracked_outputs= nothing ,
287300 check= true ,
288301 executor= ThreadedEx (),
289- multirate= false
302+ multirate= false ,
303+ return_requested_outputs= false ,
304+ requested_outputs_sink= DataFrames. DataFrame
290305) where {T<: Union{AbstractArray,AbstractDict} }
291306
292307 tracked_outputs isa OutputRequest && error (" `OutputRequest` is only supported for MTG multi-rate simulations." )
293308 tracked_outputs isa AbstractVector{<: OutputRequest } && error (" `OutputRequest` is only supported for MTG multi-rate simulations." )
309+ return_requested_outputs && error (" `return_requested_outputs=true` is only supported for MTG multi-rate simulations." )
294310
295311 dep_graphs = [dep (obj) for obj in collect (values (object))]
296312 # obj_parallelizable = all([object_parallelizable(graph) for graph in dep_graphs])
@@ -376,17 +392,12 @@ end
376392function _multirate_tracked_outputs (tracked_outputs)
377393 if isnothing (tracked_outputs)
378394 return nothing , OutputRequest[]
379- elseif tracked_outputs isa Dict
380- return tracked_outputs, OutputRequest[]
381395 elseif tracked_outputs isa OutputRequest
382396 return nothing , OutputRequest[tracked_outputs]
383397 elseif tracked_outputs isa AbstractVector{<: OutputRequest }
384398 return nothing , collect (tracked_outputs)
385399 end
386- error (
387- " For MTG multi-rate runs, `tracked_outputs` must be `nothing`, a Dict of status outputs, " ,
388- " an `OutputRequest`, or a vector of `OutputRequest`."
389- )
400+ return tracked_outputs, OutputRequest[]
390401end
391402
392403function run! (
@@ -399,27 +410,36 @@ function run!(
399410 tracked_outputs= nothing ,
400411 check= true ,
401412 executor= ThreadedEx (),
402- multirate= false
413+ multirate= false ,
414+ return_requested_outputs= false ,
415+ requested_outputs_sink= DataFrames. DataFrame
403416)
404417 isnothing (nsteps) && (nsteps = get_nsteps (meteo))
405418 meteo_adjusted = adjust_weather_timesteps_to_given_length (nsteps, meteo)
406419 status_outputs, output_requests = _multirate_tracked_outputs (tracked_outputs)
407420 ! multirate && ! isempty (output_requests) && error (" `OutputRequest` requires `multirate=true`." )
421+ return_requested_outputs && ! multirate && error (" `return_requested_outputs=true` requires `multirate=true`." )
408422
409423 # NOTE : replace_mapping_status_vectors_with_generated_models is assumed to have already run if used
410424 # otherwise there might be vector length conflicts with timesteps
411425 sim = GraphSimulation (object, mapping, nsteps= nsteps, check= check, outputs= status_outputs)
412- run! (
426+ result = run! (
413427 sim,
414428 meteo_adjusted,
415429 constants,
416430 extra;
417431 check= check,
418432 executor= executor,
419433 multirate= multirate,
420- tracked_outputs= output_requests
434+ tracked_outputs= output_requests,
435+ return_requested_outputs= return_requested_outputs,
436+ requested_outputs_sink= requested_outputs_sink
421437 )
422438
439+ if return_requested_outputs
440+ return result
441+ end
442+
423443 return outputs (sim)
424444end
425445
@@ -432,7 +452,9 @@ function run!(
432452 tracked_outputs= nothing ,
433453 check= true ,
434454 executor= ThreadedEx (),
435- multirate= false
455+ multirate= false ,
456+ return_requested_outputs= false ,
457+ requested_outputs_sink= DataFrames. DataFrame
436458)
437459
438460 dep_graph = object. dependency_graph
@@ -443,6 +465,8 @@ function run!(
443465 validate_canonical_publishers (object)
444466 prepare_output_requests! (object, tracked_outputs, timeline)
445467 configure_temporal_buffers! (object, timeline)
468+ elseif return_requested_outputs
469+ error (" `return_requested_outputs=true` requires `multirate=true`." )
446470 end
447471
448472 ! isnothing (extra) && error (" Extra parameters are not allowed for the simulation of an MTG (already used for statuses)." )
@@ -475,6 +499,10 @@ function run!(
475499 resize! (outputs (object)[organ], index - 1 )
476500 end
477501
502+ if return_requested_outputs
503+ return outputs (object), collect_outputs (object; sink= requested_outputs_sink)
504+ end
505+
478506 return outputs (object)
479507end
480508
0 commit comments