3.5. A nonlinear oscillator
So far, all considered equations were linear ODEs or linear ODE systems. However, unlike e.g. FEniCS, there is no difference in defining linear and nonlinear equations in pyoomph, a feature which is directly inherited from oomph-lib. One famous nonlinear oscillator is the Van der Pol oscillator
Here, the parameter \(\mu\) controls the nonlinearity. It is obvious that a positive value of \(\mu\) will damp the oscillation whenever \(y^2>1\) and enhance the amplitude whenever \(y^2<1\). The straightforward way of implementing this equation would be again to write an equation class:
class VanDerPolOscillator(ODEEquations):
def __init__(self,mu): #Requires the parameter mu
super(VanDerPolOscillator,self).__init__()
self.mu=mu #Store the value of mu
def define_fields(self):
self.define_ode_variable("y") #same as usual
def define_residuals(self):
y=var("y")
residual=partial_t(y,2)-self.mu*(1-y**2)*partial_t(y)+y
self.add_residual(residual*testfunction(y))
It is not a problem to add the nonlinear damping term to the residuals - a step where FEniCS would complain unless explictly implemented as nonlinear problem.
There is also another way to implement exactly the same equation by using already implemented equations. In the following, we make use of the predefined harmonic oscillator that comes with pyoomph:
# import the predefined harmonic oscillator equation
from pyoomph.equations.harmonic_oscillator import HarmonicOscillator
#Inherit from the HarmonicOscillator class
class VanDerPolOscillator(HarmonicOscillator):
def __init__(self,mu):
damping=-mu/2*(1-var("y")**2)
super(VanDerPolOscillator,self).__init__(name="y",damping=damping,omega=1)
Here, we use inheritance, i.e. the methods define_fields() and define_residuals() will be inherited from the super-class HarmonicOscillator, which will calculate
If we replace \(\delta=-1/2 \mu(1-y)^2\), we get in fact the Van der Pol oscillator (3.5). This fact is used here: when calling the constructor _init__ of the super-class HarmonicOscillator, we pass exactly this expression as damping parameter and thereby recover the Van der Pol oscillator. Obviously, there are always multiple ways in pyoomph to achieve the same goal. A plot of the numerical solution is shown in Fig. 3.4.
Fig. 3.4 Output for the nonlinear Van der Pol oscillator.