Damped Harmonic Oscillator
Nov 21, 2022
Or: Implementing a damped spring model in 16 lines of code.
Governing Equation:
Zero-input response f(t) = 0
Solve
Exponential ansatz:
Plugging in gives
Two solutions x_1(t) = \left(A_1 e^{\sigma t}\right) e^{-\bar{\lambda}t} and x_2(t) = \left(A_2e^{-\sigma t}\right) e^{-\bar{\lambda}t}
To solve for A_1 and A_2 we need two initial condition x(t_o)=x_o and \dot{x}(t_o)=\dot{x}_o , i.e.
Let t_o=0 , then all the exponentials are 1, so it simplifies to
Altogether it becomes
Which can be rearranged to
Click to see derivation
One can see that e^{-\bar{\lambda}t} contributes uniform decay and anchors the characteristic timescale of the system.
Now define the odd and even exponential factors as
Thus, the most general form for all cases can be expressed as
Sample Lua Implementation
function sprung_response(t,d,v,k,c,m)
local decay = c/2/m
local omega = math.sqrt(k/m)
local resid = decay*decay-omega*omega
local scale = math.sqrt(math.abs(resid))
local T1,T0 = t , 1
if resid<0 then
T1,T0 = math.sin( scale*t)/scale , math.cos( scale*t)
elseif resid>0 then
T1,T0 = math.sinh(scale*t)/scale , math.cosh(scale*t)
end
local dissipation = math.exp(-decay*t)
local evolved_pos = dissipation*( d*(T0+T1*decay) + v*( T1 ) )
local evolved_vel = dissipation*( d*(-T1*omega^2) + v*(T0-T1*decay) )
return evolved_pos , evolved_vel
end
Damping Cases
The e^{-\bar{\lambda}t} factor is the global dissipator, and \tau_1, \tau_0 are the first- and zeroth-order time-integrators.
If all system parameters (m,c,k) are real, then \sigma can be either real, imaginary, or zero, giving rise to the three well-known over/under/critically damped classifications.
Substituting each cases’ \sigma into T_n evaluates to the following: