API
Running Simulations
SimpleSim.simulate — Methodsimulate(model; kwargs...)Runs the simulation for the given model.
Returns a NamedTuple with all time-series information about the simulation.
Mandatory Keyword Arguments
T: Total time of the simulation. Mand
Optional Keyword Arguments
uc: Expects a function(t) -> udefining the input to a continuous-time model at timet. Defaults to(t) -> nothing.ud: Expects a function(t) -> udefining the input to a discrete-time model at timet. Defaults to(t) -> nothing.Δt_max: Maximum step size used for continuous-time model integration. Defaults toΔT_DEFAULTset inSimpleSim.jl.t0: Initial time. Defaults to0 // 1.xc0: Initial state for continuous-time model. Overwrites any initial state defined in the model itself. Defaults tonothing.xd0: Initial state for discrete-time model. Overwrites any initial state defined in the model itself. Defaults tonothing.integrator: Integration method to be used for continuous-time models. See below for supported integrators. Defaults toRK4.options: See below for additional options that can be set.
Supported Numerical Integration Methods
These options can be passed to the simulate function as the integrator keyword argument:
@enum SimpleSimIntegrator RK4 = 1 Euler = 2 Heun = 3 RKF45 = 4Options
SimpleSim.jl has a few default parameters for running simulations that generally do not need to be changed. However, if necessary the following options can be passed in a NamedTuple to the options keyword argument.
Δt_default: replaces the default (maximum) step size used for continuous-time integration. Should be rational. Defaults to global parameterΔT_DEFAULT.Δt_min: replaces the minimum step size used for continuous-time integration. Especially relevant for adaptive step size integrators. Defaults to1 // 1_000_000.zero_crossing_tol: absolute tolerance used when computing the time of a zero-crossing. Defaults to1e-5.RKF45_rel_tol: relative tolerance between the truncation error and the 5th order Runge-Kutta estimate leading to termination of theRKF45integrator. Defaults to1e-6.RKF45_abs_tol: absolute tolerance for the truncation error leading to termination of theRKF45integrator. Defaults to1e-7.silent: if set totrueall output, including warnings and erros is disabled. To only print erros and warnings and disable all other output setdisplay_progressanddebugtofalse. Defaults tofalse.debug: set totrueto get additional information printed in the terminal that might help you debug your models. Defaults tofalse.display_progress: set tofalseif you don't want to be updated about simulation progress in the terminal. Defaults totrue.progress_spacing: time between progress updates in the terminal. Defaults to1 // 1.base_rng: random number generator used for random draw functions. Defaults toMersenneTwister.out_stream: IO stream used for console output. Defaults tostdout.
Example with Options
out = simulate(my_model,
T = 20 // 1,
options = (
silent = true,
base_rng = Xoshiro,
)
)Updating Submodels
SimpleSim.@call! — Macro@call! model uThe @call! macro is crucial for running simulations with submodels. In the parent model's gc or gd function every one of its submodels must be called using @call!. Otherwise the submodels will not be updated.
Returns the output of model after the update. Use @state after calling @call! to access the new state.
Example
function gc_parent_model(x, u, p, t; models)
# ...
y_child = @call! models[1] u_child
# ...
endNote: The @call! must not be used inside a dynamics (fc / fd) function. This will throw an error. If you need access to a submodels output/state inside your parent model's dynamics function use @out / @state.
SimpleSim.@call_ct! — Macro@call_ct! model uThis macro should be used instead of @call! for calling the continuous-time dynamics of a hybrid model. This prevents ambiguity. See @call!.
SimpleSim.@call_dt! — Macro@call_dt! model uThis macro should be used instead of @call! for calling the discrete-time dynamics of a hybrid model. This prevents ambiguity. See @call!.
Access to Submodel Output
SimpleSim.@out — Macro@out modelReturns the current output of model. This macro is useful in fc or fd functions when access to a submodel's output is needed. The macro works similar to @state.
Example
function fc_parent_model(x, u, p, t; models)
y_child = @out models[1]
# ...
endNote: @out does not update the model. It only returns its current output. Use @call! to update submodels.
SimpleSim.@out_ct — Macro@out_ct modelReturns the output of a given continuous-time model. Especially useful when retrieving the output of a hybrid model in which case @out would be ambiguous. See @out.
SimpleSim.@out_dt — Macro@out_dt modelReturns the output of a given discrete-time model. Especially useful when retrieving the output of a hybrid model in which case @out would be ambiguous. See @out.
Access to Submodel State
SimpleSim.@state — Macro@state modelReturns the current state of model. This macro is useful in fc or fd functions when access to a submodel's state is needed. The macro works similar to @out.
Note: @state does not update the model. It only returns its current state. Use @call! to update submodels.
Example
function fc_parent_model(x, u, p, t; models)
x_child = @state models[1]
# ...
endSimpleSim.@state_ct — Macro@state_ct modelReturns the state of a given contiuous-time model. Especially useful when retrieving the state of a hybrid model in which case @state would be ambiguous. See @state.
SimpleSim.@state_dt — Macro@state_dt modelReturns the state of a given discrete-time model. Especially useful when retrieving the state of a hybrid model in which case @state would be ambiguous. See @state.
Convenience Functions
SimpleSim.print_model_tree — Functionprint_model_tree(model; io = stdout)Prints a tree of the given model similar to a folder tree printed by the Linux tree command.
An example for a feedback-controlled inverted pendulum could look like this
julia> print_model_tree(my_model)
└─1 (TypeCT): top-level model / FeedbackSystem
├─2 (TypeCT): .inverted_pendulum / NamedTuple
└─3 (TypeCT): .controller / NamedTupleFirst, the model_id is indicated, following the type (TypeCT, TypeDT or TypeHybrid). Then follows the name of each model in the super model. This is either its field name in the NamedTuple passed as models or the index in the case of vectors or tuples. Finally, after the slash, the type of each model is indicated. This should either be the name of a struct type, or NamedTuple.
You can also pass your own IO stream to print_model_tree as follows
print_model_tree(my_buffer, model)