Numerical solution of a system of first order ordinary differential equations . This is an explicit Runge-Kutta method of order 8(5,3) due to Dormand & Prince (with stepsize control and dense output).
iout=3 for sparse dense output)| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(dop853_class), | intent(inout) | :: | me | |||
| real(kind=wp), | intent(inout) | :: | x |
input: initial value of independent variable.
output: |
||
| real(kind=wp), | intent(inout), | dimension(:) | :: | y |
input: initial values for output: numerical solution at |
|
| real(kind=wp), | intent(in) | :: | xend |
final x-value ( |
||
| real(kind=wp), | intent(in), | dimension(:) | :: | rtol |
relative error tolerance. |
|
| real(kind=wp), | intent(in), | dimension(:) | :: | atol |
absolute error tolerance. |
|
| integer, | intent(in) | :: | iout |
switch for calling the subroutine
|
||
| integer, | intent(out) | :: | idid |
reports on successfulness upon return:
|
subroutine dop853(me,x,y,xend,rtol,atol,iout,idid) implicit none class(dop853_class),intent(inout) :: me real(wp),intent(inout) :: x !! *input:* initial value of independent variable. !! *output:* `x` for which the solution has been computed !! (after successful return `x=xend`). real(wp),dimension(:),intent(inout) :: y !! *input:* initial values for `y`. [size n] !! !! *output:* numerical solution at `x`. real(wp),intent(in) :: xend !! final x-value (`xend`-`x` may be positive or negative) real(wp),dimension(:),intent(in) :: rtol !! relative error tolerance. `rtol` and `atol` !! can be both scalars or else both vectors of length `n`. real(wp),dimension(:),intent(in) :: atol !! absolute error tolerance. `rtol` and `atol` !! can be both scalars or else both vectors of length `n`. !! `atol` should be strictly positive (possibly very small) integer,intent(in) :: iout !! switch for calling the subroutine `solout`: !! !! * `iout=0`: subroutine is never called !! * `iout=1`: subroutine is called after every successful step !! * `iout=2`: dense output is performed after every successful step !! * `iout=3`: dense output is performed in steps defined by the user !! (see `xout` above) integer,intent(out) :: idid !! reports on successfulness upon return: !! !! * `idid=1` computation successful, !! * `idid=2` comput. successful (interrupted by [[solout]]), !! * `idid=-1` input is not consistent, !! * `idid=-2` larger `nmax` is needed, !! * `idid=-3` step size becomes too small. !! * `idid=-4` problem is probably stiff (interrupted). real(wp) :: beta,fac1,fac2,hmax,safe integer :: i,ieco,iprint,istore,nrdens,nstiff,nmax logical :: arret integer :: itol !! switch for `rtol` and `atol`: !! !! * `itol=0`: both `rtol` and `atol` are scalars. !! the code keeps, roughly, the local error of !! `y(i)` below `rtol*abs(y(i))+atol`. !! !! * `itol=1`: both `rtol` and `atol` are vectors. !! the code keeps the local error of `y(i)` below !! `rtol(i)*abs(y(i))+atol(i)`. iprint = me%iprint me%iout = iout arret = .false. !check procedures: if (.not. associated(me%fcn)) then if ( iprint/=0 ) & write (iprint,*) & 'Error in dop853: procedure FCN is not associated.' idid = -1 return end if if (iout/=0 .and. .not. associated(me%solout)) then if ( iprint/=0 ) & write (iprint,*) & 'Error in dop853: procedure SOLOUT must be associated if IOUT/=0.' idid = -1 return end if !scalar or vector tolerances: if (size(rtol)==1 .and. size(atol)==1) then itol = 0 elseif (size(rtol)==me%n .and. size(atol)==me%n) then itol = 1 else if ( iprint/=0 ) & write (iprint,*) & 'Error in dop853: improper dimensions for rtol and/or atol.' idid = -1 return end if ! setting the parameters me%nfcn = 0 me%nstep = 0 me%naccpt = 0 me%nrejct = 0 nmax = me%nmax nrdens = me%nrdens !number of dense output components ! nstiff parameter for stiffness detection if ( me%nstiff<=0 ) then nstiff = nmax + 10 !no stiffness check else nstiff = me%nstiff end if if ( nrdens<0 .or. me%nrdens>me%n ) then if ( iprint/=0 ) write (iprint,*) ' curious input nrdens=' , nrdens arret = .true. else if ( nrdens>0 .and. iout<2 .and. iprint/=0 ) & write (iprint,*) ' warning: set iout=2 or iout=3 for dense output ' end if if (size(y)/=me%n) then if ( iprint/=0 ) & write (iprint,*) ' error: y must have n elements: size(y)= ',size(y) arret = .true. end if safe = me%safe fac1 = me%fac1 fac2 = me%fac2 beta = me%beta if ( me%hmax==0.0_wp ) then hmax = xend - x else hmax = me%hmax end if me%h = me%hinitial ! initial step size ! when a fail has occurred, we return with idid=-1 if ( arret ) then idid = -1 else ! call to core integrator call me%dp86co(x,y,xend,hmax,me%h,rtol,atol,itol,iprint, & iout,idid,nmax,nstiff,safe,beta,fac1,fac2, & me%nfcn,me%nstep,me%naccpt,me%nrejct) end if end subroutine dop853