On Mon, Aug 25, 2008 at 12:55 AM, Jason Merrill <[EMAIL PROTECTED]> wrote:
>
> In hopes that it may be a useful reference during the current work on
> symbolics, I wrote a toy Mathematica program for transforming a single
> higher order ODE into a system of first order ODEs.  Most of the free
> numerical differential equation solvers I've seen want input in the
> form y'[x] == f(y,x), so the purpose of a program like this is to take
> more general input and turn it into something suitable for those
> routines.
>
> I'll use the Poisson-Boltzmann equation in spherical coordinates, a
> second order ODE, as my test example, because I recently needed to
> solve it numerically.
>
> pbe = r^2 p''[r] + 2 r p'[r] == r^2 k^2 Sinh[p[r]]
>
> The full form of the equation, which is useful for pattern matching,
> is
>
> FullForm[pbe]
>
> Equal[Plus[Times[2,r,Derivative[1][p][r]],Times[Power[r,
> 2],Derivative[2][p][r]]],Times[Power[k,2],Power[r,2],Sinh[p[r]]]]
>
> Notice how this looks a lot like Lisp?
>
> First, I want to find out what the order of the equation is, so I will
> match any terms of the form Derivative[o][p][r], and then find the
> match with the maximum o:
>
> diffEqOrder[eqn_, y_, x_] :=
>  Max[Cases[pbe, Derivative[o_][y][x] -> o, Infinity]]
>
> Cases produces a list of all the subexpressions in its first argument
> that match the pattern specified in the second argument, optionally
> with a replacement rule applied to the matches.  By default, it only
> looks at the top level of an expression, but setting the final
> argument to Infinity forces it to look all the way down the tree.  The
> _ here is a wildcard that matches any expression, and writing o_ gives
> that subexpression a name.  Since o is the only part I care about, I
> replace all the matches with just o.
>
> diffEqOrder[pbe, p, r]
> 2
>
> Now we're ready for the function that actually transforms equations:
>
> firstOrderForm[eqn_, y_, x_] :=
>  Module[{rep, order = diffEqOrder[eqn, y, x]},
>  rep = Solve[
>    eqn /. {Derivative[o_][y][x] -> y[o][x], y[x] -> y[0][x]},
>    y[order][x]];
>  Join[Table[y'[o][x] == y[o + 1][x], {o, 0, order - 2}],
>   y'[order - 1][x] == y[order][x] /. rep]
>  ]
>
> The Module bit is just for keeping variables used in the definition
> out of global scope.  The important line is
>
> eqn /. {Derivative[o_][y][x] -> y[o][x], y[x] -> y[0][x]}
>
> where I use the replacement operator /. to replace all the derivatives
> of y with respect to x by a new function of x, y[o][x], where o is
> again the order of the derivative.  Once I've done that, I solve the
> equation for the highest order term.  Then I make a list basically
> just giving definitions of all the new functions as derivatives of the
> next lower order functions, and stick the solved highest order
> derivative equation on the end of the list.
>
> Here's the result for the example equation
>
> firstOrderForm[pbe, p, r]
>
> {p'[0][r] == p[1][r], p'[1][r] == (k^2 r Sinh[p[0][r]] - 2 p[1][r])/r}
>
> It's just a short shot from here to providing the input in a form that
> would be accepted by the gsl solver, or scipy.
>
> Hopefully this will be useful as one example of the kind of
> manipulations that pattern matching makes possible.  I'm happy to
> answer any more questions about it.

Thanks for doing this. It is indeed very useful, I always wondered how
things like this are done in Mathematica.

Any ideas how this could be nicely translated to Python?

Ondrej

--~--~---------~--~----~------------~-------~--~----~
To post to this group, send email to sage-devel@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at http://groups.google.com/group/sage-devel
URLs: http://www.sagemath.org
-~----------~----~----~----~------~----~------~--~---

Reply via email to