simulation.py
# -*- coding: utf-8 -*-
"""
Created on Mon Jun 7 19:06:37 2021
@author: Rocky
"""
import numpy as np
import system_model
from scipy.integrate import solve_ivp
from ackrep_core import ResultContainer
from ackrep_core.system_model_management import save_plot_in_dir
import matplotlib.pyplot as plt
import os
def simulate():
order = 5
model_two = system_model.Model(order)
u = model_two.uu_func
"""RHS-Function of the brockett_model
Args:
t (float, positive): time
x (ndarray): state vector
Returns:
dx/dt (ndarray): time derivative of state vector at time t
"""
def chain_integrator_model(t, xx_nv):
dxx_dt_nv = xx_nv * 1
dxx_dt_nv[:-1] = xx_nv[1:]
dxx_dt_nv[-1] = u(t, xx_nv)
return dxx_dt_nv
xx0 = [0, 0, 0, 0, 0]
model = system_model.Model(x_dim=len(xx0))
rhs_xx_pp_symb = model.get_rhs_symbolic()
print("Computational Equations:\n")
for i, eq in enumerate(rhs_xx_pp_symb):
print(f"dot_x{i+1} =", eq)
rhs = model.get_rhs_func()
t_end = 30
tt = times = np.linspace(0, t_end, 1000)
sim = solve_ivp(chain_integrator_model, (0, t_end), xx0, t_eval=tt)
save_plot(sim)
return sim
def save_plot(sim):
plt.plot(sim.t, sim.y[0], label="x1", lw=1)
plt.plot(sim.t, sim.y[1], label="x2", lw=1)
plt.plot(sim.t, sim.y[2], label="x3", lw=1)
plt.plot(sim.t, sim.y[3], label="x4", lw=1)
plt.plot(sim.t, sim.y[4], label="x5", lw=1)
plt.title("State progress")
plt.xlabel("Time [s]")
plt.ylabel("y")
plt.legend()
plt.grid()
plt.tight_layout()
save_plot_in_dir()
def evaluate_simulation(simulation_data):
"""
:param simulation_data: simulation_data of system_model
:return:
"""
expected_final_state = [
32337.334058261687,
3092.752509636077,
144.88833045860406,
-1.4410336827947148,
-0.0673030971647946,
]
rc = ResultContainer(score=1.0)
simulated_final_state = simulation_data.y[:, -1]
rc.final_state_errors = [
simulated_final_state[i] - expected_final_state[i] for i in np.arange(0, len(simulated_final_state))
]
rc.success = np.allclose(expected_final_state, simulated_final_state, rtol=0, atol=1e-2)
return rc
system_model.py
# -*- coding: utf-8 -*-
"""
Created on Wed Jun 9 13:33:34 2021
@author: Jonathan Rockstroh
"""
import sympy as sp
import symbtools as st
import importlib
import sys, os
from ipydex import IPS, activate_ips_on_exception # for debugging only
from ackrep_core.system_model_management import GenericModel, import_parameters
# Import parameter_file
params = None
class Model(GenericModel):
def initialize(self):
"""
this function is called by the constructor of GenericModel
:return: None
"""
# Define number of inputs -- MODEL DEPENDENT
self.u_dim = 1
# only needed for n extendable systems -- MODEL DEPENDENT
self.default_param_sys_dim = 3
# check existance of params file -> if not: System is defined to hasn't
# parameters
self.has_params = True
self.params = params
# ----------- SET DEFAULT INPUT FUNCTION ---------- #
# --------------- Only for non-autonomous Systems
# --------------- MODEL DEPENDENT
def uu_default_func(self):
"""
:param t:(scalar or vector) Time
:param xx_nv: (vector or array of vectors) state vector with
numerical values at time t
:return:(function with 2 args - t, xx_nv) default input function
"""
T = 10
y1 = 0
# create symbolic polnomial function
f1 = sp.sin(2 * sp.pi * self.t_symb / T)
# create symbolic piecewise defined symbolic transition function
transition = st.piece_wise((0, self.t_symb < 0), (f1, self.t_symb < T), (-f1, self.t_symb < 2 * T), (y1, True))
# transform symbolic to numeric function
transition_func = st.expr_to_func(self.t_symb, transition)
# Wrapper function to unify function arguments
def uu_rhs(t, xx_nv):
"""
:param t:(vector) time
:param xx_nv:(vector or array of vectors) numeric state vector
:return:(vector) numeric inputs
"""
res = transition_func(t)
return res
return uu_rhs
# ----------- SYMBOLIC RHS FUNCTION ---------- #
# --------------- MODEL DEPENDENT
def get_rhs_symbolic(self):
"""
:return:(matrix) symbolic rhs-functions
"""
if self.dxx_dt_symb is not None:
return self.dxx_dt_symb
dxx_dt_symb = self.xx_symb * 1
dxx_dt_symb[:-1] = self.xx_symb[1:]
dxx_dt_symb[-1] = self.uu_symb[0]
self.dxx_dt_symb = sp.Matrix(dxx_dt_symb)
return self.dxx_dt_symb
parameters.py
# This model does not need any parameters.