download
raw
3.81 kB
"""
Solve the general vibration ODE by various method from the Odespy
package.
"""
import scitools.std as plt
#import matplotlib.pyplot as plt
import sys
import numpy as np
from scitools.std import StringFunction
import odespy
import vib
class RHS:
"""
Class defining the right-hand side of the ODE
m*u'' + b*|u'|u' + s(u) = F(t).
"""
def __init__(self, m=1, b=0, s=lambda u: (2*np.pi)**2*u,
F=lambda t: 0, I=1, V=0, damping='linear'):
if isinstance(s, str):
# Turn string formula into Python function
# (send globals() such that pi, sin, cos, etc from
# numpy can be used in the string expression)
s = StringFunction(s, globals=globals())
if isinstance(F, str):
F = StringFunction(F, globals=globals())
self.m, self.b, self.s, self.F = float(m), b, s, F
self.I, self.V = I, V
self.damping = damping
def __call__(self, u, t):
"""Right-hand side function defining the ODE."""
u, v = u # u is array of length 2 holding our [u, v]
if self.damping == 'linear':
b_term = self.b*v
elif self.damping == 'quadratic':
b_term = self.b*np.abs(v)*v
else:
b_term = 0
return [v, (-b_term - self.s(u) + self.F(t))/self.m]
def run_solvers_and_plot(solvers, rhs, T, dt, title='', filename='tmp'):
"""
Run solvers from the `solvers` list and plot solution curves in
the same figure.
"""
Nt = int(round(T/float(dt)))
t_mesh = np.linspace(0, T, Nt+1)
t_fine = np.linspace(0, T, 8*Nt+1) # used for very accurate solution
legends = []
for solver in solvers:
solver.set_initial_condition([rhs.I, 0])
u, t = solver.solve(t_mesh)
solver_name = 'CrankNicolson' if solver.__class__.__name__ == \
'MidpointImplicit' else solver.__class__.__name__
if len(t_mesh) <= 50:
plt.plot(t, u[:,0]) # markers by default
else:
plt.plot(t, u[:,0], '-2') # no markers
plt.hold('on')
legends.append(solver_name)
# Compare with RK4 on a much finer mesh
solver_exact = odespy.RK4(rhs)
solver_exact.set_initial_condition([rhs.I, 0])
u_e, t_e = solver_exact.solve(t_fine)
plt.plot(t_e, u_e[:,0], '-') # avoid markers by spec. line type
legends.append('RK4, dt=%g' % (t_fine[1]-t_fine[0]))
plt.legend(legends, loc='lower left')
plt.xlabel('t'); plt.ylabel('u')
plt.title(title)
plotfilestem = '_'.join(legends)
plt.savefig('%s.png' % filename)
plt.savefig('%s.pdf' % filename)
class VibSolverWrapper4Odespy:
"""
Wrapper for vib.solver so that it has the same API as
required by solvers in odespy. Then it can be used
together with the odespy solvers.
"""
def __init__(self, f, *args, **kwargs):
self.rhs = f
def set_initial_condition(self, U0):
self.U0 = U0
def solve(self, t, terminate=None):
dt = t[1] - t[0] # assuming constant time step
T = t[-1]
I, V = self.U0
self.u, self.t = vib.solver(
I, V, self.rhs.m, self.rhs.b, self.rhs.s, self.rhs.F,
dt, T, damping=self.rhs.damping)
# Must compute v=u' and pack with u
self.v = np.zeros_like(self.u)
self.v[1:-1] = (self.u[2:] - self.u[:-2])/(2*dt)
self.v[0] = V
self.v[-1] = (self.u[-1] - self.u[-2])/dt
self.r = np.zeros((self.u.size, 2))
self.r[:,0] = self.u
self.r[:,1] = self.v
if terminate is not None:
for i in range(len(self.t)):
if terminate(self.r, self.t, i):
return self.r[:i+1], self.t[:i+1]
return self.r, self.t

Xet Storage Details

Size:
3.81 kB
·
Xet hash:
dbd33469534322357dd5da8adb28b8f11d6f9a8d190f04b1b8e31205c24b0d57

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.