import numpy as np
from resonance.nonlinear_systems import SingleDoFNonLinearSystem
To apply arbitrary forcing to a single degree of freedom linear or nonlinear system, you can do so with SingleDoFNonLinearSystem
(SingleDoFLinearSystem
does not support arbitrary forcing...yet).
Add constants, a generalized coordinate, and a generalized speed to the system.
sys = SingleDoFNonLinearSystem()
sys.constants['m'] = 100 # kg
sys.constants['c'] = 1.1*1.2*0.5/2
sys.constants['k'] = 10
sys.constants['Fo'] = 1000 # N
sys.constants['Ft'] = 100 # N/s
sys.constants['to'] = 3.0 # s
sys.coordinates['x'] = 0.0
sys.speeds['v'] = 0.0
Create a function that evaluates the first order form of the non-linear equations of motion. In this case:
$$ \dot{x} = v \\ m\dot{v} + c \textrm{sgn}(v)v^2 + k \textrm{sgn}(x)x^2 = F(t) $$Make the arbitrary forcing term, $F$, an input to this function.
def eval_eom(x, v, m, c, k, F):
xdot = v
vdot = (F - np.sign(v)*c*v**2 - np.sign(x)*k*x**2) / m
return xdot, vdot
Note that you cannot add this to the system because F
has not been defined.
sys.diff_eq_func = eval_eom
To rememdy this, create a function that returns the input value given the appropriate constants and time.
def eval_step_input(Fo, to, time):
if time < to:
return 0.0
else:
return Fo
import matplotlib.pyplot as plt
%matplotlib widget
ts = np.linspace(0, 10)
plt.plot(ts, eval_step_input(5.0, 3.0, ts))
ts < 3.0
def eval_step_input(Fo, to, time):
F = np.empty_like(time)
for i, ti in enumerate(time):
if ti < to:
F[i] = 0.0
else:
F[i] = Fo
return F
plt.plot(ts, eval_step_input(5.0, 3.0, ts))
eval_step_input(5.0, 3.0, ts)
eval_step_input(5.0, 3.0, 7.0)
def eval_step_input(Fo, to, time):
if np.isscalar(time):
if time < to:
return 0.0
else:
return Fo
else:
F = np.empty_like(time)
for i, ti in enumerate(time):
if ti < to:
F[i] = 0.0
else:
F[i] = Fo
return F
eval_step_input(5.0, 3.0, 7.0)
eval_step_input(5.0, 3.0, ts)
True * 5.0
False * 5.0
(ts >= 3.0)*5.0
(5.0 >= 3.0)*5.0
def eval_step_input(Fo, to, time):
return (time >=to)*Fo
eval_step_input(5.0, 3.0, ts)
eval_step_input(5.0, 3.0, 7.0)
sys.add_measurement('F', eval_step_input)
sys.diff_eq_func = eval_eom
traj = sys.free_response(20.0)
traj.plot(subplots=True)
def eval_ramp_input(Ft, to, time):
return (time >= to)*(Ft*time - Ft*to)
del sys.measurements['F']
sys.add_measurement('F', eval_ramp_input)
sys.measurements
traj = sys.free_response(20.0)
traj.plot(subplots=True)