1 # $Id: rk4.tcl,v 1.5 2009-11-15 23:00:37 villate Exp $
3 # Copyright (C) 2008 Jaime E. Villate <villate@fe.up.pt>
5 # Fourth order Runge-Kutta method, with fixed-lenght steps in phase space.
6 # Based on Rk.tcl by William F. Schelter
7 # (the license information can be found in COPYING.tcl)
9 proc fieldlines
{ f g t0 x0 y0 sx sy nsteps dir
} {
16 while { [incr nsteps
-1] >= 0 } {
17 set kn1
[$f $tn $xn $yn]
18 set ln1
[$g $tn $xn $yn]
20 set h
[expr {$dir/[vectorlength
[expr {$kn1/$sx}] [expr {$ln1/$sy}]]}]
21 set h2
[expr {$h / 2.0 }]
22 set h6
[expr {$h / 6.0 }]
24 set arg
[list [expr {$tn + $h2}] [expr {$xn + $h2 * $kn1}] [expr {$yn + $h2*$ln1}]]
25 set kn2
[eval $f $arg]
26 set ln2
[eval $g $arg]
28 set arg
[list [expr {$tn + $h2}] [expr {$xn + $h2 * $kn2}] [expr {$yn +$h2*$ln2}]]
29 set kn3
[eval $f $arg]
30 set ln3
[eval $g $arg]
32 set arg
[list [expr {$tn + $h}] [expr {$xn + $h * $kn3}] [expr {$yn + $h*$ln3}]]
33 set kn4
[eval $f $arg]
34 set ln4
[eval $g $arg]
36 set dx
[expr {$h6 * ($kn1+2*$kn2+2*$kn3+$kn4)}]
37 set dy
[expr {$h6 * ($ln1+2*$ln2+2*$ln3+$ln4)}]
39 if { [vectorlength
$dx $dy] > 5*[vectorlength
$sx $sy] } { return $ans }
40 set xn
[expr {$xn + $dx}]
41 set yn
[expr {$yn + $dy}]
42 set tn
[expr {$tn + $h}]
44 lappend ans
$tn $xn $yn
50 proc curves
{ f g t0 x0 y0 sx sy nsteps dir
} {
57 while { [incr nsteps
-1] >= 0 } {
58 set kn1
[expr -1*[$g $tn $xn $yn] ]
59 set ln1
[$f $tn $xn $yn]
61 set h
[expr {$dir/[vectorlength
[expr {$kn1/$sx}] [expr {$ln1/$sy}]]}]
62 set h2
[expr {$h / 2.0 }]
63 set h6
[expr {$h / 6.0 }]
65 set arg
[list [expr {$tn + $h2}] [expr {$xn + $h2 * $kn1}] [expr {$yn + $h2*$ln1}]]
66 set kn2
[expr -1*[eval $g $arg] ]
67 set ln2
[eval $f $arg]
69 set arg
[list [expr {$tn + $h2}] [expr {$xn + $h2 * $kn2}] [expr {$yn +$h2*$ln2}]]
70 set kn3
[expr -1*[eval $g $arg] ]
71 set ln3
[eval $f $arg]
73 set arg
[list [expr {$tn + $h}] [expr {$xn + $h * $kn3}] [expr {$yn + $h*$ln3}]]
74 set kn4
[expr -1*[eval $g $arg] ]
75 set ln4
[eval $f $arg]
77 set dx
[expr {$h6 * ($kn1+2*$kn2+2*$kn3+$kn4)}]
78 set dy
[expr {$h6 * ($ln1+2*$ln2+2*$ln3+$ln4)}]
80 if { [vectorlength
$dx $dy] > 5*[vectorlength
$sx $sy] } { return $ans }
81 set xn
[expr {$xn + $dx}]
82 set yn
[expr {$yn + $dy}]
83 set tn
[expr {$tn + $h}]
85 lappend ans
$tn $xn $yn