Diff. yht. numeriikkaa

K3/p3 22.11.05

Euler, Heun, eli parannettu Euler (RK2)

Esim 1  y' = t+y

>    restart:

>    with(plots):

Warning, the name changecoords has been redefined

>    f:=(t,y)->t+y;   # Diff. yhtälön määrittelevä funktio f(t,y)

f := proc (t, y) options operator, arrow; t+y end proc

>    h:=0.4:T[0]:=0:y[0]:=0: N:=3:   # Alkuasetukset.

>    T[1]:=T[0]+h;
y[1]:=y[0]+h*f(T[0],y[0]);      # 1. Euler-askel

T[1] := .4

y[1] := 0.

>    T[2]:=T[1]+h;
y[2]:=y[1]+h*f(T[1],y[1]);      # 2. Euler-askel

T[2] := .8

y[2] := .16

Nyt riitti manuaalinen toiminta. Aloitetaan alusta ja rakennetaan  for-silmukka.

>    h:=0.4:T[0]:=0:y[0]:=0: N:=3:   # Alkuasetukset uudestaan.

>    for k from 0 to N do
  T[k+1]:=T[k]+h;
  y[k+1]:=y[k]+h*f(T[k],y[k])
end do:

>    polku1:=[seq([T[k],y[k]],k=0..N)];  # Tässä ovat pisteet [t[k],y[k]]:

polku1 := [[0, 0], [.4, 0.], [.8, .16], [1.2, .544]]

>    plot(polku1,axes =box,legend="h=0.4");

[Maple Plot]

>    Ekuva1:=%:

>    h:=h/2;T[0]:=0;y[0]:=0: N:=2*N;  # Puolitetaan askel h ja kaksinkertaistetaan N.

h := .2000000000

T[0] := 0

N := 6

>    for k from 0 to N do
  T[k+1]:=T[k]+h:
  y[k+1]:=y[k]+h*f(T[k],y[k])
end do:

>    polku2:=[seq([T[k],y[k]],k=0..N)]: plot(polku2,color=green,axes=box,legend="h=0.2"); Ekuva2:=%:

[Maple Plot]

>    h:=h/2;T[0]:=0;y[0]:=0: N:=2*N; T1:=N*h;  # Ja vielä kerran.

h := .1000000000

T[0] := 0

N := 12

T1 := 1.200000000

>    for k from 0 to N do
  T[k+1]:=T[k]+h:
  y[k+1]:=y[k]+h*f(T[k],y[k])
end do:

>    polku3:=[seq([T[k],y[k]],k=0..N)]; plot(polku3,color=blue,axes=box,legend="h=0.1"); Ekuva3:=%:

polku3 := [[0, 0], [.1000000000, 0.], [.2000000000, .1000000000e-1], [.3000000000, .3100000000e-1], [.4000000000, .6410000000e-1], [.5000000000, .1105100000], [.6000000000, .1715610000], [.7000000000, ...
polku3 := [[0, 0], [.1000000000, 0.], [.2000000000, .1000000000e-1], [.3000000000, .3100000000e-1], [.4000000000, .6410000000e-1], [.5000000000, .1105100000], [.6000000000, .1715610000], [.7000000000, ...
polku3 := [[0, 0], [.1000000000, 0.], [.2000000000, .1000000000e-1], [.3000000000, .3100000000e-1], [.4000000000, .6410000000e-1], [.5000000000, .1105100000], [.6000000000, .1715610000], [.7000000000, ...
polku3 := [[0, 0], [.1000000000, 0.], [.2000000000, .1000000000e-1], [.3000000000, .3100000000e-1], [.4000000000, .6410000000e-1], [.5000000000, .1105100000], [.6000000000, .1715610000], [.7000000000, ...

[Maple Plot]

>    display(Ekuva1,Ekuva2,Ekuva3,title="Eulerin polut");

[Maple Plot]

Katsotaan kunkin polun viimeinen y-arvo, eli ratkaisuapproksimaatio pisteessä t=1.2:

>    yLoppu[1]:=polku1[-1][2];yLoppu[2]:=polku2[-1][2];yLoppu[3]:=polku3[-1][2];

>   

yLoppu[1] := .544

yLoppu[2] := .7859840000

yLoppu[3] := .9384283767

>   

>    dsolve({diff(Y(t),t)=t+Y(t),Y(0)=0},Y(t));

Y(t) = -t-1+exp(t)

>    ytarkka:=rhs(%);

ytarkka := -t-1+exp(t)

>    display(Ekuva1,Ekuva2,Ekuva3,plot(ytarkka,t=0..1.2,color=black,legend="Tarkka ratkaisu"));

[Maple Plot]

>    ytarkka12:=eval(subs(t=1.2,ytarkka));

ytarkka12 := 1.120116923

>    virheet:=seq(ytarkka12-yLoppu[k],k=1..3);

virheet := .576116923, .3341329230, .1816885463

Aika lähellä on O(h)-käytös, eli virhe puolittuu, kun askel puolittuu.

Esim. 2   y'=t+y   Parannetulla E:lla

>    #restart:

>    with(plots):

>    f:=(t,y)->t+y;

f := proc (t, y) options operator, arrow; t+y end proc

>    h:=0.4;T[0]:=0:y[0]:=0: N:=3:

h := .4

>    for n from 0 to N-1 do
  s1:=f(T[n],y[n]);
  s2:=f(T[n]+h,y[n]+h*s1);
  y[n+1]:=y[n]+h*(s1+s2)/2;
  T[n+1]:=T[n]+h;
end do;

s1 := 0

s2 := .4

y[1] := .8000000000e-1

T[1] := .4

s1 := .4800000000

s2 := 1.072000000

y[2] := .3904000000

T[2] := .8

s1 := 1.190400000

s2 := 2.066560000

y[3] := 1.041792000

T[3] := 1.2

>    polku1:=[seq([T[k],y[k]],k=0..N)];

polku1 := [[0, 0], [.4, .8000000000e-1], [.8, .3904000000], [1.2, 1.041792000]]

>    plot(polku1,color=blue,legend="Heun, h=0.4");

[Maple Plot]

>    Hkuva1:=%:

>    display(Ekuva1,Hkuva1,title="Punainen Euler, sininen Heun");

[Maple Plot]

Eulerin ja Heunin menetelmät systeemille

Esim 1

>    restart: with(plots): with(LinearAlgebra):

Warning, the name changecoords has been redefined

>    diff(y(t),t,t)+y(t)=0;

diff(y(t),`$`(t,2))+y(t) = 0

>    A:=<<0,-1>|<1,0>>; Id:=<<1,0>|<0,1>>;

A := Matrix(%id = 2884680)

Id := Matrix(%id = 2915524)

>    Y[0]:=<-1,0>;

Y[0] := Vector(%id = 3033508)

>    h:=0.1: N:=ceil(2*Pi/h);

N := 63

>    for k from 0 to N do
 Y[k+1]:=(Id+h*A).Y[k];
end do:

>    polku1:=[seq(convert(Y[k],list),k=0..N)]: polku1[1..4];

>   

[[-1, 0], [-1., .100000000000000004], [-.989999999999999990, .200000000000000010], [-.969999999999999974, .299000000000000042]]
[[-1, 0], [-1., .100000000000000004], [-.989999999999999990, .200000000000000010], [-.969999999999999974, .299000000000000042]]

>    display(plot(polku1,color=blue),complexplot(exp(I*t),t=0..2*Pi),scaling=constrained);

[Maple Plot]

>   

>    h:=h/2: N:=ceil(2*Pi/h);

N := 126

>    for k from 0 to N do
 Y[k+1]:=(Id+h*A).Y[k];
end do:

>    polku2:=[seq(convert(Y[k],list),k=0..N)]:

>   

>    display(plot(polku2,color=blue),complexplot(exp(I*t),t=0..2*Pi),scaling=constrained);

[Maple Plot]

On luonnollista, että Euler on huono ympyrälle ja yleisemmin keskus-tyypille (kuten kettu-jänis). Joka askeleella virhe menee samaan suuntaan,

kun itsepintaisesti mennään tangentin suuntaan. Ajaudutaan väkisin ulospäin menevälle spiraalille.

Sama Heunin menetelmällä

>    h:=0.4: N:=ceil(2*Pi/h);

N := 16

>    for n from 0 to N do
 Ytahti:=(Id+h*A).Y[n];
 K:=1/2*A.(Y[n]+Ytahti);
 Y[n+1]:=Y[n]+h*K;
end do:

>    polku1:=[seq(convert(Y[k],list),k=0..N)]:

>   

>    display(plot(polku1,color=blue),complexplot(exp(I*t),t=0..2*Pi),scaling=constrained);

[Maple Plot]

>    h:=0.2: N:=ceil(2*Pi/h);

N := 32

>    for n from 0 to N do
 Ytahti:=(Id+h*A).Y[n];
 K:=1/2*A.(Y[n]+Ytahti);
 Y[n+1]:=Y[n]+h*K;
end do:

>    polku1:=[seq(convert(Y[k],list),k=0..N)]:

>   

>    display(plot(polku1,color=blue),complexplot(exp(I*t),t=0..2*Pi),scaling=constrained);

[Maple Plot]

>   

Askeleella h=0.2  saadaan jo kuvan tarkkuudella miltei tarkka. Huomattava parannus. Mitä sitten tuokaan Runge-Kutta? (Harj. teht.)