|
|
◆ Dopri5()
| Sub Dopri5 |
( |
N As |
Long, |
|
|
F As |
LongPtr, |
|
|
T As |
Double, |
|
|
Y() As |
Double, |
|
|
Tout As |
Double, |
|
|
RTol() As |
Double, |
|
|
ATol() As |
Double, |
|
|
Info As |
Long, |
|
|
Optional Solout As |
LongPtr = NullPtr, |
|
|
Optional Neval As |
Long, |
|
|
Optional Nstep As |
Long, |
|
|
Optional Naccept As |
Long, |
|
|
Optional Nreject As |
Long, |
|
|
Optional Hinit As |
Double = 0, |
|
|
Optional Hmax As |
Double = 0, |
|
|
Optional MaxIter As |
Long = 0, |
|
|
Optional Nstiff As |
Long = 0, |
|
|
Optional Safe As |
Double = 0, |
|
|
Optional Fac1 As |
Double = 0, |
|
|
Optional Fac2 As |
Double = 0, |
|
|
Optional Beta As |
Double = 0, |
|
|
Optional Cnt As |
Long = 0 |
|
) |
| |
Initial value problem of ordinary differential equations (5(4)-th order Dorman-Prince method)
NOTE - THIS PROGRAM IS DEPRECATED AND WILL BE REMOVED IN THE NEXT VERSION.
- Purpose
- This routine integrates a system of first order ordinary differential equations of the form
dy/dt = f(t, y), y = y0 at t = t0
where t0 and y0 are the given initial values of t and y, respectively. y may be a vector if the above is a system of differential equations.
Dopri5 is the explicit Runge-Kutta code based on the 5(4)-th order Dormand-Prince method. It is provided with the step control algorithm and the dense output feature. It is still efficient even if the number of output points becomes very large.
See for details in the reference below.
- Parameters
-
| [in] | N | Number of differential equations. (N >= 1) |
| [in] | F | The user supplied subroutine, which calculates the derivatives of the differential equations, defined as follows. Sub F(N As Long, T As Double, Y() As Double, Yp() As Double)
Yp(i) = computed derivative at given T and Y() (i = 0 to N-1)
End Sub
where N is the number of equations, and Yp() is the computed derivatives at given T and Y(), i.e. Yp(i) = dyi/dt = fi(T, Y(0), ..., Y(N-1)) (i = 0 to N-1). The other variables than Yp() should not be altered. |
| [in,out] | T | This routine integrates from T to Tout. The initial point of the integration is to be given, and the last point of the final step will be returned.
[in] Initial value of the independent variable T.
[out] Last value of the independent variable T of the final step (normally equals to Tout). The solution was successfully advanced to this point. It is possible to continue the integration to new point by recalling this routine with the new Tout value with setting Info = 1. |
| [in,out] | Y() | Array Y(LY - 1) (LY >= N)
[in] Initial values of the dependent variables Y() at initial T.
[out] Computed solution approximation at last T (normally equals to Tout). |
| [in] | Tout | Set Tout to the point at which a solution is desired. Integration either forward in T (Tout > T) or backward in T (Tout < T) is permitted.
The routine advances the solution from T to Tout using step sizes which are automatically selected so as to achieve the desired accuracy. |
| [in] | RTol() | Array RTol(LRTol - 1) (LRTol >= 1) (all components of RTol() >= 0)
The relative error tolerance(s) to tell the code how accurately you want the solution to be computed. This parameter may be a scalar (LRTol = 1) or a vector (LRTol = N). If LRTol = 2, ... or N-1, LRTol = 1 is assumed. If LRTol > N, LRTol = N is assumed. Even if LRTol = N, it is assumed to be 1 if LATol = 1.
The tolerances are used by the code in a local error test at each step which requires roughly that
abs(local error of Y(i)) <= RTol(i)*abs(Y(i)) + ATol(i)
for each component of Y() (i = 0 to LRTol-1).
Setting RTol(i) = 0 results in a pure absolute error test on that component. RTol(i) and ATol(i) should not be zero at the same time (i = 0 to LRTol-1). |
| [in] | ATol() | Array ATol(LATol - 1) (LATol >= 1) (all components of ATol() >= 0)
The absolute error tolerance(s) to tell the code how accurately you want the solution to be computed. This parameter may be a scalar (LATol = 1) or a vector (LATol = N). If LATol = 2, ... or N-1, LATol = 1 is assumed. If LATol > N, LATol = N is assumed. Even if LATol = N, it is assumed to be 1 if LRTol = 1.
The tolerances are used by the code in a local error test at each step which requires roughly that
abs(local error of Y(i)) <= RTol(i)*abs(Y(i)) + ATol(i)
for each component of Y() (i = 0 to LATol-1).
Setting ATol(i) = 0 results in a pure relative error test on that component. RTol(i) and ATol(i) should not be zero at the same time (i = 0 to LRTol-1). |
| [in,out] | Info | [in]
= 0: Initialize and start computation (Solve new problem).
= 1: Continue computation with new Tout value (Resume computation of previous call).
[out]
= -1: The argument N had an illegal value. (N < 1)
= -4: The argument Y() is invalid.
= -6: The argument RTol() had an illegal value. (RTol(i) < 0, RTol(i) = 0 and ATol(i) = 0)
= -7: The argument ATol() had an illegal value. (ATol(i) < 0)
= -8: the argument Info had an illegal value (Info <> 0 and Info <> 1)
= 1: Successful exit.
= 2: Interrupted by Solout (normal return).
= 11: Maximum number of steps exceeded.
= 12: Step size becomes too small.
= 13: Problem is probably stiff (interrupted). |
| [in] | Solout | (Optional)
The user supplied subroutine to print out the intermediate solutions, which is called after every successful step, defined as follows. (default = NullPtr) Sub Solout(Nr As Long, Told As Double, T As Double, Y() As Double, N As Long, RCont As Double, ICont As Long, Irtrn As Long)
Output the Y() values at Nr-th step T.
Told is the previous value of T. N is the order of equations.
The value of Irtrn will be 0, 1 or 2 in the first, intermediate or last call of Solout, respectively.
Irtrn also serves to interrupt the integration. If Irtrn is set to the negative value in Solout, the integration will be interrupted and exit with Info = 2.
If the numerical solution is altered in Solout, set Irtrn = 3.
Dense output is supported by the control information RCont and ICont.
The solution Y(i) (0 <= i <= N-1) at the arbitrary point T2 in the interval [Told, T] can be computed by the function call
Y(i) = Contd5(i, T2, RCont, ICont)
End Sub
Function Contd5(I As Long, T As Double, RCont As Double, ICont As Long) As Double Initial value problem of ordinary differential equations (5(4)-th order Dorman-Prince method) (Interp...
If Solout is not provided (if Solout = NullPtr), the intermediate solutions will not be printed out. |
| [out] | Neval | (Optional)
Number of function evaluations. |
| [out] | Nstep | (Optional)
Number of computed steps. |
| [out] | Naccept | (Optional)
Number of accepted steps. |
| [out] | Nreject | (Optional)
Number of rejected steps. (Step rejections in the first step are not counted) |
| [in] | Hinit | (Optional)
Initial step size. (default = to be estimated from the initial function values)
(If Hinit = 0, the default value will be used) |
| [in] | Hmax | (Optional)
Maximal step size. (default = Tout - T)
(If Hmax = 0, the default value will be used) |
| [in] | MaxIter | (Optional)
Maximum number of allowed steps. (default = 100000)
(If MaxIter <= 0, the default value will be used) |
| [in] | Nstiff | (Optional)
Test for stiffness is activated after every Nstiff steps. (default = 1000)
If Nstiff < 0, the stiffness test is not activated.
(If Nstiff = 0, the default value will be used) |
| [in] | Safe | (Optional)
The safety factor in step size prediction. (0.0001 < Safe < 1) (default = 0.9)
(If Safe <= 0.0001 or Safe >= 1, the default value will be used) |
| [in] | Fac1 | (Optional) |
| [in] | Fac2 | (Optional)
Parameters for step size selection. (default: Fac1 = 0.2, Fac2 = 10)
The new step size is chosen subject to the restriction
Fac1 <= Hnew/Hold <= Fac2.
(If Fac1 = 0 or Fac2 = 0, the default values will be used) |
| [in] | Beta | (Optional)
The parameter for the stabilized step size control. (Beta <= 0.2) (default = 0.04)
(If Beta < 0 or Beta > 0.2, 0 is assumed) |
| [in] | Cnt | (Optional)
Specifies when Neval, Nstep, Naccept and Nreject are reset to zero. (default = 0)
= 0: Reset whenever this routine is called.
<> 0: Reset only if this routine is called with Info = 0. |
- Reference
- E. Hairer, S.P. Norsett and G. Wanner, "Solving Ordinary Differential Equations. Nonstiff Problems. 2nd edition", Springer Series in Computational Mathematics, Springer-Verlag (1993)
- Example Program (1)
- Solve the following initial value problem of ordinary differential equations.
dy1/dt = -2*y1 + y2 - cos(t)
dy2/dt = 2*y1 - 3*y2 + 3*cos(t) - sin(t)
(y1 = 1, y2 = 2 at t = 0)
Sub F1(N As Long, T As Double, Y() As Double, Yp() As Double)
Yp(0) = -2 * Y(0) + Y(1) - Cos(T)
Yp(1) = 2 * Y(0) - 3 * Y(1) + 3 * Cos(T) - Sin(T)
End Sub
Sub Ex_Dopri5()
Const N = 2
Dim T As Double, Y(N - 1) As Double, Tend As Double, Tout As Double
Dim RTol(0) As Double, ATol(0) As Double, Info As Long, I As Long
RTol(0) = 0.0000000001 '1.0e-10
ATol(0) = RTol(0)
T = 0: Tend = 10: Y(0) = 1: Y(1) = 2
Info = 0
Do
Tout = T + 1
Call Dopri5(N, AddressOf F1, T, Y(), Tout, RTol(), ATol(), Info)
If Info <> 1 Then
Debug.Print "Error in Dopri5: Info =", Info
Exit Do
End If
Debug.Print T, Y(0), Y(1)
Loop While Tout < Tend
End Sub
Sub Dopri5(N As Long, F As LongPtr, T As Double, Y() As Double, Tout As Double, RTol() As Double, ATol() As Double, Info As Long, Optional Solout As LongPtr=NullPtr, Optional Neval As Long, Optional Nstep As Long, Optional Naccept As Long, Optional Nreject As Long, Optional Hinit As Double=0, Optional Hmax As Double=0, Optional MaxIter As Long=0, Optional Nstiff As Long=0, Optional Safe As Double=0, Optional Fac1 As Double=0, Optional Fac2 As Double=0, Optional Beta As Double=0, Optional Cnt As Long=0) Initial value problem of ordinary differential equations (5(4)-th order Dorman-Prince method)
- Example Results
1 0.367879441193688 0.908181746995853
2 0.13533528322734 -0.280811553289576
3 4.97870683500648E-02 -0.940205428195432
4 1.83156388723754E-02 -0.635327981941068
5 6.73794700675574E-03 0.290400132447405
6 2.4787521939019E-03 0.962649038792233
7 9.1188198233568E-04 0.75481413627468
8 3.35462627424841E-04 -0.145164571180089
9 1.2340978747767E-04 -0.911006852047013
10 4.53999120696984E-05 -0.839026129110666
- Example Program (2)
- Solve the following initial value problem of ordinary differential equations (using dense output).
dy1/dt = -2*y1 + y2 - cos(t)
dy2/dt = 2*y1 - 3*y2 + 3*cos(t) - sin(t)
(y1 = 1, y2 = 2 at t = 0)
Sub F1(N As Long, T As Double, Y() As Double, Yp() As Double)
Yp(0) = -2 * Y(0) + Y(1) - Cos(T)
Yp(1) = 2 * Y(0) - 3 * Y(1) + 3 * Cos(T) - Sin(T)
End Sub
Sub Ex_Dopri5_2()
Const N = 2
Dim T As Double, Y(N - 1) As Double, Tend As Double
Dim RTol(0) As Double, ATol(0) As Double, Info As Long, I As Long
RTol(0) = 0.0000000001 '1.0e-10
ATol(0) = RTol(0)
T = 0: Tend = 10: Y(0) = 1: Y(1) = 2
Info = 0
Call Dopri5(N, AddressOf F1, T, Y(), Tend, RTol(), ATol(), Info, AddressOf SoloutD5)
If Info <> 1 Then Debug.Print "Error in Dopri5: Info =", Info
End Sub
Sub SoloutD5(Nr As Long, Told As Double, T As Double, Y() As Double, N As Long, RCont As Double, ICont As Long, rtrn As Long)
Dim Y0 As Double, Y1 As Double
Static Tout As Double
If Nr = 1 Then Tout = 1
While T >= Tout
Y0 = Contd5(0, Tout, RCont, ICont)
Y1 = Contd5(1, Tout, RCont, ICont)
Debug.Print Tout, Y0, Y1
Tout = Tout + 1
Wend
End Sub
- Example Results
1 0.367879441187881 0.908181747006775
2 0.135335283237205 -0.280811553309717
3 4.97870683667704E-02 -0.940205428229821
4 1.83156388900869E-02 -0.635327981977462
5 6.73794699879586E-03 0.290400132463192
6 2.47875219132359E-03 0.962649038797553
7 9.11881968405946E-04 0.754814136303386
8 3.3546265009956E-04 -0.145164571227014
9 1.23409786683808E-04 -0.911006852045392
10 4.53999126645588E-05 -0.83902612911184
|