@jrising @hbenveniste @BerBastien @FrankErrickson @AlexandrePavlov This is another PSA for users of the Simulation API. We have been working to simplify the API a bit from a user-perspective, so there are some small changes coming in the next tagged release of Mimi that you will want to be aware of. I will update all models we are responsible for as well. In most uses cases, all you will have to do is (1) remove calls to set_models!
and generate_trials!
(2) rewrite your run_sim!
functions as run
functions and add a few arguments to that call.
The basic API now looks like this:
#samplesize
N = 1000
# get simulation definition
sim_definition = @defsim ...
end
# get whatever model you are using
m = get_model()
# run simulation and save results to the results_output_dir
sim_instance = run(sim_definition, m, 1000; results_output_dir = "./out")
# view in-memory results for a variable
results = sim_instance[:comp_name, :variable_name]
All changes are documented in docs and tutorials. Lots of details can be found in the notes here: https://github.com/mimiframework/Mimi.jl/pull/522.
Main Changes:
-
Types: Mirroring work with models, there are now two types
SimulationDefinition
andSimulationInstance
. The former is what you get from@defsim
, the latter is returned byrun
and holds a (mutated) copy of theSimulationDefinition
it’srun
function had as an argument. -
Run Function: The functions
set_models!
andgenerate_trials!
have been absorbed into therun_sim
function, which has been renamed to simplyrun
with the full signature:
function Base.run(sim_def::SimulationDef{T}, models::Union{Vector{Model}, Model}, samplesize::Int;
ntimesteps::Int=typemax(Int),
trials_output_filename::Union{Nothing, AbstractString}=nothing,
results_output_dir::Union{Nothing, AbstractString}=nothing,
pre_trial_func::Union{Nothing, Function}=nothing,
post_trial_func::Union{Nothing, Function}=nothing,
scenario_func::Union{Nothing, Function}=nothing,
scenario_placement::ScenarioLoopPlacement=OUTER,
scenario_args=nothing,
results_in_memory::Bool=true) where T <: AbstractSimulationData
Thus, in its simplest form, you may define a SimulationDefinition with @defsim
, and then call run(sim_def, model, 100)
to run sim_def
on model
with sample size of 100. You will notice that the output filename for the trial data is thus moved to run
as trials_output_filename
, and if set your trial data will be saved to disk at that location.
run(sim_def ...)
will return a SimulationInstance
which contains a mutated copy of the SimulationDefinition
argument, a vector of models, and a vector of results. These can be accessed with regular dot syntax:
sim_instance = `run(sim_def, model, 1000)
models = sim_instance.models
results = sim_instance.results
The results are organized as a vector, one item per model, and each item is a dictionary with keys for each saved variable and values are DataFrames. It is easiest to access results with getindex
, for example you may get the DataFrame for component comp_name
and variable var_name
with:
results = sim_def[:comp, :var_name] # returns a DataFrame
If there are scenarios, results
will have a field with :scen
holding the scenario name.
-
Results Saving: If you specify a
results_output_dir
, your results will be saved both in that directory in a folder structure as well as in memory in theresults
array. This folder structure is organized asscenario folder => model folder => comp_var.csv files
. Only if you set theresults_in_memory
flag tofalse
will memory be cleared after each trial. We have also fixed a bug that did not properly save results (to disk or memory) when multiple scenarios were involved. -
Callback Functions: Extra functions like
post_trial_func
andpre_trial_func
now have aSimulationInstance
in their signature instead of aSimulation
.
Please do not hesitate to ask any questions here. This will be the next tagged version of Mimi but I wanted to post this now in case you have questions and don’t get taken by surprise!