3 ***************************************************************
6 * <functionality description> *
8 * from: Perturbation Methods, Bifurcation *
9 * Theory and Computer Algebra. *
10 * by Rand & Armbruster (Springer 1987) *
11 * Programmed by Richard Rand *
12 * These files are released to the public domain *
14 ***************************************************************
16 /* program number 6: twovar(), a function to perform a two variable
17 expansion to order epsilon for n weakly coupled perturbed nonlinear
18 oscillators. see page 94 in "perturbation methods, bifurcation
19 theory and computer algebra". */
25 choice:read("do you want to enter new data (y/n)"),
27 if choice = n then go(jump1),
30 n:read("number of d.e.'s"),
32 print("the",n,"d.e.'s will be in the form:"),
33 print("x[i]'' + w[i]^2 x[i] = e f[i](x[1],...,x[",n,"],t)"),
36 x[i]:read("enter symbol for x[",i,"]"),
42 w[i]:read("enter w[",i,"]"),
45 f[i]:read("enter f[",i,"]"),
49 /* update eqs for substitution of resonant values on 2nd time thru */
54 /* echo back the d.e.'s */
55 print("the d.e.'s are entered as:"),
57 print(x[i],"'' +",w[i]^2*x[i],"=",e*f[i]),
59 print("the method assumes a solution in the form:"),
60 print("x[i] = x0[i] + e x1[i]"),
61 print("where x0[i] = a[i](eta) cos w[i] xi + b[i](eta) sin w[i] xi"),
62 print("where xi = t and eta = e t"),
64 /* don't use a or b as parameters in the given d.e.'s */
68 x0[i]:a[i]*cos(w[i]*xi)+b[i]*sin(w[i]*xi),
75 g[i]:ev(g[i],x[j]::x0[j])),
78 g[i]:g[i]-2*diff(x0[i],xi,1,eta,1),
80 g[i]:expand(trigreduce(expand(g[i])))),
82 /* collect secular terms */
84 s[i]:coeff(g[i],sin(w[i]*xi)),
85 c[i]:coeff(g[i],cos(w[i]*xi))),
87 /* display secular terms */
88 print("removal of secular terms in the x1[i] eqs. gives:"),
94 abeqs:append(makelist(s[i],i,1,n),makelist(c[i],i,1,n)),
96 choice2:read("do you want to transform to polar coordinates (y/n)"),
98 if choice2=n then go(jump2),
100 /* transform to polar coordinates */
101 depends([r,theta],eta),
102 trans:makelist([a[i]=r[i]*cos(theta[i]),b[i]=r[i]*sin(theta[i])],i,1,n),
103 inteqs:ev(abeqs,trans,diff),
104 rtheqs:solve(inteqs,append(makelist(diff(r[i],eta),i,1,n),
105 makelist(diff(theta[i],eta),i,1,n))),
106 rtheqs:trigsimp(rtheqs),
107 rtheqs:expand(trigreduce(rtheqs)),
112 choice3:read("do you want to search for resonant parameter values (y/n)"),
114 if choice3=n then go(end),
116 /* obtain frequencies which appear on rhs's of d.e.'s */
118 /* define pattern matching rules to isolate freqs */
119 matchdeclare([dummy1,dummy2],true),
120 defrule(cosarg,dummy1*cos(dummy2),dummy2),
121 defrule(sinarg,dummy1*sin(dummy2),dummy2),
124 /* change sum to a list */
126 /* remove constant terms */
127 temp2:map(trigidentify,temp1),
128 /* isolate arguments of trig terms */
129 temp3:apply1(temp2,cosarg,sinarg),
130 temp4:ev(temp3,xi=1),
131 /* remove duplicate arguments */
132 freq[i]:setify(temp4)),
134 /* display frequencies */
136 print(x[i],"eq's resonant freq =",w[i]),
137 print("freqs on rhs =",freq[i])),
141 par:read("which parameter to search for ?"),
143 /* compute resonant values of desired parameter */
146 for j:1 thru length(freq[i]) do(
147 res:solve(part(freq[i],j)=w[i],par),
148 if (res#[] and res#all) then resvals:append(resvals,res),
149 res:solve(part(freq[i],j)=-w[i],par),
150 if (res#[] and res#all) then resvals:append(resvals,res))),
152 /* eliminate duplicate parameter values */
153 resvalues:setify(resvals),
155 /* display resonant parameter values */
158 choice4:read("do you want to search for another parameter (y/n) ?"),
160 if choice4=y then go(jump3),
164 /* auxiliary functions */
166 trigidentify(exp):=if freeof(sin,exp) and freeof(cos,exp) then 0 else exp$
170 for i:2 thru length(list) do(
171 if not member(list[i],set) then set:cons(list[i],set)),