home *** CD-ROM | disk | FTP | other *** search
- {---------------------------------------------------------------------------}
- { DGL.PAS }
- { Loesen von Differentialgleichungssystemen nach Runge-Kutta }
- {---------------------------------------------------------------------------}
-
- PROGRAM DGL_Solver;
-
- CONST nm = 5; { Max. DGL-Anzahl }
-
- TYPE Vektor = ARRAY[1..nm] OF REAL;
-
- VAR Y, Yo, dY :Vektor;
- Xstart, Xend, x, dx, h, AbsErr, ymin, ymax :REAL;
- n, i, nmax:INTEGER;
-
- {---------------------------------------------------------------------------}
- { das DGL-System ist hier zu definieren: }
-
- PROCEDURE DGL (VAR dY, Y: Vektor; x: REAL);
-
- CONST k1=0.04;
- k2=0.03;
-
- BEGIN { n DGLn der Form: }
- dY[1] := -k1*Y[1]; { dY[i] := f(x,Y[1],..,Y[n]) }
- dY[2] := k1*Y[1] - k2*Y[2];
- dY[3] := k2*Y[2]; { Folgereaktion }
- END;
-
- {---------------------------------------------------------------------------}
-
- PROCEDURE Ausgabe (VAR Y: Vektor; x, h: REAL; n, nmax: INTEGER);
-
- CONST xpos=60; ypos=10; { Bildschirmposition }
- VAR i: INTEGER;
-
- BEGIN
- FOR i:=1 TO n DO
- BEGIN
- GotoXY(xpos,ypos+i); WriteLn('Y[',i,'] =',y[i]);
- END;
- GotoXY(xpos,ypos+n+1); WriteLn('x =',x);
- GotoXY(xpos,ypos+n+2); WriteLn('h =',h);
- GotoXY(xpos,ypos+n+3); WriteLn(nmax,' Teilintervalle');
- END;
-
- {---------------------------------------------------------------------------}
-
- PROCEDURE Plot (x, y, xmin, xmax, ymin, ymax: REAL; ch:CHAR);
-
- CONST umax=78; vmax=28; { Bildschirmbreite/-hoehe }
- VAR u, v: INTEGER;
-
- BEGIN
- u := Round((x-xmin)/(xmax-xmin)*umax);
- v := vmax-Round((y-ymin)/(ymax-ymin)*vmax);
- GotoXY(u,v); Write(ch);
- END;
-
- {---------------------------------------------------------------------------}
- { das Runge-Kutta-Verfahren: }
-
- PROCEDURE RungeKutta (VAR Y, Yo:Vektor; Xstart, Xend: REAL;
- VAR h: REAL; AbsErr: REAL;
- n: INTEGER; VAR nmax: INTEGER);
-
- VAR C1, C2, C3, C4, z, dY: Vektor;
- x, xo, yalt, Tol: REAL;
- j, k: INTEGER;
-
- BEGIN
- yalt := 0; nmax := 4;
- REPEAT
- h := ABS((Xend-Xstart)/nmax); { Schrittweite }
- FOR k := 1 TO n DO Y[k] := Yo[k]; { Anfangsbedingungen }
- FOR j := 0 TO Pred(nmax) DO { Runge-Kutta-Iteration }
- BEGIN
- xo := Xstart+j*h;
- DGL(dY, Y, xo);
- FOR k := 1 TO n DO
- BEGIN
- C1[k] := h*dY[k];
- z[k] := Y[k]+C1[k]/2;
- END;
- DGL(dY, z, (xo+h/2));
- FOR k := 1 TO n DO
- BEGIN
- C2[k] := h*dY[k];
- z[k] := Y[k]+C2[k]/2;
- END;
- DGL(dY, z, (xo+h/2));
- FOR k := 1 TO n DO
- BEGIN
- C3[k] := h*dY[k];
- z[k] := Y[k]+C3[k];
- END;
- DGL(dY, z, (xo+h));
- FOR k := 1 TO n DO
- BEGIN
- C4[k] := h*dY[k];
- y[k] := y[k]+(C1[k]+2*C2[k]+2*C3[k]+C4[k])/6;
- END;
- END;
- Tol := ABS(yalt-y[1]); { Abbruchkriterium }
- nmax := nmax*2; { Teilintervalle }
- yalt := Y[1];
- UNTIL Tol <= AbsErr;
- END;
-
- {---------------------------------------------------------------------------}
-
- BEGIN { DGL_Solver }
- { Anfangsbedingungen: }
- n := 3; { Zahl der DGLn }
- Yo[1] := 2.5; { n Anfangsbedingungen der Form: }
- Yo[2] := 0.0; { Yo[i] := const }
- Yo[3] := 0.0;
- Xstart:= 0.1; { untere Integrationsgrenze }
- Xend := 120.0; { obere Integrationsgrenze }
- dx := (Xend-Xstart)/80; { x-Schrittweite }
- AbsErr:= 1.0E-3; { Absoluter Fehler }
- ymin := 0.0; { y-Ausdehnung der Graphik }
- ymax := 2.5;
-
- ClrScr;
- FOR i := 1 TO n DO Y[i] := Yo[i];
- x := Xstart;
- WHILE x <= Xend DO
- BEGIN
- FOR i := 1 TO n DO Plot(x, Y[i], Xstart, Xend, ymin, ymax, Chr(48+i));
- RungeKutta(Y, Yo, Xstart, x, h, AbsErr, n, nmax);
- Ausgabe(Y, x, h, n, nmax);
- x := x + dx;
- END;
- GotoXY(0,0);
- END.