import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt
# --- 1. Define the Duffing Equation as a system of first-order ODEs ---
# The Duffing equation is a second-order non-linear differential equation:
# x'' + delta*x' + beta*x + alpha*x^3 = gamma*cos(omega*t)
# We convert it to a system of two first-order ODEs for numerical solution:
# Let y[0] = x (displacement)
# Let y[1] = x' (velocity)
# Then, y[0]' = y[1]
# And, y[1]' = gamma*cos(omega*t) - delta*y[1] - beta*y[0] - alpha*y[0]**3
def duffing_model(y, t, delta, alpha, beta, gamma, omega):
"""
Returns the derivatives of the state variables for the Duffing equation.
Args:
y (list): A list or array containing the state variables [x, x'].
t (float): The current time.
delta (float): Damping coefficient.
alpha (float): Coefficient for the non-linear term.
beta (float): Coefficient for the linear restoring force.
gamma (float): Amplitude of the periodic forcing term.
omega (float): Frequency of the periodic forcing term.
Returns:
list: The derivatives of the state variables [x', x''].
"""
= y[1]
y0_prime = gamma * np.cos(omega * t) - delta * y[1] - beta * y[0] - alpha * y[0]**3
y1_prime return [y0_prime, y1_prime]
# --- 2. Set up the parameters and initial conditions ---
# Parameters for the Duffing oscillator
= 0.2 # Damping
delta = 1.0 # Non-linear spring coefficient
alpha = -1.0 # Linear spring coefficient (negative for a bistable potential)
beta = 0.3 # Forcing amplitude
gamma = 1.0 # Forcing frequency
omega
# Initial conditions [x(0), x'(0)]
= [0.0, 0.0]
y0
# Time points to solve for
= np.linspace(0, 100, 1000)
t
# Pack parameters into a tuple
= (delta, alpha, beta, gamma, omega)
params
# --- 3. Solve the ODE using odeint ---
# The odeint function returns an array where each row is a solution for a time point.
= odeint(duffing_model, y0, t, args=params)
solution
# --- 4. Plot the results ---
# Separate the solution into displacement (x) and velocity (x')
= solution[:, 0]
x_solution = solution[:, 1]
x_prime_solution
# Create a figure with two subplots side-by-side
= plt.subplots(1, 2, figsize=(12, 5))
fig, (ax1, ax2) 'Duffing Equation Simulation', fontsize=16)
fig.suptitle(
# Plot Displacement vs. Time
'b-')
ax1.plot(t, x_solution, 'Displacement vs. Time')
ax1.set_title('Time')
ax1.set_xlabel('Displacement (x)')
ax1.set_ylabel(True)
ax1.grid(
# Plot the Phase Portrait (Velocity vs. Displacement)
'r-')
ax2.plot(x_solution, x_prime_solution, 'Phase Portrait (Velocity vs. Displacement)')
ax2.set_title('Displacement (x)')
ax2.set_xlabel('Velocity (dx/dt)')
ax2.set_ylabel(True)
ax2.grid(0, color='gray', linewidth=0.5)
ax2.axhline(0, color='gray', linewidth=0.5)
ax2.axvline(
# Adjust layout and display the plots
=[0, 0.03, 1, 0.95])
plt.tight_layout(rect plt.show()
DENLDuffing
writeup
Duffing Non Linear Differential Equation