ddeabm_initialize Subroutine

private subroutine ddeabm_initialize(me, neq, maxnum, df, rtol, atol, report, initial_step_mode, initial_step_size, max_step_size, max_order)

Initialize the ddeabm_class, and set the variables that cannot be changed during a problem.

Type Bound

ddeabm_class

Arguments

Type IntentOptional Attributes Name
class(ddeabm_class), intent(inout) :: me
integer, intent(in) :: neq

number of equations to be integrated

integer, intent(in) :: maxnum

maximum number of integration steps allowed

procedure(deriv_func) :: df

derivative function dx/dt

real(kind=wp), intent(in), dimension(:) :: rtol

relative tolerance for integration (see ddeabm)

real(kind=wp), intent(in), dimension(:) :: atol

absolution tolerance for integration (see ddeabm)

procedure(report_func), optional :: report

reporting function

integer, intent(in), optional :: initial_step_mode

how to choose the initial step h:

  1. Use dhstrt.
  2. Use the older (quicker) algorithm.
  3. Use the user-specified value initial_step_size (>0).
real(kind=wp), intent(in), optional :: initial_step_size

for initial_step_mode=3

real(kind=wp), intent(in), optional :: max_step_size

maximum step size magnitude (>0). If not present, the step size is not limited.

integer, intent(in), optional :: max_order

maximum order of the method (1 to ddeabm_max_order_limit). If not present, ddeabm_default_max_order (12) is used. A lower value can improve stability on some problems. A higher value can reduce the number of steps for very tight tolerances when using higher precision (REAL128).


Calls

proc~~ddeabm_initialize~~CallsGraph proc~ddeabm_initialize ddeabm_class%ddeabm_initialize proc~destroy_ddeabm ddeabm_class%destroy_ddeabm proc~ddeabm_initialize->proc~destroy_ddeabm

Called by

proc~~ddeabm_initialize~~CalledByGraph proc~ddeabm_initialize ddeabm_class%ddeabm_initialize proc~ddeabm_with_event_initialize ddeabm_with_event_class%ddeabm_with_event_initialize proc~ddeabm_with_event_initialize->proc~ddeabm_initialize proc~ddeabm_with_event_initialize_vec ddeabm_with_event_class_vec%ddeabm_with_event_initialize_vec proc~ddeabm_with_event_initialize_vec->proc~ddeabm_initialize

Source Code

   subroutine ddeabm_initialize(me, neq, maxnum, df, rtol, atol, report, initial_step_mode, initial_step_size, &
                                max_step_size, max_order)

      implicit none

      class(ddeabm_class), intent(inout)   :: me
      integer, intent(in)                  :: neq     !! number of equations to be integrated
      integer, intent(in)                  :: maxnum  !! maximum number of integration steps allowed
      procedure(deriv_func)               :: df      !! derivative function dx/dt
      real(wp), dimension(:), intent(in)    :: rtol    !! relative tolerance for integration (see [[ddeabm]])
      real(wp), dimension(:), intent(in)    :: atol    !! absolution tolerance for integration (see [[ddeabm]])
      procedure(report_func), optional     :: report  !! reporting function
      integer, intent(in), optional         :: initial_step_mode !! how to choose the initial step `h`:
                                                             !!
                                                             !! 1. Use [[dhstrt]].
                                                             !! 2. Use the older (quicker) algorithm.
                                                             !! 3. Use the user-specified value `initial_step_size` (>0).
      real(wp), intent(in), optional        :: initial_step_size !! for `initial_step_mode=3`
      real(wp), intent(in), optional        :: max_step_size !! maximum step size magnitude (>0).
                                                             !! If not present, the step size is not limited.
      integer, intent(in), optional         :: max_order !! maximum order of the method
                                                         !! (`1` to `ddeabm_max_order_limit`). If not present,
                                                         !! `ddeabm_default_max_order` (12) is used.
                                                         !! A lower value can improve stability on some problems.
                                                         !! A higher value can reduce the number of steps for very
                                                         !! tight tolerances when using higher precision (`REAL128`).

      logical :: vector_tols
      integer :: i, j, k
      integer :: kmax !! maximum order of the method
      character(len=100) :: msg !! error message

      !initialize the class:
      call me%destroy()

      !maximum order of the method:
      kmax = ddeabm_default_max_order
      if (present(max_order)) then
         if (max_order < 1 .or. max_order > ddeabm_max_order_limit) then
            write (msg, '(A,I0,A,I0)') 'Error in ddeabm_initialize: max_order must be in the range 1 to ', &
               ddeabm_max_order_limit, '. It was ', max_order
            error stop trim(msg)
         end if
         kmax = max_order
      end if
      me%max_order = kmax

      !number of equations:
      me%neq = neq

      !maximum number of steps:
      me%maxnum = maxnum

      !set the derivative routine pointer:
      me%df => df

      !set the report function (optional):
      if (present(report)) then
         me%report => report
      else
         nullify (me%report)
      end if

      !allocate the work arrays:
      allocate (me%ypout(neq))
      allocate (me%yp(neq))
      allocate (me%yy(neq))
      allocate (me%wt(neq))
      allocate (me%p(neq))
      allocate (me%phi(neq, max(kmax + 4, 6)))  ! (dhstrt uses columns 3:6 as work arrays)
      allocate (me%alpha(kmax), me%beta(kmax), me%psi(kmax), me%v(kmax), me%w(kmax), me%gi(kmax))
      allocate (me%sig(kmax + 1), me%g(kmax + 1))
      allocate (me%iv(kmax))
      me%alpha = 0.0_wp
      me%beta = 0.0_wp
      me%psi = 0.0_wp
      me%v = 0.0_wp
      me%w = 0.0_wp
      me%gi = 0.0_wp
      me%sig = 0.0_wp
      me%g = 0.0_wp
      me%iv = 0
      ! so that interpolation before the first step is well defined:
      me%ypout = 0.0_wp
      me%yp = 0.0_wp
      me%yy = 0.0_wp
      me%wt = 0.0_wp
      me%p = 0.0_wp
      me%phi = 0.0_wp

      !tolerances:
      ! [for now, we are considering these unchangeable, although they do not have to be]
      ! each of rtol and atol can be size 1 (used for all equations) or size neq.

      if (size(rtol) /= 1 .and. size(rtol) /= neq) &
         error stop 'Error in ddeabm_initialize: rtol must be size 1 or neq'
      if (size(atol) /= 1 .and. size(atol) /= neq) &
         error stop 'Error in ddeabm_initialize: atol must be size 1 or neq'

      vector_tols = (size(rtol) == neq .or. size(atol) == neq) .and. neq > 1
      me%scalar_tols = .not. vector_tols

      if (me%scalar_tols) then
         allocate (me%rtol(1)); allocate (me%rtol_tmp(1))
         allocate (me%atol(1)); allocate (me%atol_tmp(1))
         me%rtol = rtol(1)
         me%atol = atol(1)
      else
         ! a size-1 tolerance is used for all the equations
         allocate (me%rtol(neq)); allocate (me%rtol_tmp(neq))
         allocate (me%atol(neq)); allocate (me%atol_tmp(neq))
         if (size(rtol) == 1) then
            me%rtol = rtol(1)
         else
            me%rtol = rtol
         end if
         if (size(atol) == 1) then
            me%atol = atol(1)
         else
            me%atol = atol
         end if
      end if

      !Compute the two and gstr arrays:
      !  Note: this is a modification of the original dsteps code.
      !  The full-precision coefficients are used here, instead
      !  of the less precise ones in the original.
      !  These are computed recursively using the equation on p. 159 of
      !  Shampine/Gordon, "Computer Solution of Ordinary Differential Equations", 1975.
      allocate (me%two(kmax + 1))
      allocate (me%gstr(0:kmax + 1))
      do i = 1, kmax + 1
         me%two(i) = 2.0_wp**i
      end do
      me%gstr = 0.0_wp
      me%gstr(0) = 1.0_wp
      do i = 1, kmax + 1
         k = 1
         do j = i - 1, 0, -1
            k = k + 1
            me%gstr(i) = me%gstr(i) + 1.0_wp/real(k, wp)*me%gstr(j)
         end do
         me%gstr(i) = -me%gstr(i)
      end do
      me%gstr = abs(me%gstr)

      ! initial step size (can have initial_step_mode 1, 2, or 3):
      me%initial_step_size = 0.0_wp ! dummy value (only used if initial_step_mode is 3)
      if (present(initial_step_mode)) then
         select case (initial_step_mode)
         case (1, 2, 3)
            me%initial_step_mode = initial_step_mode
            if (initial_step_mode == 3) then
               if (present(initial_step_size)) then
                  if (initial_step_size > 0.0_wp) then
                     me%initial_step_size = initial_step_size
                  else
                     error stop 'Error in ddeabm_initialize: initial_step_size must be > 0'
                  end if
               else
                  error stop 'Error in ddeabm_initialize: initial_step_size must be input when initial_step_mode=3'
               end if
            end if
         case default
            error stop 'Error in ddeabm_initialize: invalid input for initial_step_mode'
         end select
      else
         me%initial_step_mode = 1 ! original method (dhstrt) if none is specified
      end if

      ! maximum step size (optional):
      me%max_step_size = 0.0_wp ! no limit
      if (present(max_step_size)) then
         if (max_step_size > 0.0_wp) then
            me%max_step_size = max_step_size
         else
            error stop 'Error in ddeabm_initialize: max_step_size must be > 0'
         end if
      end if

   end subroutine ddeabm_initialize