Generating Data for an ODEProblem
To train a DigitalEcho
we need to generate the training data. To generate this data, we simulate the system which can be an ODEProblem or a FMU. In this section, we will demonstrate how to generate data using an ODEProblem for training a DigitalEcho
.
We start by setting up our enviornment. We load DataGeneration
and OrdinaryDiffEq
for defining an ODEProblem
.
using DataGeneration
using OrdinaryDiffEq
For this demonstration, we choose a simple Lotka Volterra system. This system is a pair of non-linear differential equations used to describe the dynamics of a biological system. The system has a set of parameters α
, β
, γ
, δ
.
\[\frac{du₁}{dt} = \alpha u₁ - \beta u₁u₂\]
\[\frac{du₂}{dt} = \delta u₁u₂ - \gamma u₂\]
ODEProblem with parameters
We define the dynamics in the above equations in a function lotka_volterra
.
function lotka_volterra(u, p, t)
u₁, u₂ = u
α, β, γ, δ = p
dx = α * u₁ - β * u₁ * u₂
dy = δ * u₁ * u₂ - γ * u₂
[dx, dy]
end
lotka_volterra (generic function with 1 method)
Next we define the initial condition for the states : u₁
and u₂
, and the timespan : tspan
.
u0 = [1.0, 1.0]
tspan = (0, 12.5)
(0, 12.5)
We define the ODEProblem
as:
lv_ode_problem = ODEProblem{false}(lotka_volterra, u0, tspan)
ODEProblem with uType Vector{Float64} and tType Float64. In-place: false
timespan: (0.0, 12.5)
u0: 2-element Vector{Float64}:
1.0
1.0
For more detailed examples on defining ODEProblem
see: OrdinaryDiffEq.jl. Note one needs to define it with the {false} flag. For generating data, we need to define a ParameterSpace
for sampling parameters: α
, β
, γ
, δ
. We start by defining the lower bound and upper bound.
param_lb = [1.5, 1.75, 1.5, 1.75]
param_lb = [2.0, 2.25, 2.25, 2.0]
n_samples = 10
10
And then we define the ParameterSpace
:
param_space = ParameterSpace(param_lb, param_lb, n_samples; labels = ["α", "β", "γ", "δ"]);
We define the SimulatorConfig
with this parameter space:
simconfig = SimulatorConfig(param_space);
And finally to generate the data, we call this SimulatorConfig
on our problem. This returns an ExperimentData
object that is consumed by DigitalEcho
for training.
ed = simconfig(lv_ode_problem);
[ Info: #Processes = 1
[ Info: Simulating samples from worker processes
Additionally we can provide keyword arguments such as alg
to the SimulatorConfig
object call.
ed = simconfig(lv_ode_problem; alg = Tsit5())
Number of Trajectories in ExperimentData: 10
Basic Statistics for Given Dynamical System's Specifications
Number of u0s in the ExperimentData: 2
Number of ps in the ExperimentData: 4
╭─────────┬────────────────────────────────────────────────────────────────────╮
│ Field │ │
├─────────┼────────────────────────────────────────────────────────────────────┤
│ │ ╭────────────┬──────────────┬──────────────┬────────┬──────────╮ │
│ │ │ Labels │ LowerBound │ UpperBound │ Mean │ StdDev │ │
│ │ ├────────────┼──────────────┼──────────────┼────────┼──────────┤ │
│ │ │ states_1 │ 1.0 │ 1.0 │ 1.0 │ 0.0 │ │
│ u0s │ ├────────────┼──────────────┼──────────────┼────────┼──────────┤ │
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ │
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ │
│ │ ├────────────┼──────────────┼──────────────┼────────┼──────────┤ │
│ │ │ states_2 │ 1.0 │ 1.0 │ 1.0 │ 0.0 │ │
│ │ ╰────────────┴──────────────┴──────────────┴────────┴──────────╯ │
├─────────┼────────────────────────────────────────────────────────────────────┤
│ │ ╭──────────┬──────────────┬──────────────┬────────┬──────────╮ │
│ │ │ Labels │ LowerBound │ UpperBound │ Mean │ StdDev │ │
│ │ ├──────────┼──────────────┼──────────────┼────────┼──────────┤ │
│ │ │ α │ 2.0 │ 2.0 │ 2.0 │ 0.0 │ │
│ ps │ ├──────────┼──────────────┼──────────────┼────────┼──────────┤ │
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ │
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ │
│ │ ├──────────┼──────────────┼──────────────┼────────┼──────────┤ │
│ │ │ δ │ 2.0 │ 2.0 │ 2.0 │ 0.0 │ │
│ │ ╰──────────┴──────────────┴──────────────┴────────┴──────────╯ │
╰─────────┴────────────────────────────────────────────────────────────────────╯
Basic Statistics for Given Dynamical System's Continuous Fields
Number of states in the ExperimentData: 2
╭──────────┬─────────────────────────────────────────────────────────────────...
──╮...
│ Field │...
│...
├──────────┼─────────────────────────────────────────────────────────────────...
──┤...
│ │ ╭────────────┬──────────────┬──────────────┬─────────┬─────────...
│ │ │ Labels │ LowerBound │ UpperBound │ Mean │ StdDev...
│ │ ├────────────┼──────────────┼──────────────┼─────────┼─────────...
│ │ │ states_1 │ 0.951 │ 1.3 │ 1.096 │ 0.129...
│ states │ ├────────────┼──────────────┼──────────────┼─────────┼─────────...
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │...
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │...
│ │ ├────────────┼──────────────┼──────────────┼─────────┼─────────...
│ │ │ states_2 │ 0.746 │ 1.048 │ 0.889 │ 0.104...
│ │ ╰────────────┴──────────────┴──────────────┴─────────┴─────────...
╰──────────┴─────────────────────────────────────────────────────────────────...
──╯...
ODEProblem with parameters and inputs
The above system of equations can be modified to use control inputs as:
\[\frac{du₁}{dt} = \alpha u₁ - \beta u₁u₂ + x₁ \]
\[\frac{du₂}{dt} = \delta u₁u₂ - \gamma u₂ - x₂\]
And thus our new function would be:
function lotka_volterra_ctrl(u, x, p, t)
u₁, u₂ = u
α, β, γ, δ = p
x₁, x₂ = x
dx = α * u₁ - β * u₁ * u₂ + x₁
dy = δ * u₁ * u₂ - γ * u₂ - x₂
[dx, dy]
end
lotka_volterra_ctrl (generic function with 1 method)
Now we can define a new ODEProblem
for this controlled lotka-volterra system as:
controlled_lv_ode_problem = ODEProblem{false}(lotka_volterra_ctrl, u0, tspan)
ODEProblem with uType Vector{Float64} and tType Float64. In-place: false
timespan: (0.0, 12.5)
u0: 2-element Vector{Float64}:
1.0
1.0
Since we have introduced control inputs in this system, lets define a CtrlSpace
to sample control functions.
nsamples_ctrl = 10
ctrl_lb = [0.0, 0.0]
ctrl_ub = [0.1, 0.1]
ctrl_func(u, p, t) = [p[1] * sin(t), p[2] * sin(t)]
ctrl_space = CtrlSpace(ctrl_lb, ctrl_ub, ctrl_func, nsamples_ctrl; labels = ["x₁", "x₂"]);
We have previously defined a ParameterSpace
, which we will reuse for data generation in this case. So we can define a SimulatorConfig
with ParameterSpace
as well as CtrlSpace
.
simconfig = SimulatorConfig(param_space, ctrl_space)
Simulator Config with : CtrlSpace ParameterSpace
Statistics for all Spaces
2 dimensional CtrlSpace with 10 samples
╭──────────────┬──────────────────────────────────────────────┬──────────────...
─────╮...
│ Space Type │ Statistics │ Number...
Samples │...
├──────────────┼──────────────────────────────────────────────┼──────────────...
─────┤...
│ │ ╭──────────┬──────────────┬──────────────╮ │...
│ │ │ Labels │ LowerBound │ UpperBound │ │...
│ │ ├──────────┼──────────────┼──────────────┤ │...
│ │ │ x₁ │ 0.0 │ 0.1 │ │...
│ CtrlSpace │ ├──────────┼──────────────┼──────────────┤ │...
│ │ │ ⋮ │ ⋮ │ ⋮ │ │...
│ │ │ ⋮ │ ⋮ │ ⋮ │ │...
│ │ ├──────────┼──────────────┼──────────────┤ │...
│ │ │ x₂ │ 0.0 │ 0.1 │ │...
│ │ ╰──────────┴──────────────┴──────────────╯ │...
╰──────────────┴──────────────────────────────────────────────┴──────────────...
─────╯...
4 dimensional ParameterSpace with 10 samples
╭──────────────────┬──────────────────────────────────────────────┬──────────...
─────────╮...
│ Space Type │ Statistics │ Number...
of Samples │...
├──────────────────┼──────────────────────────────────────────────┼──────────...
─────────┤...
│ │ ╭──────────┬──────────────┬──────────────╮ │...
│ │ │ Labels │ LowerBound │ UpperBound │ │...
│ │ ├──────────┼──────────────┼──────────────┤ │...
│ │ │ α │ 2.0 │ 2.0 │ │...
│ ParameterSpace │ ├──────────┼──────────────┼──────────────┤ │...
│ │ │ ⋮ │ ⋮ │ ⋮ │ │...
│ │ │ ⋮ │ ⋮ │ ⋮ │ │...
│ │ ├──────────┼──────────────┼──────────────┤ │...
│ │ │ δ │ 2.0 │ 2.0 │ │...
│ │ ╰──────────┴──────────────┴──────────────╯ │...
╰──────────────────┴──────────────────────────────────────────────┴──────────...
─────────╯...
Similar to the previous example, we can generate the ExperimentData
by calling the SimulatorConfig
on our controlled_lv_ode_problem
.
ed_ctrl = simconfig(controlled_lv_ode_problem)
Number of Trajectories in ExperimentData: 100
Basic Statistics for Given Dynamical System's Specifications
Number of u0s in the ExperimentData: 2
Number of ps in the ExperimentData: 4
╭─────────┬────────────────────────────────────────────────────────────────────╮
│ Field │ │
├─────────┼────────────────────────────────────────────────────────────────────┤
│ │ ╭────────────┬──────────────┬──────────────┬────────┬──────────╮ │
│ │ │ Labels │ LowerBound │ UpperBound │ Mean │ StdDev │ │
│ │ ├────────────┼──────────────┼──────────────┼────────┼──────────┤ │
│ │ │ states_1 │ 1.0 │ 1.0 │ 1.0 │ 0.0 │ │
│ u0s │ ├────────────┼──────────────┼──────────────┼────────┼──────────┤ │
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ │
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ │
│ │ ├────────────┼──────────────┼──────────────┼────────┼──────────┤ │
│ │ │ states_2 │ 1.0 │ 1.0 │ 1.0 │ 0.0 │ │
│ │ ╰────────────┴──────────────┴──────────────┴────────┴──────────╯ │
├─────────┼────────────────────────────────────────────────────────────────────┤
│ │ ╭──────────┬──────────────┬──────────────┬────────┬──────────╮ │
│ │ │ Labels │ LowerBound │ UpperBound │ Mean │ StdDev │ │
│ │ ├──────────┼──────────────┼──────────────┼────────┼──────────┤ │
│ │ │ α │ 2.0 │ 2.0 │ 2.0 │ 0.0 │ │
│ ps │ ├──────────┼──────────────┼──────────────┼────────┼──────────┤ │
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ │
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ │
│ │ ├──────────┼──────────────┼──────────────┼────────┼──────────┤ │
│ │ │ δ │ 2.0 │ 2.0 │ 2.0 │ 0.0 │ │
│ │ ╰──────────┴──────────────┴──────────────┴────────┴──────────╯ │
╰─────────┴────────────────────────────────────────────────────────────────────╯
Basic Statistics for Given Dynamical System's Continuous Fields
Number of states in the ExperimentData: 2
Number of controls in the ExperimentData: 2
╭────────────┬───────────────────────────────────────────────────────────────...
────╮...
│ Field │...
│...
├────────────┼───────────────────────────────────────────────────────────────...
────┤...
│ │ ╭────────────┬──────────────┬──────────────┬─────────┬───────...
│ │ │ Labels │ LowerBound │ UpperBound │ Mean │...
│ │ ├────────────┼──────────────┼──────────────┼─────────┼───────...
│ │ │ states_1 │ 0.887 │ 1.43 │ 1.096 │...
│ states │ ├────────────┼──────────────┼──────────────┼─────────┼───────...
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │...
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │...
│ │ ├────────────┼──────────────┼──────────────┼─────────┼───────...
│ │ │ states_2 │ 0.705 │ 1.129 │ 0.889 │...
│ │ ╰────────────┴──────────────┴──────────────┴─────────┴───────...
├────────────┼───────────────────────────────────────────────────────────────...
────┤...
│ │ ╭──────────┬──────────────┬──────────────┬─────────┬────────...
│ │ │ Labels │ LowerBound │ UpperBound │ Mean │ StdDev...
│ │ ├──────────┼──────────────┼──────────────┼─────────┼────────...
│ │ │ x₁ │ -0.093 │ 0.094 │ 0.003 │ 0.036...
│ controls │ ├──────────┼──────────────┼──────────────┼─────────┼────────...
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │...
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │...
│ │ ├──────────┼──────────────┼──────────────┼─────────┼────────...
│ │ │ x₂ │ -0.095 │ 0.097 │ 0.004 │ 0.041...
│ │ ╰──────────┴──────────────┴──────────────┴─────────┴────────...
╰────────────┴───────────────────────────────────────────────────────────────...
────╯...
Parallelization
The Data Generation supports distributed computing via multiple processes. To enable multi-processing using processes, we need to load Distributed
.
using Distributed
We add processes using addprocs
. For more detailed understanding about distributed computing see: Distributed.jl.
addprocs(2, exeflags = ["--project=."])
We need to load DataGeneration
module of JuliaSimSurrogates
on all the processes.
@everywhere using DataGeneration
We need to use @everywhere
to define functions on these added processes.
@everywhere function lotka_volterra_ctrl(u, x, p, t)
u₁, u₂ = u
α, β, γ, δ = p
x₁, x₂ = x
dx = α * u₁ - β * u₁ * u₂ + x₁
dy = δ * u₁ * u₂ - γ * u₂ - x₂
[dx, dy]
end
@everywhere ctrl_func(u, p, t) = [p[1] * sin(t), p[2] * sin(t)]
Once we have defined the necessary functions on these processes, we can take advantage of multi-processing for data generation.
ed_ctrl = simconfig(controlled_lv_ode_problem)
Number of Trajectories in ExperimentData: 100
Basic Statistics for Given Dynamical System's Specifications
Number of u0s in the ExperimentData: 2
Number of ps in the ExperimentData: 4
╭─────────┬────────────────────────────────────────────────────────────────────╮
│ Field │ │
├─────────┼────────────────────────────────────────────────────────────────────┤
│ │ ╭────────────┬──────────────┬──────────────┬────────┬──────────╮ │
│ │ │ Labels │ LowerBound │ UpperBound │ Mean │ StdDev │ │
│ │ ├────────────┼──────────────┼──────────────┼────────┼──────────┤ │
│ │ │ states_1 │ 1.0 │ 1.0 │ 1.0 │ 0.0 │ │
│ u0s │ ├────────────┼──────────────┼──────────────┼────────┼──────────┤ │
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ │
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ │
│ │ ├────────────┼──────────────┼──────────────┼────────┼──────────┤ │
│ │ │ states_2 │ 1.0 │ 1.0 │ 1.0 │ 0.0 │ │
│ │ ╰────────────┴──────────────┴──────────────┴────────┴──────────╯ │
├─────────┼────────────────────────────────────────────────────────────────────┤
│ │ ╭──────────┬──────────────┬──────────────┬────────┬──────────╮ │
│ │ │ Labels │ LowerBound │ UpperBound │ Mean │ StdDev │ │
│ │ ├──────────┼──────────────┼──────────────┼────────┼──────────┤ │
│ │ │ α │ 2.0 │ 2.0 │ 2.0 │ 0.0 │ │
│ ps │ ├──────────┼──────────────┼──────────────┼────────┼──────────┤ │
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ │
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ │
│ │ ├──────────┼──────────────┼──────────────┼────────┼──────────┤ │
│ │ │ δ │ 2.0 │ 2.0 │ 2.0 │ 0.0 │ │
│ │ ╰──────────┴──────────────┴──────────────┴────────┴──────────╯ │
╰─────────┴────────────────────────────────────────────────────────────────────╯
Basic Statistics for Given Dynamical System's Continuous Fields
Number of states in the ExperimentData: 2
Number of controls in the ExperimentData: 2
╭────────────┬───────────────────────────────────────────────────────────────...
────╮...
│ Field │...
│...
├────────────┼───────────────────────────────────────────────────────────────...
────┤...
│ │ ╭────────────┬──────────────┬──────────────┬─────────┬───────...
│ │ │ Labels │ LowerBound │ UpperBound │ Mean │...
│ │ ├────────────┼──────────────┼──────────────┼─────────┼───────...
│ │ │ states_1 │ 0.887 │ 1.43 │ 1.096 │...
│ states │ ├────────────┼──────────────┼──────────────┼─────────┼───────...
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │...
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │...
│ │ ├────────────┼──────────────┼──────────────┼─────────┼───────...
│ │ │ states_2 │ 0.705 │ 1.129 │ 0.889 │...
│ │ ╰────────────┴──────────────┴──────────────┴─────────┴───────...
├────────────┼───────────────────────────────────────────────────────────────...
────┤...
│ │ ╭──────────┬──────────────┬──────────────┬─────────┬────────...
│ │ │ Labels │ LowerBound │ UpperBound │ Mean │ StdDev...
│ │ ├──────────┼──────────────┼──────────────┼─────────┼────────...
│ │ │ x₁ │ -0.093 │ 0.094 │ 0.003 │ 0.036...
│ controls │ ├──────────┼──────────────┼──────────────┼─────────┼────────...
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │...
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │...
│ │ ├──────────┼──────────────┼──────────────┼─────────┼────────...
│ │ │ x₂ │ -0.095 │ 0.097 │ 0.004 │ 0.041...
│ │ ╰──────────┴──────────────┴──────────────┴─────────┴────────...
╰────────────┴───────────────────────────────────────────────────────────────...
────╯...