123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 |
- module odespcfn$ % Linear special function ODEs
- % F.J.Wright@Maths.QMW.ac.uk, Time-stamp: <14 September 2000>
- % Old version temporarily preserved for testing other developments!
- % A first attempt at pattern-matching solution of special (currently
- % only second-order) linear odes. Need to add more patterns. But
- % this approach may be too slow with more patterns anyway.
- % If the specfn package is not loaded then we need this declaration:
- algebraic operator Airy_Ai, Airy_Bi$
- algebraic operator odesolve!-specfn!*$ % internal wrapper function
- algebraic procedure ODESolve!-Specfn(odecoeffs1, driver1, x);
- %% Using monic coeffs for uniqueness.
- begin scalar ode, rules, soln;
- traceode1 "Looking for special-function solutions ...";
- ode := odesolve!-specfn!*(first odecoeffs1, second odecoeffs1);
- rules := {
- %% MUST use specific x, y (not ~x, ~y) for correct matching.
- %% ~~ does not seem to work in any of these rules.
- %% odesolve(df(y,x,2) - x*y, y, x);
- odesolve!-specfn!*(-x, 0) =>
- odesolve!-solns(Airy_Ai(x), Airy_Bi(x)),
- %% odesolve(df(y,x,2) - a3*x*y, y, x);
- odesolve!-specfn!*(-~a3*x, 0) =>
- odesolve!-solns(Airy_Ai(x), Airy_Bi(x), x=a3^(1/3)*x),
- %% odesolve(df(y,x,2) - (a3*x+a2b)*y, y, x);
- odesolve!-specfn!*(-(~a3*x+~a2b), 0) =>
- odesolve!-solns(Airy_Ai(x), Airy_Bi(x),
- x=a3^(1/3)*x+a2b/a3^(2/3)),
- %% The order of the following rules matters!
- %% odesolve(x^2*df(y,x,2) + x*df(y,x) - (x^2+n2)*y, y, x);
- odesolve!-specfn!*(-(1+~n2/x^2), 1/x)
- => odesolve!-solns(BesselI(n,x), BesselK(n,x),
- n = sqrt(n2)),
- %% odesolve(x^2*df(y,x,2) + x*df(y,x) + (x^2-n2)*y, y, x);
- odesolve!-specfn!*(1-~n2/x^2, 1/x)
- => odesolve!-solns(BesselJ(n,x), BesselY(n,x),
- n = sqrt(n2)),
- %% odesolve(x^2*df(y,x,2) + x*df(y,x) - (a2*x^2+n2)*y, y, x);
- odesolve!-specfn!*(-(~a2+~n2/x^2), 1/x)
- => odesolve!-solns(BesselI(n,a*x), BesselK(n,a*x),
- n = sqrt(n2), a = sqrt(a2)),
- %% odesolve(x^2*df(y,x,2) + x*df(y,x) + (a2*x^2-n2)*y, y, x);
- odesolve!-specfn!*(~a2-~n2/x^2, 1/x)
- => odesolve!-solns(BesselJ(n,a*x), BesselY(n,a*x),
- n = sqrt(n2), a = sqrt(a2)),
- %% odesolve(x*df(y,x,2) + df(y,x) - x*y, y, x);
- %% odesolve!-specfn!*(-1, 1/x)
- %% => odesolve!-solns(BesselI(0,x), BesselK(0,x)),
- %% odesolve(x*df(y,x,2) + df(y,x) - a2*x*y, y, x);
- odesolve!-specfn!*(-~a2, 1/x)
- => odesolve!-solns(BesselI(0,a*x), BesselK(0,a*x),
- a = sqrt(a2)),
- %% odesolve(x*df(y,x,2) + df(y,x) + x*y, y, x);
- %% odesolve!-specfn!*(1, 1/x)
- %% => odesolve!-solns(BesselJ(0,x), BesselY(0,x)),
- %% odesolve(x*df(y,x,2) + df(y,x) + a2*x*y, y, x);
- odesolve!-specfn!*(~a2, 1/x)
- => odesolve!-solns(BesselJ(0,a*x), BesselY(0,a*x),
- a = sqrt(a2))
- }$
- soln := (ode where rules); % `where' cannot produce a list!
- if soln neq ode then <<
- traceode
- "The reduced ODE can be solved in terms of special functions.";
- soln := part(soln, 1);
- %% if symbolic !*odesolve_load_specfn then load_package specfn;
- return if driver1 then
- %% BEWARE: This driver code is not well tested!
- %% traceode "But cannot currently handle the driver term! "
- { soln, ODESolve!-PI(soln, driver1, x) }
- else { soln }
- >>
- end$
- algebraic operator ODESolve!-Solns!*$
- listargp ODESolve!-Solns!*$
- put('ODESolve!-Solns, 'psopfn, 'ODESolve!-Solns)$
- symbolic procedure ODESolve!-Solns u; % (solns, subs)
- %% Avoid invalid lists on right of replacement rule, and build full
- %% optionally substituted basis data structure:
- begin scalar solns;
- %% u := revlis u;
- solns := {'list, car u, cadr u}; % algebraic list
- if (u := cddr u) then << % substitutions
- u := if cdr u then 'list . u else car u;
- solns := algebraic sub(u, solns)
- >>;
- return {'ODESolve!-Solns!*, solns}
- end$
- endmodule$
- end$
|