foodie_integrator_multistep_object.f90 Source File

Define the abstract type integrator_multistep_object of FOODIE ODE integrators.

This File Depends On

sourcefile~~foodie_integrator_multistep_object.f90~~EfferentGraph sourcefile~foodie_integrator_multistep_object.f90 foodie_integrator_multistep_object.f90 sourcefile~foodie_integrand_object.f90 foodie_integrand_object.F90 sourcefile~foodie_integrand_object.f90->sourcefile~foodie_integrator_multistep_object.f90 sourcefile~foodie_integrator_object.f90 foodie_integrator_object.f90 sourcefile~foodie_integrator_object.f90->sourcefile~foodie_integrator_multistep_object.f90
Help

Files Dependent On This One

sourcefile~~foodie_integrator_multistep_object.f90~~AfferentGraph sourcefile~foodie_integrator_multistep_object.f90 foodie_integrator_multistep_object.f90 sourcefile~foodie.f90 foodie.f90 sourcefile~foodie_integrator_multistep_object.f90->sourcefile~foodie.f90 sourcefile~foodie_integrator_adams_bashforth.f90 foodie_integrator_adams_bashforth.f90 sourcefile~foodie_integrator_multistep_object.f90->sourcefile~foodie_integrator_adams_bashforth.f90 sourcefile~foodie_integrator_adams_bashforth_moulton.f90 foodie_integrator_adams_bashforth_moulton.f90 sourcefile~foodie_integrator_multistep_object.f90->sourcefile~foodie_integrator_adams_bashforth_moulton.f90 sourcefile~foodie_integrator_backward_differentiation_formula.f90 foodie_integrator_backward_differentiation_formula.f90 sourcefile~foodie_integrator_multistep_object.f90->sourcefile~foodie_integrator_backward_differentiation_formula.f90 sourcefile~foodie_integrator_lmm_ssp_vss.f90 foodie_integrator_lmm_ssp_vss.f90 sourcefile~foodie_integrator_multistep_object.f90->sourcefile~foodie_integrator_lmm_ssp_vss.f90 sourcefile~foodie_integrator_adams_moulton.f90 foodie_integrator_adams_moulton.f90 sourcefile~foodie_integrator_multistep_object.f90->sourcefile~foodie_integrator_adams_moulton.f90 sourcefile~foodie_integrator_lmm_ssp.f90 foodie_integrator_lmm_ssp.f90 sourcefile~foodie_integrator_multistep_object.f90->sourcefile~foodie_integrator_lmm_ssp.f90 sourcefile~foodie_integrator_leapfrog.f90 foodie_integrator_leapfrog.f90 sourcefile~foodie_integrator_multistep_object.f90->sourcefile~foodie_integrator_leapfrog.f90 sourcefile~type_euler-1d.f90 type_euler-1D.f90 sourcefile~foodie.f90->sourcefile~type_euler-1d.f90 sourcefile~lorenz.f90 lorenz.f90 sourcefile~foodie.f90->sourcefile~lorenz.f90 sourcefile~foodie_test_integrand_oscillation.f90 foodie_test_integrand_oscillation.f90 sourcefile~foodie.f90->sourcefile~foodie_test_integrand_oscillation.f90 sourcefile~euler-1d.f90 euler-1D.f90 sourcefile~foodie.f90->sourcefile~euler-1d.f90 sourcefile~foodie_test_integrand_lcce.f90 foodie_test_integrand_lcce.f90 sourcefile~foodie.f90->sourcefile~foodie_test_integrand_lcce.f90 sourcefile~type_burgers.f90 type_burgers.f90 sourcefile~foodie.f90->sourcefile~type_burgers.f90 sourcefile~type_euler-1d-caf.f90 type_euler-1D-caf.f90 sourcefile~foodie.f90->sourcefile~type_euler-1d-caf.f90 sourcefile~type_lorenz.f90 type_lorenz.f90 sourcefile~foodie.f90->sourcefile~type_lorenz.f90 sourcefile~foodie_test_lcce.f90 foodie_test_lcce.f90 sourcefile~foodie.f90->sourcefile~foodie_test_lcce.f90 sourcefile~euler-1d-caf.f90 euler-1D-caf.f90 sourcefile~foodie.f90->sourcefile~euler-1d-caf.f90 sourcefile~burgers.f90 burgers.f90 sourcefile~foodie.f90->sourcefile~burgers.f90 sourcefile~type_euler-1d-openmp.f90 type_euler-1D-openmp.f90 sourcefile~foodie.f90->sourcefile~type_euler-1d-openmp.f90 sourcefile~foodie_tester.f90 foodie_tester.f90 sourcefile~foodie.f90->sourcefile~foodie_tester.f90 sourcefile~foodie_test_integrand_ladvection.f90 foodie_test_integrand_ladvection.f90 sourcefile~foodie.f90->sourcefile~foodie_test_integrand_ladvection.f90 sourcefile~foodie_test_integrand_tester_object.f90 foodie_test_integrand_tester_object.f90 sourcefile~foodie.f90->sourcefile~foodie_test_integrand_tester_object.f90 sourcefile~euler-1d-openmp.f90 euler-1D-openmp.f90 sourcefile~foodie.f90->sourcefile~euler-1d-openmp.f90 sourcefile~foodie_test_oscillation.f90 foodie_test_oscillation.f90 sourcefile~foodie.f90->sourcefile~foodie_test_oscillation.f90 sourcefile~foodie_integrator_adams_bashforth.f90->sourcefile~foodie.f90 sourcefile~foodie_integrator_adams_bashforth.f90->sourcefile~foodie_integrator_adams_bashforth_moulton.f90 sourcefile~foodie_integrator_adams_bashforth_moulton.f90->sourcefile~foodie.f90 sourcefile~foodie_integrator_backward_differentiation_formula.f90->sourcefile~foodie.f90 sourcefile~foodie_integrator_lmm_ssp_vss.f90->sourcefile~foodie.f90 sourcefile~foodie_integrator_adams_moulton.f90->sourcefile~foodie.f90 sourcefile~foodie_integrator_adams_moulton.f90->sourcefile~foodie_integrator_adams_bashforth_moulton.f90 sourcefile~foodie_integrator_lmm_ssp.f90->sourcefile~foodie.f90 sourcefile~foodie_integrator_leapfrog.f90->sourcefile~foodie.f90 sourcefile~type_euler-1d.f90->sourcefile~euler-1d.f90 sourcefile~foodie_test_integrand_oscillation.f90->sourcefile~foodie_tester.f90 sourcefile~foodie_test_integrand_oscillation.f90->sourcefile~foodie_test_oscillation.f90 sourcefile~foodie_test_integrand_lcce.f90->sourcefile~foodie_test_lcce.f90 sourcefile~foodie_test_integrand_lcce.f90->sourcefile~foodie_tester.f90 sourcefile~type_burgers.f90->sourcefile~burgers.f90 sourcefile~type_euler-1d-caf.f90->sourcefile~euler-1d-caf.f90 sourcefile~type_lorenz.f90->sourcefile~lorenz.f90 sourcefile~type_euler-1d-openmp.f90->sourcefile~euler-1d-openmp.f90 sourcefile~foodie_test_integrand_ladvection.f90->sourcefile~foodie_tester.f90 sourcefile~foodie_test_integrand_tester_object.f90->sourcefile~foodie_test_integrand_oscillation.f90 sourcefile~foodie_test_integrand_tester_object.f90->sourcefile~foodie_test_integrand_lcce.f90 sourcefile~foodie_test_integrand_tester_object.f90->sourcefile~foodie_tester.f90 sourcefile~foodie_test_integrand_tester_object.f90->sourcefile~foodie_test_integrand_ladvection.f90
Help


Source Code

!< Define the abstract type [[integrator_multistep_object]] of FOODIE ODE integrators.

module foodie_integrator_multistep_object
!< Define the abstract type [[integrator_multistep_object]] of FOODIE ODE integrators.

use, intrinsic :: iso_fortran_env, only : stderr=>error_unit
use foodie_integrand_object, only : integrand_object
use foodie_integrator_object, only : integrator_object
use penf, only : I_P, R_P

implicit none
private
public :: integrator_multistep_object

type, extends(integrator_object), abstract :: integrator_multistep_object
   !< Abstract type of FOODIE ODE integrators of the multistep-implicit family.
   integer(I_P)                         :: registers   !< Number of registers used for steps.
   integer(I_P)                         :: steps       !< Number of time steps.
   logical                              :: autoupdate  !< Perform cyclic autoupdate of previous time steps buffers.
   integer(I_P)                         :: iterations  !< Implicit iterations.
   real(R_P),               allocatable :: Dt(:)       !< Previous time steps.
   real(R_P),               allocatable :: t(:)        !< Previous times.
   class(integrand_object), allocatable :: previous(:) !< Previous steps.
   class(integrand_object), allocatable :: buffer      !< Buffer used for fast integration.
   contains
      ! deferred methods
      procedure(integrate_interface),         pass(self), deferred :: integrate      !< Integrate integrand field.
      procedure(integrate_fast_interface),    pass(self), deferred :: integrate_fast !< Integrate integrand field, fast mode.
      ! implemented deferred methods of parent
      procedure, pass(self) :: is_multistage !< Return .true. for multistage integrator.
      procedure, pass(self) :: is_multistep  !< Return .true. for multistep integrator.
      procedure, pass(self) :: stages_number !< Return number of stages used.
      procedure, pass(self) :: steps_number  !< Return number of steps used.
      ! public methods
      procedure, pass(self) :: allocate_integrand_members !< Allocate integrand members.
      procedure, pass(lhs)  :: assign_multistep           !< Assign members of [[integrator_multistep_object]] and parents.
      procedure, pass(self) :: destroy_multistep          !< Destroy the integrator.
      procedure, nopass     :: update_previous            !< Cyclic update previous time steps.
endtype integrator_multistep_object

abstract interface
   !< Abstract interfaces of deferred methods of [[integrator_multistep_object]].
   subroutine integrate_interface(self, U, Dt, t)
   !< Integrate integrand field.
   import :: integrand_object, integrator_multistep_object, R_P
   class(integrator_multistep_object), intent(inout) :: self !< Integrator.
   class(integrand_object),            intent(inout) :: U    !< Integrand.
   real(R_P),                          intent(in)    :: Dt   !< Time steps.
   real(R_P),                          intent(in)    :: t    !< Times.
   endsubroutine integrate_interface

   subroutine integrate_fast_interface(self, U, Dt, t)
   !< Integrate integrand field, fast mode.
   import :: integrand_object, integrator_multistep_object, R_P
   class(integrator_multistep_object), intent(inout) :: self !< Integrator.
   class(integrand_object),            intent(inout) :: U    !< Field to be integrated.
   real(R_P),                          intent(in)    :: Dt   !< Time steps.
   real(R_P),                          intent(in)    :: t    !< Times.
   endsubroutine integrate_fast_interface
endinterface

contains
   ! deferred methods
   elemental function is_multistage(self)
   !< Return .true. for multistage integrator.
   class(integrator_multistep_object), intent(in) :: self          !< Integrator.
   logical                                        :: is_multistage !< Inquire result.

   is_multistage = .false.
   endfunction is_multistage

   elemental function is_multistep(self)
   !< Return .true. for multistage integrator.
   class(integrator_multistep_object), intent(in) :: self         !< Integrator.
   logical                                        :: is_multistep !< Inquire result.

   is_multistep = .true.
   endfunction is_multistep

   elemental function stages_number(self)
   !< Return number of stages used.
   class(integrator_multistep_object), intent(in) :: self          !< Integrator.
   integer(I_P)                                   :: stages_number !< Number of stages used.

   stages_number = 0
   endfunction stages_number

   elemental function steps_number(self)
   !< Return number of steps used.
   class(integrator_multistep_object), intent(in) :: self         !< Integrator.
   integer(I_P)                                   :: steps_number !< Number of steps used.

   steps_number = self%steps
   endfunction steps_number

   ! public methods
   subroutine allocate_integrand_members(self, U)
   !< Allocate members of interpolator being of [[integrand_object]] class.
   !<
   !< @note It is assumed that the integrator has been properly initialized before calling this method.
   class(integrator_multistep_object), intent(inout) :: self !< Integrator.
   class(integrand_object),            intent(in)    :: U    !< Integrand.
   integer(I_P)                                      :: s    !< Counter.

   if (self%is_multistep() .and. self%registers > 0) then
      if (allocated(self%Dt)) deallocate(self%Dt)
      allocate(self%Dt(1:self%registers)) ; self%Dt = 0._R_P
      if (allocated(self%t)) deallocate(self%t)
      allocate(self%t(1:self%registers)) ; self%t = 0._R_P
      if (allocated(self%previous)) deallocate(self%previous)
      allocate(self%previous(1:self%registers), mold=U)
      do s=1, self%registers
         self%previous(s) = U
      enddo
   endif
   if (self%has_fast_mode()) then
      if (allocated(self%buffer)) deallocate(self%buffer)
      allocate(self%buffer, mold=U)
      self%buffer = U
   endif
   endsubroutine allocate_integrand_members

   subroutine assign_multistep(lhs, rhs)
   !< Assign members of [[integrator_multistep_object]] and parents.
   class(integrator_multistep_object), intent(inout) :: lhs !< Left hand side.
   class(integrator_object),           intent(in)    :: rhs !< Right hand side.
   integer(I_P)                                      :: s   !< Counter.

   call lhs%assign_abstract(rhs=rhs)
   select type(rhs)
   class is (integrator_multistep_object)
     lhs%registers = rhs%registers
     lhs%steps = rhs%steps
     lhs%autoupdate = rhs%autoupdate
     lhs%iterations = rhs%iterations
     if (allocated(lhs%Dt)) deallocate(lhs%Dt)
     if (allocated(rhs%Dt)) lhs%Dt = rhs%Dt
     if (allocated(lhs%t)) deallocate(lhs%t)
     if (allocated(rhs%t)) lhs%t = rhs%t
     if (allocated(lhs%previous)) deallocate(lhs%previous)
     if (allocated(rhs%previous)) then
        allocate(lhs%previous(1:lhs%registers), mold=rhs%previous)
        do s=1, lhs%registers
           lhs%previous(s) = rhs%previous(s)
        enddo
     endif
     if (allocated(lhs%buffer)) deallocate(lhs%buffer)
     if (allocated(rhs%buffer)) then
        allocate(lhs%buffer, mold=rhs%buffer)
        lhs%buffer = rhs%buffer
     endif
   endselect
   endsubroutine assign_multistep

   elemental subroutine destroy_multistep(self)
   !< Destroy the integrator.
   class(integrator_multistep_object), intent(inout) :: self !< Integrator.

   call self%destroy_abstract
   self%registers = 0
   self%steps = -1
   self%autoupdate = .false.
   self%iterations = 0
   if (allocated(self%Dt)) deallocate(self%Dt)
   if (allocated(self%t)) deallocate(self%t)
   if (allocated(self%previous)) deallocate(self%previous)
   if (allocated(self%buffer)) deallocate(self%buffer)
   endsubroutine destroy_multistep

   subroutine update_previous(U, previous, Dt, t, previous_Dt, previous_t)
   !< Cyclic update previous time steps.
   class(integrand_object), intent(in)              :: U               !< Field to be integrated.
   class(integrand_object), intent(inout)           :: previous(1:)    !< Previous time steps solutions of integrand.
   real(R_P),               intent(in),    optional :: Dt              !< Time step.
   real(R_P),               intent(in),    optional :: t               !< Time.
   real(R_P),               intent(inout), optional :: previous_Dt(1:) !< Time step.
   real(R_P),               intent(inout), optional :: previous_t(1:)  !< Time.
   integer(I_P)                                     :: last_step       !< Last step.
   integer(I_P)                                     :: s               !< Steps counter.

   last_step = size(previous, dim=1)
   do s=1, last_step - 1
     previous(s) = previous(s + 1)
     if (present(previous_Dt)) previous_Dt(s) = previous_Dt(s + 1)
     if (present(previous_t)) previous_t(s) = previous_t(s + 1)
   enddo
   previous(last_step) = U
   if (present(previous_Dt)) previous_Dt(last_step) = Dt
   if (present(previous_t)) previous_t(last_step) = t + Dt
   endsubroutine update_previous
endmodule foodie_integrator_multistep_object