Example 4: Coupled quadratic oscillators in 1:2 internal resonance
MMS example on coupled quadratic oscillators in 1:2 internal resonance subject to harmonic forcing. This configuration was studied by Nayfeh and Mook in Nonlinear Oscillations (1995), sections 6.5 and 6.5.1.
System description
Illustration of two forced oscillators coupled through quadratic nonlinearities in 1:2 internal resonance, provided \(\omega_1 \approx 2 \omega_0\).
The system’s equations are
where
\(x_0,\; x_1\) are the oscillators’ coordinates,
\(t\) is the time,
\(\dot{(\bullet)} = \mathrm{d}(\bullet)/\mathrm{d}t\) is a time derivative,
\(\mu_0,\; \mu_1\) are the linear viscous damping coefficients,
\(\omega_1,\; \omega_1\) are the oscillator’s natural frequencies,
\(\alpha_0,\; \alpha_1\) are nonlinear coefficients,
\(\eta_0,\; \eta_1\) are forcing coefficients,
\(F\) is the forcing amplitude,
\(\omega\) is the forcing frequency.
The oscillators are in 1:2 internal resonance. Taking \(\omega_0\) as the reference frequency, this implies
where \(\sigma_1\) is the detuning of oscillator 1 wrt the 1:2 internal resonance condition.
A response around \(2\omega_0 \approx \omega_1\) is sought so the frequency is set to
where
\(\epsilon\) is a small parameter involved in the MMS,
\(\sigma\) is the detuning.
The parameters are then scaled to indicate how weak they are:
\(\mu_i = \epsilon \tilde{\mu}_i\) indicates that damping is weak,
\(\eta_0 = \epsilon \tilde{\eta}_0\) indicates that forcing on oscillator 0 is weak,
\(\eta_1 = \epsilon \tilde{\eta}_1\) indicates that forcing on oscillator 1 is one order weaker than that on oscillator 0,
\(\sigma_1 = \epsilon \tilde{\sigma}_1\) indicates that detuning is small,
\(\alpha_i = \epsilon \tilde{\alpha}_i\) indicates that nonlinearities are weak.
In addition, the solutions are sought with leading order terms at order \(\epsilon\) rather than \(\epsilon^0=1\) which was used in previous examples.
This is controled through eps_pow_0=1.
Code description
The script below allows to
Construct the dynamical system.
Apply the MMS to the system,
Evaluate the MMS results at steady state,
Compute the backbone curve when only oscillator 0 responds,
Compute the coupled-mode forced response.
1# -*- coding: utf-8 -*-
2
3#%% Imports and initialisation
4from sympy import symbols, Function, solve, sin, cos, Rational
5from sympy.physics.vector.printing import init_vprinting
6init_vprinting(use_latex=True, forecolor='White') # Initialise latex printing
7from oscilate import MMS
8
9# Parameters and variables
10omega0, omega1, F, mu0, ma0 = symbols(r'\omega_0, \omega_1, F, \mu_0, \mu_1', real=True, positive=True)
11alpha0, alpha1 = symbols(r"\alpha_0, \alpha_1", real=True) # Nonlinear coefficients
12eta0, eta1 = symbols(r"\eta_0, \eta_1", real=True) # Forcing coefficients
13
14t = symbols('t')
15x0 = Function(r'x_0', real=True)(t)
16x1 = Function(r'x_1', real=True)(t)
17
18# Dynamical system
19Eq0 = x0.diff(t,2) + omega0**2*x0 + 2*mu0*x0.diff(t) + alpha0*x0*x1
20Eq1 = x1.diff(t,2) + omega1**2*x1 + 2*ma0*x1.diff(t) + alpha1*x0**2
21fF = [eta0, eta1]
22dyn = MMS.Dynamical_system(t, [x0, x1], [Eq0, Eq1], [omega0, omega1], fF=fF, F=F)
23
24# Initialisation of the MMS sytem
25eps = symbols(r"\epsilon", real=True, positive=True) # Small parameter epsilon
26Ne = 1 # Order of the expansions
27omega_ref = omega0 # Reference frequency
28ratio_omegaMMS = 2 # Look for a solution around omega1
29
30ratio_omega_osc = [1, 2] # Ratio between the oscillators' frequencies and the reference frequency
31sigma1 = symbols(r"\sigma_1", real=True) # Detuning of oscillator 1
32detunings = [0, sigma1] # Detuning of the oscillators' frequency
33
34param_to_scale = (F, eta0, eta1, mu0, ma0, sigma1, alpha0, alpha1)
35scaling = (0, 1, 2, 1, 1, 1, 0, 0)
36param_scaled, sub_scaling = MMS.scale_parameters(param_to_scale, scaling, eps)
37
38kwargs_mms = dict(ratio_omegaMMS=ratio_omegaMMS, ratio_omega_osc=ratio_omega_osc,
39 detunings=detunings, eps_pow_0=1)
40mms = MMS.Multiple_scales_system(dyn, eps, Ne, omega_ref, sub_scaling, **kwargs_mms)
41
42# Application of the MMS
43mms.apply_MMS(rewrite_polar="all")
44
45# Evaluation at steady state
46ss = MMS.Steady_state(mms)
47ss.solve_bbc(solve_dof=0, c=param_scaled[3:5])
48
49# Computation of the coupled forced solution
50print("Manual computation of the coupled forced solution")
51
52a, beta = ss.coord.a, ss.coord.beta
53
54Dbeta = symbols(r"\Delta\beta", real=True) # Phase difference Dbeta = 2beta0-beta1
55sub_phase = [(beta[0], Rational(1,2)*(beta[1]-Dbeta))] # Substitute the phases by the phase difference
56fa = [fai.subs(sub_phase) for fai in ss.sol.fa]
57fbeta = [fbetai.subs(sub_phase) for fbetai in ss.sol.fbeta]
58
59dic_fa0 = fa[0].collect(sin(Dbeta), evaluate=False)
60dic_fbeta0 = fbeta[0].collect(cos(Dbeta), evaluate=False)
61Eq_a1 = (dic_fa0[1]/dic_fa0[sin(Dbeta)])**2 + (dic_fbeta0[1]/dic_fbeta0[cos(Dbeta)])**2 - 1
62a1_2_sol = solve(Eq_a1, a[1]**2)[0] # Solution a1**2
63
64Dbeta_sol = solve(fa[0], Dbeta) # Phase difference solution
65chi = symbols(r"\chi", real=True) # +/- symbol introduced to represent the 2 phase difference solutions
66sub_Dbeta = [(sin(Dbeta), sin(Dbeta_sol[0])), (cos(Dbeta), chi*cos(Dbeta_sol[0]))]
67
68dic_fa1 = fa[1].collect(sin(beta[1]), evaluate=False)
69dic_fbeta0 = fbeta[1].collect(cos(beta[1]), evaluate=False)
70Eq_a0 = (((dic_fa1[1]/dic_fa1[sin(beta[1])])**2 + (dic_fbeta0[1]/dic_fbeta0[cos(beta[1])])**2 - 1).subs(sub_Dbeta).subs(ss.coord.a[1]**2, a1_2_sol)).simplify()
71a0_2_sol = solve(Eq_a0, a[0]**2) # Solution a0**2
72
73
74# %%