API

Running Simulations

SimpleSim.simulateMethod
simulate(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) -> u defining the input to a continuous-time model at time t. Defaults to (t) -> nothing.
  • ud: Expects a function (t) -> u defining the input to a discrete-time model at time t. Defaults to (t) -> nothing.
  • Δt_max: Maximum step size used for continuous-time model integration. Defaults to ΔT_DEFAULT set in SimpleSim.jl.
  • t0: Initial time. Defaults to 0 // 1.
  • xc0: Initial state for continuous-time model. Overwrites any initial state defined in the model itself. Defaults to nothing.
  • xd0: Initial state for discrete-time model. Overwrites any initial state defined in the model itself. Defaults to nothing.
  • integrator: Integration method to be used for continuous-time models. See below for supported integrators. Defaults to RK4.
  • 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 = 4

Options

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 to 1 // 1_000_000.
  • zero_crossing_tol: absolute tolerance used when computing the time of a zero-crossing. Defaults to 1e-5.
  • RKF45_rel_tol: relative tolerance between the truncation error and the 5th order Runge-Kutta estimate leading to termination of the RKF45 integrator. Defaults to 1e-6.
  • RKF45_abs_tol: absolute tolerance for the truncation error leading to termination of the RKF45 integrator. Defaults to 1e-7.
  • silent: if set to true all output, including warnings and erros is disabled. To only print erros and warnings and disable all other output set display_progress and debug to false. Defaults to false.
  • debug: set to true to get additional information printed in the terminal that might help you debug your models. Defaults to false.
  • display_progress: set to false if you don't want to be updated about simulation progress in the terminal. Defaults to true.
  • progress_spacing: time between progress updates in the terminal. Defaults to 1 // 1.
  • base_rng: random number generator used for random draw functions. Defaults to MersenneTwister.
  • out_stream: IO stream used for console output. Defaults to stdout.

Example with Options

out = simulate(my_model,
    T = 20 // 1,
    options = (
        silent = true,
        base_rng = Xoshiro,
    )
)
source

Updating Submodels

SimpleSim.@call!Macro
@call! model u

The @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
    # ...
end

Note: 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.

source
SimpleSim.@call_ct!Macro
@call_ct! model u

This macro should be used instead of @call! for calling the continuous-time dynamics of a hybrid model. This prevents ambiguity. See @call!.

source
SimpleSim.@call_dt!Macro
@call_dt! model u

This macro should be used instead of @call! for calling the discrete-time dynamics of a hybrid model. This prevents ambiguity. See @call!.

source

Access to Submodel Output

SimpleSim.@outMacro
@out model

Returns 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]
    # ...
end

Note: @out does not update the model. It only returns its current output. Use @call! to update submodels.

source
SimpleSim.@out_ctMacro
@out_ct model

Returns 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.

source
SimpleSim.@out_dtMacro
@out_dt model

Returns 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.

source

Access to Submodel State

SimpleSim.@stateMacro
@state model

Returns 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]
    # ...
end
source
SimpleSim.@state_ctMacro
@state_ct model

Returns 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.

source
SimpleSim.@state_dtMacro
@state_dt model

Returns 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.

source

Convenience Functions

SimpleSim.print_model_treeFunction
print_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 / NamedTuple

First, 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)
source