Try PyDSTool integrator, cgeneralize simulations in notebook

This commit is contained in:
Michael Soukup 2019-05-12 13:36:44 +02:00
parent 4c5c4ca124
commit 8df782ab92
6 changed files with 404 additions and 17829 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,222 +0,0 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%matplotlib notebook\n",
"\n",
"import numpy as np\n",
"from scipy.integrate import odeint\n",
"import matplotlib.pyplot as plt\n",
"from matplotlib import animation\n",
"plt.rcParams[\"animation.html\"] = \"jshtml\""
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"m1 = 1\n",
"m2 = 1\n",
"c1 = 0.1\n",
"c2 = 0.1\n",
"c3 = 0.1\n",
"a1 = 0.1\n",
"a2 = 0.1\n",
"a3 = 0.1\n",
"k1 = 0.05\n",
"k2 = 0.21\n",
"k3 = 0.11\n",
"C1 = 0.15\n",
"C2 = 0.30\n",
"omega = 0.1\n",
"\n",
"f1 = lambda t: C1*np.cos(omega*t)\n",
"f2 = lambda t: C2*np.cos(omega*t)\n",
"\n",
"def deriv(X, t):\n",
" \"\"\"Return the derivatives dx/dt and d2x/dt2.\"\"\"\n",
" x1, x2, xd1, xd2 = X\n",
" F1 = f1(t)\n",
" F2 = f2(t)\n",
" xdd1 = F1 - xd1*(c1 + c2) + xd2*c2 - x1*(k1 + k2) + x2*k2 - a1*x1**3 + a2*(x2 - x1)**3\n",
" xdd2 = F2 - xd2*(c2 + c3) + xd1*c1 - x2*(k2 + k3) + x1*k2 - a3*x2**3 + a2*(x2 - x1)**3\n",
" return xd1, xd2, xdd1/m1, xdd2/m2\n",
"\n",
"\n",
"def solve_duffing(tmax, dt_per_period, t_trans, x0, v0):\n",
" \"\"\"Solve the Duffing equation with the standard odeint solver.\n",
" \n",
" Find the numerical solution to the Duffing equation using a suitable\n",
" time grid: tmax is the maximum time (s) to integrate to; t_trans is\n",
" the initial time period of transient behaviour until the solution\n",
" settles down (if it does) to some kind of periodic motion (these data\n",
" points are dropped) and dt_per_period is the number of time samples\n",
" (of duration dt) to include per period of the driving motion (frequency\n",
" omega).\n",
" \n",
" Returns the time grid, t (after t_trans), position, x, and velocity,\n",
" xdot, dt, and step, the number of array points per period of the driving\n",
" motion.\n",
" \n",
" \"\"\"\n",
" # Time point spacings and the time grid\n",
"\n",
" period = 2*np.pi/omega\n",
" dt = 2*np.pi/omega / dt_per_period\n",
" step = int(period / dt)\n",
" t = np.arange(0, tmax, dt)\n",
" # Initial conditions: x, xdot\n",
" X0 = x0 + v0\n",
" X = odeint(deriv, X0, t)\n",
" idx = int(t_trans / dt)\n",
" return t[idx:], X[idx:], dt, step"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Set up the motion for a oscillator with initial positions and velocities\n",
"x0, v0 = (0.5, -0.5), (0.5, -0.1)\n",
"tmax, t_trans = 150, 0\n",
"dt_per_period = 100"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Solve the equation of motion.\n",
"t, X, dt, pstep = solve_duffing(tmax, dt_per_period, t_trans, x0, v0)\n",
"print(\"# samples: %d\" % len(t))\n",
"print(\"dt: %.4f\" % dt)\n",
"print(\"Steps per period: %d\" % pstep)\n",
"x1, x2, xd1, xd2 = X.T"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"fig1, ((ax11, ax12), (ax21, ax22)) = plt.subplots(nrows=2, ncols=2)\n",
"\n",
"ax11.plot(t, x1)\n",
"ax11.set_xlabel(r'$x_1$')\n",
"ax12.plot(t, x2)\n",
"ax12.set_xlabel(r'$x_2$')\n",
"ax21.plot(t, xd1)\n",
"ax21.set_xlabel(r'$v_1$')\n",
"ax22.plot(t, xd2)\n",
"ax22.set_xlabel(r'$v_2$')\n",
"plt.tight_layout()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": false
},
"outputs": [],
"source": [
"%%capture\n",
"fig2, ((ax11, ax12), (ax21, ax22)) = plt.subplots(nrows=2, ncols=2)\n",
"\n",
"# Positions\n",
"ax11.set_xlabel(r'$x_1$')\n",
"ax11.set_ylabel(r'$x_2$')\n",
"ln11, = ax11.plot([], [])\n",
"ax11.set_xlim([np.min(x1), np.max(x1)])\n",
"ax11.set_ylim([np.min(x2), np.max(x2)])\n",
"\n",
"# Velocities\n",
"ax12.set_xlabel(r'$v_1$')\n",
"ax12.set_ylabel(r'$v_2$')\n",
"ln12, = ax12.plot([], [])\n",
"ax12.set_xlim([np.min(xd1), np.max(xd1)])\n",
"ax12.set_ylim([np.min(xd2), np.max(xd2)])\n",
"\n",
"# Phase spaces\n",
"ax21.set_xlabel(r'$\\mathbf{x}$')\n",
"ax21.set_ylabel(r'$\\mathbf{v}$')\n",
"ln21a, = ax21.plot([], [])\n",
"ln21b, = ax21.plot([], [])\n",
"ax21.set_xlim([min(np.min(x1), np.min(x2)), max(np.max(x1), np.max(x2))])\n",
"ax21.set_ylim([min(np.min(xd1), np.min(xd2)), max(np.max(xd1), np.max(xd2))])\n",
"\n",
"# F(t)\n",
"F1 = f1(t)\n",
"F2 = f2(t)\n",
"ax22.set_xlabel(r'$t$')\n",
"ax22.set_ylabel(r'$\\mathbf{F}(t)$')\n",
"ln22a, = ax22.plot([], [])\n",
"ln22b, = ax22.plot([], [])\n",
"ax22.set_xlim([t[0], t[-1]])\n",
"ax21.set_ylim([min(np.min(F1), np.min(F2)), max(np.max(F1), np.max(F2))])\n",
"\n",
"plt.tight_layout()\n",
"\n",
"def animate(i):\n",
" ln11.set_data(x1[:i], x2[:i])\n",
" ln12.set_data(xd1[:i], xd2[:i])\n",
" ln21a.set_data(x1[:i], xd1[:i])\n",
" ln21b.set_data(x2[:i], xd2[:i])\n",
" ln22a.set_data(t[:i], F1[:i])\n",
" ln22b.set_data(t[:i], F2[:i])\n",
" \n",
"\n",
"anim = animation.FuncAnimation(fig2, animate, frames=len(t), interval=100, repeat_delay=1000)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"anim"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"anaconda-cloud": {},
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.2"
}
},
"nbformat": 4,
"nbformat_minor": 1
}

File diff suppressed because one or more lines are too long

144
pydstool_integrator.py Normal file
View File

@ -0,0 +1,144 @@
"""Simulate duffing model with PyDSTool integrator.
See
https://github.com/robclewley/pydstool/blob/master/examples/forced_spring.py
for forced-spring example.
"""
import numpy as np
import PyDSTool
def simulate(T, t_trans, steps, x0, v0, omega, p):
x1, x2 = x0
xd1, xd2 = v0
C1, C2, m1, m2, c1, c2, c3, k1, k2, k3, a1, a2, a3 = p
args = PyDSTool.args(name='duffing-stuffing')
args.varspecs = {
'x1': 'xd1',
'x2': 'xd2',
'xd1': 'C1*F(t)/m1 - xd1*(c1 + c3) + xd2*c3 - x1*(k1 + k3) + x2*k3 - a1*pow(x1, 3) + a3*pow(x2 - x1, 3)',
'xd2': 'C2*F(t)/m2 - xd2*(c2 + c3) + xd1*c3 - x2*(k2 + k3) + x1*k3 - a2*pow(x2, 3) + a3*pow(x2 - x1, 3)'
}
args.fnspecs = {
'F': (['t'], 'cos(omega*t)')
}
args.pars = {
'omega': omega,
'C1': C1, 'C2': C2,
'm1': m1, 'm2': m2,
'c1': c1, 'c2': c2, 'c3': c3,
'k1': k1, 'k2': k2, 'k3': k3,
'a1': a1, 'a2': a2, 'a3': a3
}
args.ics = {
'x1': x0[0], 'x2': x0[1],
'xd1': v0[0], 'xd2': v0[1]
}
args.xdomain = {
'x1': [-10, 10], 'x2': [-10, 10],
'xd1': [-1e6, 1e6], 'xd2': [-1e6, 1e6]
}
#args.tdomain = [0, T]
args.tdata = [0, T]
# Integrator
ds = PyDSTool.Generator.Vode_ODEsystem(args)
traj = ds.compute('experiment')
pts = traj.sample(dt=(T-t_trans)/steps, precise=True)
return np.stack([
pts['x1'][-steps:],
pts['x2'][-steps:],
pts['xd1'][-steps:],
pts['xd2'][-steps:]
])
def test():
C1 = 1.5e5
C2 = 1.5e5
m1 = 1.0 #1e-3
m2 = 1.0 #1e-3
c1 = 9647.403
c2 = 10282.101
c3 = 0.000
k1 = 2326809592.681
k2 = 2643039774.512
k3 = 0.000
a1 = 0.000
a2 = 0.000
a3 = 0.000
p = (
C1, C2,
m1, m2,
c1, c2, c3,
k1, k2, k3,
a1, a2, a3
)
omega = 2*np.pi*5e3
x0, v0 = (0.00001, 0.00002), (0.000001, 0.0002)
T = 0.6
t_trans = 0.1
steps = 100
return simulate(T, t_trans, steps, x0, v0, omega, p)
if __name__ == '__main__':
X = test()
print(X.shape)
print(X.mean(axis=1))
print(X.std(axis=1))
print(X)
#pars = {'D1': 1.0 , 'D2': 10.0, 'A': 2.1, 'B': 3.5, 'lambda': 5}
#
#tdomain = [0,50]
#
#icdict = {'X1': 1.087734, 'X2': 1.087734, 'X3': 4.124552, \
# 'Y1': 1.8488063, 'Y2': 1.8488063, 'Y3': 1.0389936}
#
## Set up model
#X1str = 'D1*(X2 - 2*X1 + X3) + lambda*(A - (B+1)*X1 + pow(X1,2)*Y1)'
#X2str = 'D1*(X3 - 2*X2 + X1) + lambda*(A - (B+1)*X2 + pow(X2,2)*Y2)'
#X3str = 'D1*(X1 - 2*X3 + X2) + lambda*(A - (B+1)*X3 + pow(X3,2)*Y3)'
#Y1str = 'D2*(Y2 - 2*Y1 + Y3) + lambda*(B*X1 - pow(X1,2)*Y1)'
#Y2str = 'D2*(Y3 - 2*Y2 + Y1) + lambda*(B*X2 - pow(X2,2)*Y2)'
#Y3str = 'D2*(Y1 - 2*Y3 + Y2) + lambda*(B*X3 - pow(X3,2)*Y3)'
#
#DSargs = args(name='Brusselator')
#DSargs.tdomain = tdomain
#DSargs.pars = pars
#DSargs.varspecs = {'X1': X1str, 'X2': X2str, 'X3': X3str, 'Y1': Y1str, 'Y2': Y2str, 'Y3': Y3str}
#DSargs.xdomain = {'X1': [0, 50], 'X2': [0, 50], 'X3': [0, 50], 'Y1': [0, 50], 'Y2': [0, 50], 'Y3': [0, 50]}
#DSargs.ics = icdict
#
#testDS = Generator.Vode_ODEsystem(DSargs)
#
## Set up continuation class
#PyCont = ContClass(testDS)
#
#PCargs = args(name='EQ1', type='EP-C')
#PCargs.freepars = ['lambda']
#PCargs.StepSize = 5e-3
#PCargs.LocBifPoints = ['BP','LP']
#PCargs.verbosity = 2
#PCargs.SaveEigen = True
#PyCont.newCurve(PCargs)
#
#print('Computing curve...')
#start = clock()
#PyCont['EQ1'].forward()
#print('done in %.3f seconds!' % (clock()-start))
#
## Plot
#PyCont['EQ1'].display(('lambda','X1'), stability=True)
#PyCont.plot.toggleAll('off', byname='P1')
#show()

2
requirements.txt Normal file
View File

@ -0,0 +1,2 @@
scipy>=0.5.1,<1.0
PyDSTool