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 environment. We load DataGeneration and OrdinaryDiffEq for defining an ODEProblem.
using DataGeneration
using OrdinaryDiffEqFor 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]
endlotka_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.0For 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 = 1010And 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 processesAdditionally 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       │      1       │   1    │    0     │  │
│   u0s   │  ├────────────┼──────────────┼──────────────┼────────┼──────────┤  │
│         │  │     ⋮      │      ⋮       │      ⋮       │   ⋮    │    ⋮     │  │
│         │  │     ⋮      │      ⋮       │      ⋮       │   ⋮    │    ⋮     │  │
│         │  ├────────────┼──────────────┼──────────────┼────────┼──────────┤  │
│         │  │  states_2  │      1       │      1       │   1    │    0     │  │
│         │  ╰────────────┴──────────────┴──────────────┴────────┴──────────╯  │
├─────────┼────────────────────────────────────────────────────────────────────┤
│         │   ╭──────────┬──────────────┬──────────────┬────────┬──────────╮   │
│         │   │  Labels  │  LowerBound  │  UpperBound  │  Mean  │  StdDev  │   │
│         │   ├──────────┼──────────────┼──────────────┼────────┼──────────┤   │
│         │   │    α     │      2       │      2       │   2    │    0     │   │
│   ps    │   ├──────────┼──────────────┼──────────────┼────────┼──────────┤   │
│         │   │    ⋮     │      ⋮       │      ⋮       │   ⋮    │    ⋮     │   │
│         │   │    ⋮     │      ⋮       │      ⋮       │   ⋮    │    ⋮     │   │
│         │   ├──────────┼──────────────┼──────────────┼────────┼──────────┤   │
│         │   │    δ     │      2       │      2       │   2    │    0     │   │
│         │   ╰──────────┴──────────────┴──────────────┴────────┴──────────╯   │
╰─────────┴────────────────────────────────────────────────────────────────────╯
 Basic Statistics for Given Dynamical System's Continuous Fields 
  Number of states in the ExperimentData: 2 
 ╭──────────┬─────────────────────────────────────────────────────────────────...
───────╮...
│  Field   │...
            │...
├──────────┼─────────────────────────────────────────────────────────────────...
───────┤...
│          │  ╭────────────┬──────────────┬──────────────┬────────────┬──────...
│          │  │   Labels   │  LowerBound  │  UpperBound  │    Mean    │...
│          │  ├────────────┼──────────────┼──────────────┼────────────┼──────...
│          │  │  states_1  │   0.951337   │   1.30017    │  1.09613   │...
│  states  │  ├────────────┼──────────────┼──────────────┼────────────┼──────...
│          │  │     ⋮      │      ⋮       │      ⋮       │     ⋮      │...
│          │  │     ⋮      │      ⋮       │      ⋮       │     ⋮      │...
│          │  ├────────────┼──────────────┼──────────────┼────────────┼──────...
│          │  │  states_2  │   0.745919   │    1.0482    │  0.889332  │...
│          │  ╰────────────┴──────────────┴──────────────┴────────────┴──────...
╰──────────┴─────────────────────────────────────────────────────────────────...
───────╯...
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]
endlotka_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.0Since 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 
 With controls : x₁, x₂ 
╭──────────────┬──────────────────────────────────────────────┬──────────────...
─────╮...
│  Space Type  │                  Statistics                  │  Number...
Samples  │...
├──────────────┼──────────────────────────────────────────────┼──────────────...
─────┤...
│              │  ╭──────────┬──────────────┬──────────────╮  │...
│              │  │  Labels  │  LowerBound  │  UpperBound  │  │...
│              │  ├──────────┼──────────────┼──────────────┤  │...
│              │  │   x_1    │      0       │     0.1      │  │...
│  CtrlSpace   │  ├──────────┼──────────────┼──────────────┤  │...
│              │  │    ⋮     │      ⋮       │      ⋮       │  │...
│              │  │    ⋮     │      ⋮       │      ⋮       │  │...
│              │  ├──────────┼──────────────┼──────────────┤  │...
│              │  │   x_2    │      0       │     0.1      │  │...
│              │  ╰──────────┴──────────────┴──────────────╯  │...
╰──────────────┴──────────────────────────────────────────────┴──────────────...
─────╯...
 4 dimensional ParameterSpace with 10 samples 
 ╭──────────────────┬──────────────────────────────────────────────┬──────────...
─────────╮...
│    Space Type    │                  Statistics                  │  Number...
of Samples  │...
├──────────────────┼──────────────────────────────────────────────┼──────────...
─────────┤...
│                  │  ╭──────────┬──────────────┬──────────────╮  │...
│                  │  │  Labels  │  LowerBound  │  UpperBound  │  │...
│                  │  ├──────────┼──────────────┼──────────────┤  │...
│                  │  │    α     │      2       │      2       │  │...
│  ParameterSpace  │  ├──────────┼──────────────┼──────────────┤  │...
│                  │  │    ⋮     │      ⋮       │      ⋮       │  │...
│                  │  │    ⋮     │      ⋮       │      ⋮       │  │...
│                  │  ├──────────┼──────────────┼──────────────┤  │...
│                  │  │    δ     │      2       │      2       │  │...
│                  │  ╰──────────┴──────────────┴──────────────╯  │...
╰──────────────────┴──────────────────────────────────────────────┴──────────...
─────────╯...
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       │      1       │   1    │    0     │  │
│   u0s   │  ├────────────┼──────────────┼──────────────┼────────┼──────────┤  │
│         │  │     ⋮      │      ⋮       │      ⋮       │   ⋮    │    ⋮     │  │
│         │  │     ⋮      │      ⋮       │      ⋮       │   ⋮    │    ⋮     │  │
│         │  ├────────────┼──────────────┼──────────────┼────────┼──────────┤  │
│         │  │  states_2  │      1       │      1       │   1    │    0     │  │
│         │  ╰────────────┴──────────────┴──────────────┴────────┴──────────╯  │
├─────────┼────────────────────────────────────────────────────────────────────┤
│         │   ╭──────────┬──────────────┬──────────────┬────────┬──────────╮   │
│         │   │  Labels  │  LowerBound  │  UpperBound  │  Mean  │  StdDev  │   │
│         │   ├──────────┼──────────────┼──────────────┼────────┼──────────┤   │
│         │   │    α     │      2       │      2       │   2    │    0     │   │
│   ps    │   ├──────────┼──────────────┼──────────────┼────────┼──────────┤   │
│         │   │    ⋮     │      ⋮       │      ⋮       │   ⋮    │    ⋮     │   │
│         │   │    ⋮     │      ⋮       │      ⋮       │   ⋮    │    ⋮     │   │
│         │   ├──────────┼──────────────┼──────────────┼────────┼──────────┤   │
│         │   │    δ     │      2       │      2       │   2    │    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.887627   │   1.42643    │   1.0959...
│   states   │  ├────────────┼──────────────┼──────────────┼────────────┼────...
│            │  │     ⋮      │      ⋮       │      ⋮       │     ⋮...
│            │  │     ⋮      │      ⋮       │      ⋮       │     ⋮...
│            │  ├────────────┼──────────────┼──────────────┼────────────┼────...
│            │  │  states_2  │   0.709326   │   1.13012    │  0.889302...
│            │  ╰────────────┴──────────────┴──────────────┴────────────┴────...
├────────────┼───────────────────────────────────────────────────────────────...
──────────┤...
│            │  ╭──────────┬──────────────┬──────────────┬──────────────┬────...
│            │  │  Labels  │  LowerBound  │  UpperBound  │     Mean...
│            │  ├──────────┼──────────────┼──────────────┼──────────────┼────...
│            │  │    x₁    │  -0.0929809  │  0.0949977   │  0.00341274...
│  controls  │  ├──────────┼──────────────┼──────────────┼──────────────┼────...
│            │  │    ⋮     │      ⋮       │      ⋮       │      ⋮...
│            │  │    ⋮     │      ⋮       │      ⋮       │      ⋮...
│            │  ├──────────┼──────────────┼──────────────┼──────────────┼────...
│            │  │    x₂    │  -0.0930931  │  0.0949977   │  0.00331477...
│            │  ╰──────────┴──────────────┴──────────────┴──────────────┴────...
╰────────────┴───────────────────────────────────────────────────────────────...
──────────╯...
Parallelization
The Data Generation supports distributed computing via multiple processes. To enable multi-processing using processes, we need to load Distributed.
using DistributedWe 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 DataGenerationWe 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       │      1       │   1    │    0     │  │
│   u0s   │  ├────────────┼──────────────┼──────────────┼────────┼──────────┤  │
│         │  │     ⋮      │      ⋮       │      ⋮       │   ⋮    │    ⋮     │  │
│         │  │     ⋮      │      ⋮       │      ⋮       │   ⋮    │    ⋮     │  │
│         │  ├────────────┼──────────────┼──────────────┼────────┼──────────┤  │
│         │  │  states_2  │      1       │      1       │   1    │    0     │  │
│         │  ╰────────────┴──────────────┴──────────────┴────────┴──────────╯  │
├─────────┼────────────────────────────────────────────────────────────────────┤
│         │   ╭──────────┬──────────────┬──────────────┬────────┬──────────╮   │
│         │   │  Labels  │  LowerBound  │  UpperBound  │  Mean  │  StdDev  │   │
│         │   ├──────────┼──────────────┼──────────────┼────────┼──────────┤   │
│         │   │    α     │      2       │      2       │   2    │    0     │   │
│   ps    │   ├──────────┼──────────────┼──────────────┼────────┼──────────┤   │
│         │   │    ⋮     │      ⋮       │      ⋮       │   ⋮    │    ⋮     │   │
│         │   │    ⋮     │      ⋮       │      ⋮       │   ⋮    │    ⋮     │   │
│         │   ├──────────┼──────────────┼──────────────┼────────┼──────────┤   │
│         │   │    δ     │      2       │      2       │   2    │    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.887627   │   1.42643    │   1.0959...
│   states   │  ├────────────┼──────────────┼──────────────┼────────────┼────...
│            │  │     ⋮      │      ⋮       │      ⋮       │     ⋮...
│            │  │     ⋮      │      ⋮       │      ⋮       │     ⋮...
│            │  ├────────────┼──────────────┼──────────────┼────────────┼────...
│            │  │  states_2  │   0.709326   │   1.13012    │  0.889302...
│            │  ╰────────────┴──────────────┴──────────────┴────────────┴────...
├────────────┼───────────────────────────────────────────────────────────────...
──────────┤...
│            │  ╭──────────┬──────────────┬──────────────┬──────────────┬────...
│            │  │  Labels  │  LowerBound  │  UpperBound  │     Mean...
│            │  ├──────────┼──────────────┼──────────────┼──────────────┼────...
│            │  │    x₁    │  -0.0929809  │  0.0949977   │  0.00341274...
│  controls  │  ├──────────┼──────────────┼──────────────┼──────────────┼────...
│            │  │    ⋮     │      ⋮       │      ⋮       │      ⋮...
│            │  │    ⋮     │      ⋮       │      ⋮       │      ⋮...
│            │  ├──────────┼──────────────┼──────────────┼──────────────┼────...
│            │  │    x₂    │  -0.0930931  │  0.0949977   │  0.00331477...
│            │  ╰──────────┴──────────────┴──────────────┴──────────────┴────...
╰────────────┴───────────────────────────────────────────────────────────────...
──────────╯...