Compute the new step size using the specific method.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
class(stepsize_class), | intent(in) | :: | me | |||
real(kind=wp), | intent(in) | :: | h |
current step size (<>0) |
||
real(kind=wp), | intent(in) | :: | tol |
abs error tolerance (>0) |
||
real(kind=wp), | intent(in) | :: | err |
truncation error estimate (>0) |
||
integer, | intent(in) | :: | p |
order of the method |
||
real(kind=wp), | intent(out) | :: | hnew |
new step size (<>0) |
||
logical, | intent(out) | :: | accept |
if the step is accepted |
pure subroutine compute_stepsize(me,h,tol,err,p,hnew,accept) !! Compute the new step size using the specific method. implicit none class(stepsize_class),intent(in) :: me real(wp),intent(in) :: h !! current step size (<>0) real(wp),intent(in) :: tol !! abs error tolerance (>0) real(wp),intent(in) :: err !! truncation error estimate (>0) integer,intent(in) :: p !! order of the method real(wp),intent(out) :: hnew !! new step size (<>0) logical,intent(out) :: accept !! if the step is accepted real(wp) :: hfactor !! step size factor (>0) real(wp),parameter :: small = ten * epsilon(one) !! small error value if (err<=small) then ! the error is extremely small hfactor = me%hfactor_accept accept = .true. else ! compute base factor based on the selected formula: !hfactor = abs(me%compute_h_factor(h,tol,err,p)) if (me%relative_err) then hfactor = abs( me%safety_factor*abs(tol*h/err)**(one/real(p+me%p_exponent_offset,wp)) ) else hfactor = abs( me%safety_factor*abs(tol/err)**(one/real(p+me%p_exponent_offset,wp)) ) end if ! if the step is to be accepted: select case (me%accept_mode) case(1) !algorithm 17.12 accept = (hfactor>=one) case(2) !algorithm 17.13 accept = (err<=tol) end select !...notes: ! see: L. Shampine "Some Practical Runge-Kutta Formulas", ! Mathematics of Computation, 46(173), Jan 1986. ! different conditions for satisfying error conditions: ! ||err|| <= tol -- Error per step (EPS) ! ||err|| <= h*tol -- Error per unit step (EPUS) !compute the actual hfactor based on the limits: if (accept) then hfactor = min(me%hfactor_accept, hfactor) else hfactor = max(me%hfactor_reject, hfactor) end if end if ! compute the new step size (enforce min/max bounds & add sign): hnew = sign(max(me%hmin,min(me%hmax,abs(h)*hfactor)),h) end subroutine compute_stepsize