odespcfn.red 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. module odespcfn$ % Linear special function ODEs
  2. % F.J.Wright@Maths.QMW.ac.uk, Time-stamp: <14 September 2000>
  3. % Old version temporarily preserved for testing other developments!
  4. % A first attempt at pattern-matching solution of special (currently
  5. % only second-order) linear odes. Need to add more patterns. But
  6. % this approach may be too slow with more patterns anyway.
  7. % If the specfn package is not loaded then we need this declaration:
  8. algebraic operator Airy_Ai, Airy_Bi$
  9. algebraic operator odesolve!-specfn!*$ % internal wrapper function
  10. algebraic procedure ODESolve!-Specfn(odecoeffs1, driver1, x);
  11. %% Using monic coeffs for uniqueness.
  12. begin scalar ode, rules, soln;
  13. traceode1 "Looking for special-function solutions ...";
  14. ode := odesolve!-specfn!*(first odecoeffs1, second odecoeffs1);
  15. rules := {
  16. %% MUST use specific x, y (not ~x, ~y) for correct matching.
  17. %% ~~ does not seem to work in any of these rules.
  18. %% odesolve(df(y,x,2) - x*y, y, x);
  19. odesolve!-specfn!*(-x, 0) =>
  20. odesolve!-solns(Airy_Ai(x), Airy_Bi(x)),
  21. %% odesolve(df(y,x,2) - a3*x*y, y, x);
  22. odesolve!-specfn!*(-~a3*x, 0) =>
  23. odesolve!-solns(Airy_Ai(x), Airy_Bi(x), x=a3^(1/3)*x),
  24. %% odesolve(df(y,x,2) - (a3*x+a2b)*y, y, x);
  25. odesolve!-specfn!*(-(~a3*x+~a2b), 0) =>
  26. odesolve!-solns(Airy_Ai(x), Airy_Bi(x),
  27. x=a3^(1/3)*x+a2b/a3^(2/3)),
  28. %% The order of the following rules matters!
  29. %% odesolve(x^2*df(y,x,2) + x*df(y,x) - (x^2+n2)*y, y, x);
  30. odesolve!-specfn!*(-(1+~n2/x^2), 1/x)
  31. => odesolve!-solns(BesselI(n,x), BesselK(n,x),
  32. n = sqrt(n2)),
  33. %% odesolve(x^2*df(y,x,2) + x*df(y,x) + (x^2-n2)*y, y, x);
  34. odesolve!-specfn!*(1-~n2/x^2, 1/x)
  35. => odesolve!-solns(BesselJ(n,x), BesselY(n,x),
  36. n = sqrt(n2)),
  37. %% odesolve(x^2*df(y,x,2) + x*df(y,x) - (a2*x^2+n2)*y, y, x);
  38. odesolve!-specfn!*(-(~a2+~n2/x^2), 1/x)
  39. => odesolve!-solns(BesselI(n,a*x), BesselK(n,a*x),
  40. n = sqrt(n2), a = sqrt(a2)),
  41. %% odesolve(x^2*df(y,x,2) + x*df(y,x) + (a2*x^2-n2)*y, y, x);
  42. odesolve!-specfn!*(~a2-~n2/x^2, 1/x)
  43. => odesolve!-solns(BesselJ(n,a*x), BesselY(n,a*x),
  44. n = sqrt(n2), a = sqrt(a2)),
  45. %% odesolve(x*df(y,x,2) + df(y,x) - x*y, y, x);
  46. %% odesolve!-specfn!*(-1, 1/x)
  47. %% => odesolve!-solns(BesselI(0,x), BesselK(0,x)),
  48. %% odesolve(x*df(y,x,2) + df(y,x) - a2*x*y, y, x);
  49. odesolve!-specfn!*(-~a2, 1/x)
  50. => odesolve!-solns(BesselI(0,a*x), BesselK(0,a*x),
  51. a = sqrt(a2)),
  52. %% odesolve(x*df(y,x,2) + df(y,x) + x*y, y, x);
  53. %% odesolve!-specfn!*(1, 1/x)
  54. %% => odesolve!-solns(BesselJ(0,x), BesselY(0,x)),
  55. %% odesolve(x*df(y,x,2) + df(y,x) + a2*x*y, y, x);
  56. odesolve!-specfn!*(~a2, 1/x)
  57. => odesolve!-solns(BesselJ(0,a*x), BesselY(0,a*x),
  58. a = sqrt(a2))
  59. }$
  60. soln := (ode where rules); % `where' cannot produce a list!
  61. if soln neq ode then <<
  62. traceode
  63. "The reduced ODE can be solved in terms of special functions.";
  64. soln := part(soln, 1);
  65. %% if symbolic !*odesolve_load_specfn then load_package specfn;
  66. return if driver1 then
  67. %% BEWARE: This driver code is not well tested!
  68. %% traceode "But cannot currently handle the driver term! "
  69. { soln, ODESolve!-PI(soln, driver1, x) }
  70. else { soln }
  71. >>
  72. end$
  73. algebraic operator ODESolve!-Solns!*$
  74. listargp ODESolve!-Solns!*$
  75. put('ODESolve!-Solns, 'psopfn, 'ODESolve!-Solns)$
  76. symbolic procedure ODESolve!-Solns u; % (solns, subs)
  77. %% Avoid invalid lists on right of replacement rule, and build full
  78. %% optionally substituted basis data structure:
  79. begin scalar solns;
  80. %% u := revlis u;
  81. solns := {'list, car u, cadr u}; % algebraic list
  82. if (u := cddr u) then << % substitutions
  83. u := if cdr u then 'list . u else car u;
  84. solns := algebraic sub(u, solns)
  85. >>;
  86. return {'ODESolve!-Solns!*, solns}
  87. end$
  88. endmodule$
  89. end$