aboutsummaryrefslogtreecommitdiff
path: root/src/algebra
diff options
context:
space:
mode:
Diffstat (limited to 'src/algebra')
-rw-r--r--src/algebra/odeef.spad.pamphlet37
1 files changed, 26 insertions, 11 deletions
diff --git a/src/algebra/odeef.spad.pamphlet b/src/algebra/odeef.spad.pamphlet
index 5598124b..37f26e8e 100644
--- a/src/algebra/odeef.spad.pamphlet
+++ b/src/algebra/odeef.spad.pamphlet
@@ -434,7 +434,7 @@ ElementaryFunctionODESolver(R, F): Exports == Implementation where
getfreelincoeff1: (F, K, List F) -> F
getlincoeff : (F, K) -> F
getcoeff : (F, K) -> UU
- parseODE : (F, OP, SY) -> Union(LEQ, NLQ)
+ parseODE : (F, OP, SY) -> Union(LEQ, NLQ, "failed")
parseLODE : (F, List K, UP, SY) -> LEQ
parseSYS : (List F, List OP, SY) -> Union(SYS, "failed")
parseSYSeq : (F, List K, List K, List F, SY) -> Union(ROW, "failed")
@@ -462,7 +462,9 @@ ElementaryFunctionODESolver(R, F): Exports == Implementation where
solve(diffeq:F, y:OP, center:EQ, y0:List F) ==
a := rhs center
kx:K := kernel(x := retract(lhs(center))@SY)
- (ur := parseODE(diffeq, y, x)) case NLQ =>
+ ur := parseODE(diffeq, y, x)
+ ur case "failed" => "failed"
+ ur case NLQ =>
not one?(#y0) => error "solve: more than one initial condition!"
rc := ur::NLQ
(u := solve(rc.dx, rc.dy, y, x)) case "failed" => "failed"
@@ -483,7 +485,9 @@ ElementaryFunctionODESolver(R, F): Exports == Implementation where
error "solve: not a first order linear system"
solve(diffeq:F, y:OP, x:SY) ==
- (u := parseODE(diffeq, y, x)) case NLQ =>
+ u := parseODE(diffeq, y, x)
+ u case "failed" => "failed"
+ u case NLQ =>
rc := u::NLQ
(uu := solve(rc.dx, rc.dy, y, x)) case "failed" => "failed"
uu::F
@@ -527,28 +531,39 @@ ElementaryFunctionODESolver(R, F): Exports == Implementation where
eq := eq - ci * y::F
[n, v, -eq]
--- returns either [p, g] where the equation (diffeq) is of the form p(D)(y) = g
--- or [p, q] such that the equation (diffeq) is of the form p dx + q dy = 0
+ -- returns either
+ -- [p, g] where the equation (diffeq) is of the form
+ -- p(D)(y) = g
+ -- or
+ -- [p, q] such that the equation (diffeq) is of the form
+ -- p dx + q dy = 0
parseODE(diffeq, y, x) ==
- f := y(x::F)
+ -- FIXME: Assume we don't have a parametric equation.
+ f := y(x::F)
l:List(K) := [retract(f)@K]
n:N := 2
for k in varselect(kernels diffeq, x) | is?(k, OPDIFF) repeat
if (m := height k) > n then n := m
n := (n - 2)::N
--- build a list of kernels in the order [y^(n)(x),...,y''(x),y'(x),y(x)]
+ -- build a list of kernels in the order [y^(n)(x),...,y''(x),y'(x),y(x)]
for i in 1..n repeat
l := concat(retract(f := differentiate(f, x))@K, l)
+ -- Determine the order of the equation and its leading coefficient
k:K -- #$^#& compiler requires this line and the next one too...
c:F
- while not(empty? l) and zero?(c := getlincoeff(diffeq, k := first l))
- repeat l := rest l
- empty? l or empty? rest l => error "parseODE: equation has order 0"
+ while not empty? l repeat
+ c' := getcoeff(diffeq, k := first l)
+ c' case "failed" => return "failed"
+ c := c'::F
+ not zero? c => break
+ l := rest l
+ empty? l or empty? rest l => "failed" -- maybe a functional equation?
diffeq := diffeq - c * (k::F)
ny := name y
l := rest l
height(k) > 3 => parseLODE(diffeq, l, monomial(c, #l), ny)
- (u := getcoeff(diffeq, k := first l)) case "failed" => [diffeq, c]
+ u := getcoeff(diffeq, k := first l)
+ u case "failed" => [diffeq, c]
eqrhs := (d := u::F) * (k::F) - diffeq
freeOf?(eqrhs, ny) and freeOf?(c, ny) and freeOf?(d, ny) =>
[monomial(c, 1) + d::UP, eqrhs]