> restart; > #Runge-Kutta-Verfahren mit Schrittweitensteuerung für AWP y'=f(t,y), y(t0)=y0 > RungeKutta1:=proc(y0,t0,f,T,h0,maxtol,mintol) > #t0,y0,T,h Anfangsstelle, Anfangswert, Intervalllänge, Schrittweite > #f(.,.) rechte Seite der Differentialgleichung > #mintol,maxtol untere und obere Schranke für relativen Diskretisierungsfehler > local RK,t,y,u,v,w,est,fehler,h; > RK:=proc(y,t,f,h) > # ein Runge-Kutta-Schritt mit Schrittweite h > local y1,k1,k2,k3,k4; > y1:=y; > k1:=f(t,y1); > k2:=f(t+h/2,y1+k1*h/2); > k3:=f(t+h/2,y1+k2*h/2); > k4:=f(t+h,y1+k3*h); > y1:=y1+h*(k1+2*k2+2*k3+k4)/6; > RETURN(y1) > end: > t:=t0; y:=y0; h:=h0; > while t if t+h>T then h:=T-t fi; > u:=RK(y,t,f,h); # grobe Näherung für y(t+h) > w:=RK(y,t,f,h/2); # Näherung für y(t+h/2) > v:=RK(w,t+h/2,f,h/2); # bessere Näherung für y(t+h) > est:=(v-u)/15; > v:=v+est; > fehler:=abs(est)/(0.001+abs(v)); #Berechnung des geschätzten Fehlers > if fehler>maxtol then h:=h/2 else y:=v; t:=t+h; > print(t,y) fi; > if fehler end do > end: > > > #Vergleich klassisches Runge-Kutta-Verfahren: > RungeKutta:=proc(y0,t0,f,T,N) > # Schrittweite ist (T-t0)/N > local y,t,k1,k2,k3,k4,j,h; > y:=y0; t:=t0; h:=(T-t0)/N; > print(`klassisches Runge-Kutta-Verfahren:`); > for j from 0 to N-1 do > k1:=f(t,y); > k2:=f(t+h/2,y+k1*h/2); > k3:=f(t+h/2,y+k2*h/2); > t:=t+h; > k4:=f(t,y+k3*h); > y:=y+h*(k1+2*k2+2*k3+k4)/6; > print(t,y) > od > end: > > #Beispiel 1: y':=-2ty^2, y(1.0)=0.5; > f:=proc(t,y) > local g; > g:=-2*t*y^2; > RETURN(g) > end: > maxtol:=0.00001: mintol:=0.000001: > RungeKutta1(0.5,1.0,f,2.0,0.1,maxtol,mintol); > # Vergleich mit genauer Lösung > print(`genaue Lösung:`); > for j from 1 to 10 do print(1+j*0.1,evalf(1/(1+(1+j*0.1)^2))) od; > #Vergleich mit klassischem Runge-Kutta-Verfahren mit h=0.1: > RungeKutta(0.5,1.0,f,2.0,10); 1.1, .4524886868 1.3, .3717471642 1.5, .3076922435 1.7, .2570693447 2.0, .1999998612 genaue Lösung: 1.1, .4524886878 1.2, .4098360656 1.3, .3717472119 1.4, .3378378378 1.5, .3076923077 1.6, .2808988764 1.7, .2570694087 1.8, .2358490566 1.9, .2169197397 2.0, .2000000000 klassisches Runge-Kutta-Verfahren: 1.100000000, .4524889829 1.200000000, .4098365642 1.300000000, .3717478373 1.400000000, .3378385306 1.500000000, .3076930244 1.600000000, .2808995871 1.700000000, .2570700938 1.800000000, .2358497043 1.900000000, .2169203437 2.000000000, .2000005578 > >