In [1]:
%load_ext autoreload
%autoreload 2
import sys
import pylab as pl
sys.path.insert(0, '..')
import pymoca.parser
import pymoca.backends.sympy.generator as generator
import pylab as pl
import sympy
import control
sympy.init_printing()
%load_ext autoreload
%autoreload 2
%matplotlib inline
In [2]:
modelica_src = '''
model System
input Real u;
output Real x(start=1), v_x(start=1);
Spring spring;
Damper damper;
equation
spring.x = x;
damper.v = v_x;
der(x) = v_x;
der(v_x) = spring.f + damper.f - u;
end System;
model Spring
Real x "displacement";
Real f "force";
parameter Real k = 2.0 "spring constant";
equation
f = -k*x;
end Spring;
model Damper
Real v "velocity";
Real f "force";
parameter Real c = 0.2 "damping constant";
equation
f = -c*v;
end Damper;
'''
In [30]:
ast = pymoca.parser.parse(modelica_src)
ast.classes['System'].symbols.keys()
Out[30]:
In [32]:
ast
Out[32]:
In [7]:
src_code = generator.generate(ast, 'System')
print(src_code)
In [8]:
exec(src_code)
model = System()
model
Out[8]:
In [9]:
t = sympy.Symbol('t')
model.x.diff(t)
Out[9]:
In [10]:
sol = sympy.solve(model.eqs, list(model.v) + list(model.x.diff(t)))
sol
Out[10]:
In [11]:
model.x.diff(t).subs(sol)
Out[11]:
In [12]:
model.linearize_symbolic()
Out[12]:
In [13]:
ss = control.ss(*model.linearize())
ss
Out[13]:
In [14]:
control.ss2tf(ss)
Out[14]:
In [15]:
control.bode(ss[0,0], omega=pl.logspace(-1,1,100));
In [16]:
control.rlocus(ss[0,0], klist=pl.logspace(-2,1,1000));
pl.grid()
In [17]:
model.f
Out[17]:
In [18]:
import sympy
ss_sub = {}
ss_sub.update({model.x[i]: sympy.DeferredVector('x')[i] for i in range(len(model.x))})
#ss_sub.update({model.y[i]: sympy.DeferredVector('y')[i] for i in range(len(model.y))})
ss_sub
Out[18]:
In [19]:
res = model.simulate(t0=10, tf=20, dt=0.001)
In [20]:
pl.plot(res['t'], res['x'])
pl.grid()
pl.xlabel('t, sec')
pl.ylabel('x')
Out[20]:
In [21]:
sympy.init_printing()
model.f
Out[21]:
In [22]:
model.f.jacobian(model.x)
Out[22]:
Using the energy function as a candidate function, we can show that the system has global exponential stability (GES).
In [23]:
v_x, spring_k, t, V, x = sympy.symbols('v_x, spring.k, t, V, x')
V_eq = (v_x(t)**2 + spring_k*x(t)**2)/2
sympy.Eq(V, V_eq)
Out[23]:
In [24]:
dV_dt_eq = (sympy.Matrix([V_eq]).jacobian(model.x).dot(model.f)).simplify()
sympy.Eq(V(t).diff(t), dV_dt_eq)
Out[24]:
In [25]:
V_lam = sympy.lambdify(model.x, V_eq.subs(model.p0))
V_vals = [V_lam(*x) for x in res['x']]
pl.plot(res['t'], V_vals)
pl.xlabel('t')
pl.ylabel('V')
pl.grid()
In [26]:
model.f.jacobian(model.p)
Out[26]: