home *** CD-ROM | disk | FTP | other *** search
-
- (* :Name: NumericalMath`Butcher` *)
-
- (* :Title: Runge-Kutta Order Conditions *)
-
- (* :Author: Jerry B. Keiper *)
-
- (* :Summary:
- Gives the order conditions which any Runge-Kutta method must
- satisfy to be of any particular order. Works for both implicit
- and explicit methods.
- *)
-
- (* :Context: NumericalMath`Butcher` *)
-
- (* :Package Version: 2.0 *)
-
- (* :Copyright: Copyright 1990, Wolfram Research, Inc.
-
- Permission is hereby granted to modify and/or make copies of
- this file for any purpose other than direct profit, or as part
- of a commercial product, provided this copyright notice is left
- intact. Sale, other than for the cost of media, is prohibited.
-
- Permission is hereby granted to reproduce part or all of
- this file, provided that the source is acknowledged.
- *)
-
- (* :History:
- Updated by Jerry B. Keiper, December, 1990.
- Version 1.2 by Jerry B. Keiper, 1989.
- *)
-
- (* :Keywords:
- Butcher trees, Runge-Kutta, order conditions
- *)
-
- (* :Source:
- John C. Butcher: The Numerical Analysis of Ordinary Differential
- Equations: Runge-Kutta and General Linear Methods, John Wiley &
- Sons, New York, 1987
- *)
-
- (* :Mathematica Version: 2.0 *)
-
- (* :Limitation:
- This package only finds the order conditions; it does not try
- to solve them for the required coefficients.
-
- Combinatorial explosion effectively limits the order for which
- order conditions can be found, e.g., 7813 (highly nonlinear)
- conditions are required for a 12th-order method.
-
- This is a rather rudimentary package and could be improved
- considerably. The functions r (order), gamma (density),
- and phi are defined as private functions and could be exposed
- to the user. Furthermore, tools for aiding in the solution
- of the order conditions could be useful.
- *)
-
- (* :Warnings:
- Derivative is unprotected so that rules can be attached to it.
- It is protected after.
- *)
-
- (* :Discussion:
- The method is due to John C. Butcher and is explained in chapter
- 3 of Butcher's book. It relies heavily on graph theory and
- recursive decomposition of Butcher trees. Pattern matching is
- used extensively.
- *)
-
- BeginPackage["NumericalMath`Butcher`"];
-
- RungeKuttaOrderConditions::usage =
- "RungeKuttaOrderConditions[p, s] gives a list of the order conditions that
- any s-stage Runge-Kutta method of order p must satisfy. These conditions are
- expressed in terms of the global variables a, b, c, and the resulting
- Runge-Kutta method is\n
- \n
- Y[i,x] = y[x0] + (x - x0) Sum[a[i,j] f[Y[j,x]], {j, 1, s}], i = 1, ..., s\n
- \n
- Y[x] = y[x0] + (x - x0) Sum[b[j] f[Y[j,x]], {j, 1, s}]\n
- \n
- where c[i] == Sum[a[i, j], {j, 1, s}]."
-
- a::usage =
- "a[i,j] is the coefficient of f[Y[j, x]] in the formula for Y[i, x] for the
- Runge-Kutta method being considered."
-
- b::usage =
- "b[j] is the coefficient of f[Y[j, x]] in the formula for Y[x] for the
- Runge-Kutta method being considered."
-
- c::usage =
- "c[i] is a notational convenience representing Sum[a[i, j], {j, 1, s}] in
- the order conditions for the Runge-Kutta method being considered."
-
- Begin["NumericalMath`Butcher`Private`"];
-
- (* Attach rules to Derivative must unprotect it *)
- Unprotect[ Derivative]
-
- (* general rules for ' *)
- (a_Integer)' := 0;
- (a_ + b_)' := a' + b';
- (a_ b_)' := Expand[a' b + a b'];
- (a_^n_)' := Expand[n a^(n-1) a'];
-
- (* rules for recursively evaluating y', y'', y''', ...
- note: derivatives of f are implicit in the number of arguments it has. *)
- y' = f;
- f' = f[f];
- (f[g_])' := (f[g])' = f[Expand[g f]] + f[g'];
-
- (* make f multi-linear. *)
- f[a_ + b_] := f[a] + f[b];
- f[n_Integer a_] := n f[a];
-
- (* rewrite a derivative of y as the list of trees appearing in the expression. *)
- trees[f] = {f};
- trees[f[f]] = {f[f]};
- trees[a_Plus] := Apply[List, Map[trees, a]]
- trees[n_. a_f] := a
-
- (* define the order of a tree. *)
- r[t_f] := (r[t] = 1 + Map[r, Apply[Plus, t[[1]]]]) /; Head[t[[1]]] === Times;
- r[t_f] := r[t] = 1 + r[t[[1]]];
- r[f^n_.] := n;
- r[(t_f)^n_Integer] := r[t^n] = n r[t];
-
- (* define the density of a tree. *)
- gamma[t_f] := (gamma[t] = r[t] Map[gamma, t[[1]]]) /; Head[t[[1]]] === Times;
- gamma[t_f] := gamma[t] = r[t] gamma[t[[1]]];
- gamma[f^n_.] = 1;
- gamma[(t_f)^n_Integer] := gamma[t]^n;
-
- (* the function phi is more complicated, since we need bookkeeping for the
- various indices of summation. The argument s must be an integer and is
- the upper bound of the summation in the order conditions.
- phi[l, s, forest] recursively produces a list containing the largest
- summation variable needed for that forest and those factors associated
- with the subtree rooted at vertex l and having as its own subtrees those
- listed in forest. phi[l, s, tree] does the same except it is for a
- single subtree that appears in the forest. *)
-
- (* find the list of subtrees (one level up) of a tree. *)
- split[tree_f] :=
- Module[{i, j, sub = tree[[1]]},
- sub = If[Head[sub] === Times, Apply[List, sub], {sub}];
- Do[If[Head[sub[[i]]] === Power,
- sub[[i]] = Table[sub[[i, 1]], {j, sub[[i, 2]]}]],
- {i, Length[sub]}];
- Flatten[sub]
- ];
-
- (* special case for the tree with one vertex. *)
- phi[s_, f] = Sum[b[i[0]], {i[0], s}];
-
- (* special case for the root of the tree. *)
- phi[s_, tree_f] :=
- Module[{prod, j, k, ranges},
- prod = phi[0, s, split[tree]];
- k = prod[[1]];
- prod = b[i[0]] prod[[2]];
- ranges = Table[{i[j], s}, {j, 0, k}];
- Apply[Sum, Prepend[ranges, prod]]
- ];
-
- (* a forest of sub-trees. *)
- phi[l_, s_, forest_List] :=
- Module[{j, k=l, prod = 1, temp},
- Do[ temp = phi[k, s, forest[[j]]];
- prod *= temp[[2]];
- k = temp[[1]],
- {j, Length[forest]}];
- {k, prod}
- ];
-
- (* special case for a leaf. *)
- phi[l_, s_, f] := {l, c[i[l]]};
-
- (* a single subtree. *)
- phi[l_, s_, tree_f] :=
- Module[{temp},
- temp = phi[l+1, s, split[tree]];
- {temp[[1]], a[i[l], i[l+1]] temp[[2]]}
- ];
-
- RungeKuttaOrderConditions[p_, s_] :=
- Module[{treelist, gammalist, i, yder},
- yder = y;
- treelist = {};
- Do[treelist = Join[treelist, trees[yder = yder']], {i,p}];
- gammalist = 1/Map[gamma, treelist];
- Map[Apply[Equal, #]&,
- Transpose[{Map[phi[s, #]&, treelist], gammalist}]]
- ]
-
- End[ ]; (* "NumericalMath`Butcher`Private`" *)
-
- Protect[RungeKuttaOrderConditions, a, b, c];
-
- EndPackage[ ]; (* "NumericalMath`Butcher`" *)
-
-