fortime.f90 Source File


Files dependent on this one

sourcefile~~fortime.f90~~AfferentGraph sourcefile~fortime.f90 fortime.f90 sourcefile~example1.f90 example1.f90 sourcefile~example1.f90->sourcefile~fortime.f90 sourcefile~example2.f90 example2.f90 sourcefile~example2.f90->sourcefile~fortime.f90 sourcefile~example3.f90 example3.f90 sourcefile~example3.f90->sourcefile~fortime.f90 sourcefile~example4.f90 example4.f90 sourcefile~example4.f90->sourcefile~fortime.f90 sourcefile~example5.f90 example5.f90 sourcefile~example5.f90->sourcefile~fortime.f90 sourcefile~example6.f90 example6.f90 sourcefile~example6.f90->sourcefile~fortime.f90 sourcefile~test1.f90 test1.f90 sourcefile~test1.f90->sourcefile~fortime.f90 sourcefile~test10.f90 test10.f90 sourcefile~test10.f90->sourcefile~fortime.f90 sourcefile~test11.f90 test11.f90 sourcefile~test11.f90->sourcefile~fortime.f90 sourcefile~test12.f90 test12.f90 sourcefile~test12.f90->sourcefile~fortime.f90 sourcefile~test13.f90 test13.f90 sourcefile~test13.f90->sourcefile~fortime.f90 sourcefile~test14.f90 test14.f90 sourcefile~test14.f90->sourcefile~fortime.f90 sourcefile~test15.f90 test15.f90 sourcefile~test15.f90->sourcefile~fortime.f90 sourcefile~test16.f90 test16.f90 sourcefile~test16.f90->sourcefile~fortime.f90 sourcefile~test17.f90 test17.f90 sourcefile~test17.f90->sourcefile~fortime.f90 sourcefile~test18.f90 test18.f90 sourcefile~test18.f90->sourcefile~fortime.f90 sourcefile~test19.f90 test19.f90 sourcefile~test19.f90->sourcefile~fortime.f90 sourcefile~test2.f90 test2.f90 sourcefile~test2.f90->sourcefile~fortime.f90 sourcefile~test20.f90 test20.f90 sourcefile~test20.f90->sourcefile~fortime.f90 sourcefile~test21.f90 test21.f90 sourcefile~test21.f90->sourcefile~fortime.f90 sourcefile~test22.f90 test22.f90 sourcefile~test22.f90->sourcefile~fortime.f90 sourcefile~test23.f90 test23.f90 sourcefile~test23.f90->sourcefile~fortime.f90 sourcefile~test24.f90 test24.f90 sourcefile~test24.f90->sourcefile~fortime.f90 sourcefile~test25.f90 test25.f90 sourcefile~test25.f90->sourcefile~fortime.f90 sourcefile~test26.f90 test26.f90 sourcefile~test26.f90->sourcefile~fortime.f90 sourcefile~test27.f90 test27.f90 sourcefile~test27.f90->sourcefile~fortime.f90 sourcefile~test28.f90 test28.f90 sourcefile~test28.f90->sourcefile~fortime.f90 sourcefile~test29.f90 test29.f90 sourcefile~test29.f90->sourcefile~fortime.f90 sourcefile~test3.f90 test3.f90 sourcefile~test3.f90->sourcefile~fortime.f90 sourcefile~test30.f90 test30.f90 sourcefile~test30.f90->sourcefile~fortime.f90 sourcefile~test4.f90 test4.f90 sourcefile~test4.f90->sourcefile~fortime.f90 sourcefile~test5.f90 test5.f90 sourcefile~test5.f90->sourcefile~fortime.f90 sourcefile~test6.f90 test6.f90 sourcefile~test6.f90->sourcefile~fortime.f90 sourcefile~test7.f90 test7.f90 sourcefile~test7.f90->sourcefile~fortime.f90 sourcefile~test8.f90 test8.f90 sourcefile~test8.f90->sourcefile~fortime.f90 sourcefile~test9.f90 test9.f90 sourcefile~test9.f90->sourcefile~fortime.f90

Source Code

 !> This module provides a timer object for measuring elapsed time.
 !> It includes procedures for starting and stopping the timer, as well
 !> as calculating and printing the elapsed time in seconds.
module fortime

   use kinds

   implicit none

   private

   public :: timer

   !===============================================================================
   type :: timer
      integer, private :: clock_rate       ! Processor clock rate
      integer, private :: clock_start      ! Start time in processor ticks
      integer, private :: clock_end        ! End time in processor ticks
      integer, private :: clock_elapsed    ! Elapsed time in processor ticks
      real(rk)         :: elapsed_time     ! Elapsed time in seconds

      real(rk), private :: cpu_start       ! Start CPU time
      real(rk), private :: cpu_end         ! End CPU time
      real(rk), private :: cpu_elapsed     ! Elapsed CPU time
      real(rk)          :: cpu_time        ! Elapsed time in seconds

#if defined(USE_OMP)
      real(rk), private :: omp_start       ! Start OMP time
      real(rk), private :: omp_end         ! End OMP time
      real(rk), private :: omp_elapsed     ! Elapsed OMP time
      real(rk)          :: omp_time        ! Elapsed time in seconds
#endif

#if defined(USE_MPI)
      real(rk), private :: mpi_start       ! Start MPI time
      real(rk), private :: mpi_end         ! End MPI time
      real(rk), private :: mpi_elapsed     ! Elapsed MPI time
      real(rk)          :: mpi_time        ! Elapsed time in seconds
#endif

      integer, dimension(8), private :: values_start     ! Start date and time values
      integer, dimension(8), private :: values_end       ! End date and time values
      integer, dimension(8), private :: values_elapsed   ! Elapsed date and time values
      real(rk)                       :: elapsed_dtime    ! Elapsed time in seconds
   contains
      procedure :: timer_start     ! Procedure for starting the timer
      procedure :: timer_stop      ! Procedure for stopping the timer
      procedure :: timer_write     ! Procedure for writing elapsed time to a file

      procedure :: ctimer_start    ! Procedure for starting the CPU timer
      procedure :: ctimer_stop     ! Procedure for stopping the CPU timer
      procedure :: ctimer_write    ! Procedure for writing elapsed CPU time to a file

#if defined(USE_OMP)
      procedure :: otimer_start    ! Procedure for starting the OMP timer
      procedure :: otimer_stop     ! Procedure for stopping the OMP timer
      procedure :: otimer_write    ! Procedure for writing elapsed OMP time to a file
#endif

#if defined(USE_MPI)
      procedure :: mtimer_start    ! Procedure for starting the MPI timer
      procedure :: mtimer_stop     ! Procedure for stopping the MPI timer
      procedure :: mtimer_write    ! Procedure for writing elapsed MPI time to a file
#endif

      procedure :: dtimer_start     ! Procedure for starting the date_and_time timer
      procedure :: dtimer_stop      ! Procedure for stopping the date_and_time timer
      procedure :: dtimer_write     ! Procedure for writing elapsed date_and_time time to a file
   end type
   !===============================================================================

contains

   !===============================================================================
   !> author: Seyed Ali Ghasemi
   !> Starts the timer by recording the current processor clock value.
   !> This value is used to calculate the elapsed time later.
   impure subroutine timer_start(this)
      class(timer), intent(inout) :: this

      ! Get the processor clock rate
      call system_clock(count_rate=this%clock_rate)

      ! Start the timer
      call system_clock(count=this%clock_start)

   end subroutine timer_start
   !===============================================================================


   !===============================================================================
   !> author: Seyed Ali Ghasemi
   !> Stops the timer and calculates the elapsed time.
   !> Optionally, it can print a message along with the elapsed time.
   impure subroutine timer_stop(this, nloops, message, print, color)
      class(timer), intent(inout)        :: this
      integer,      intent(in), optional :: nloops
      character(*), intent(in), optional :: message
      character(:), allocatable          :: msg
      logical,      intent(in), optional :: print
      character(*), intent(in), optional :: color

      ! Stop the timer
      call system_clock(count=this%clock_end)

      ! Calculate the elapsed processor ticks
      this%clock_elapsed = this%clock_end - this%clock_start

      ! Convert processor ticks to seconds
      if (.not.present(nloops)) &
      this%elapsed_time = real(this%clock_elapsed, kind=rk) / real(this%clock_rate, kind=rk)
      if (     present(nloops)) &
      this%elapsed_time = real(this%clock_elapsed, kind=rk) / real(this%clock_rate, kind=rk) / real(nloops, kind=rk)

      ! Print the elapsed time
      if (.not. present(message)) then
         msg = "Elapsed time:"
      else
         msg = message
      end if

      if (present(print)) then
         if (print) call print_time(this%elapsed_time, msg, color)
      else
         call print_time(this%elapsed_time, msg, color)
      end if

      ! Deallocate the message
      if (allocated(msg)) deallocate(msg)

   end subroutine timer_stop
   !===============================================================================


   !===============================================================================
   !> author: Seyed Ali Ghasemi
   !> Writes the elapsed time to a file.
   impure subroutine timer_write(this, file_name)
      class(timer), intent(in) :: this
      character(*), intent(in) :: file_name
      logical                  :: file_exists
      integer                  :: nunit

      ! Check if the file exists
      inquire(file=file_name, exist=file_exists)

      ! Open the file in appropriate mode
      if (file_exists) then
         open(newunit=nunit, file=file_name, status='old', action='write', position='append')
      else
         open(newunit=nunit, file=file_name, status='new', action='write')
      end if

      ! Write the elapsed time to the file
      write(nunit, '(g0)') this%elapsed_time

      ! Close the file
      close(nunit)

   end subroutine timer_write
   !===============================================================================


   !===============================================================================
   !> author: Seyed Ali Ghasemi
   !> Starts the timer by recording the current CPU time value.
   !> This value is used to calculate the CPU time later.
   impure subroutine ctimer_start(this)
      class(timer), intent(inout) :: this

      ! Start the timer
      call cpu_time(this%cpu_start)

   end subroutine ctimer_start
   !===============================================================================


   !===============================================================================
   !> author: Seyed Ali Ghasemi
   !> Stops the timer and calculates the CPU time.
   !> Optionally, it can print a message along with the CPU time.
   impure subroutine ctimer_stop(this, nloops, message, print, color)
      class(timer), intent(inout)        :: this
      integer,      intent(in), optional :: nloops
      character(*), intent(in), optional :: message
      character(:), allocatable          :: msg
      logical,      intent(in), optional :: print
      character(*), intent(in), optional :: color

      ! Stop the timer
      call cpu_time(this%cpu_end)

      ! Calculate the elapsed CPU time
      this%cpu_elapsed = this%cpu_end - this%cpu_start

      ! Convert CPU time to seconds
      if (.not.present(nloops)) this%cpu_time = this%cpu_elapsed
      if (     present(nloops)) this%cpu_time = this%cpu_elapsed / real(nloops, kind=rk)

      ! Print the elapsed time
      if (.not. present(message)) then
         msg = "CPU time:"
      else
         msg = message
      end if

      if (present(print)) then
         if (print) call print_time(this%cpu_time, msg, color)
      else
         call print_time(this%cpu_time, msg, color)
      end if

      ! Deallocate the message
      if (allocated(msg)) deallocate(msg)

   end subroutine ctimer_stop
   !===============================================================================


   !===============================================================================
   !> author: Seyed Ali Ghasemi
   !> Writes the CPU time to a file.
   impure subroutine ctimer_write(this, file_name)
      class(timer), intent(in) :: this
      character(*), intent(in) :: file_name
      logical                  :: file_exists
      integer                  :: nunit

      ! Check if the file exists
      inquire(file=file_name, exist=file_exists)

      ! Open the file in appropriate mode
      if (file_exists) then
         open(newunit=nunit, file=file_name, status='old', action='write', position='append')
      else
         open(newunit=nunit, file=file_name, status='new', action='write')
      end if

      ! Write the CPU time to the file
      write(nunit, '(g0)') this%cpu_time

      ! Close the file
      close(nunit)

   end subroutine ctimer_write
   !===============================================================================


   !===============================================================================
   !> author: Seyed Ali Ghasemi
   !> Starts the timer by recording the current OMP time value.
   !> This value is used to calculate the OMP time later.
#if defined(USE_OMP)
   impure subroutine otimer_start(this)
      use omp_lib
      class(timer), intent(inout) :: this

      ! Start the timer
      this%omp_start = omp_get_wtime()

   end subroutine otimer_start
   !===============================================================================
#endif


#if defined(USE_OMP)
   !===============================================================================
   !> author: Seyed Ali Ghasemi
   !> Stops the timer and calculates the OMP time.
   !> Optionally, it can print a message along with the OMP time.
   impure subroutine otimer_stop(this, nloops, message, print, color)
      use omp_lib
      class(timer), intent(inout)        :: this
      integer,      intent(in), optional :: nloops
      character(*), intent(in), optional :: message
      character(:), allocatable          :: msg
      logical,      intent(in), optional :: print
      character(*), intent(in), optional :: color

      ! Stop the timer
      this%omp_end = omp_get_wtime()

      ! Calculate the elapsed OMP time
      this%omp_elapsed = this%omp_end - this%omp_start

      ! Convert OMP time to seconds
      if (.not.present(nloops)) this%omp_time = this%omp_elapsed
      if (     present(nloops)) this%omp_time = this%omp_elapsed / real(nloops, kind=rk)

      ! Print the elapsed time
      if (.not. present(message)) then
         msg = "OMP time:"
      else
         msg = message
      end if

      if (present(print)) then
         if (print) call print_time(this%omp_time, msg, color)
      else
         call print_time(this%omp_time, msg, color)
      end if

      ! Deallocate the message
      if (allocated(msg)) deallocate(msg)

   end subroutine otimer_stop
   !===============================================================================
#endif


#if defined(USE_OMP)
   !===============================================================================
   !> author: Seyed Ali Ghasemi
   !> Writes the OMP time to a file.
   impure subroutine otimer_write(this, file_name)
      use omp_lib
      class(timer), intent(in) :: this
      character(*), intent(in) :: file_name
      logical                  :: file_exists
      integer                  :: nunit

      ! Check if the file exists
      inquire(file=file_name, exist=file_exists)

      ! Open the file in appropriate mode
      if (file_exists) then
         open(newunit=nunit, file=file_name, status='old', action='write', position='append')
      else
         open(newunit=nunit, file=file_name, status='new', action='write')
      end if

      ! Write the OMP time to the file
      write(nunit, '(g0)') this%omp_time

      ! Close the file
      close(nunit)

   end subroutine otimer_write
   !===============================================================================
#endif


#if defined(USE_MPI)
   !===============================================================================
   !> author: Seyed Ali Ghasemi
   !> Starts the timer by recording the current MPI time value.
   !> This value is used to calculate the MPI time later.
   impure subroutine mtimer_start(this)
      ! include 'mpif.h'
      class(timer), intent(inout) :: this

      interface
         function mpi_wtime()
            import rk
            real(rk) :: mpi_wtime
         end function mpi_wtime
      end interface

      ! Start the timer
      this%mpi_start = mpi_wtime()

   end subroutine mtimer_start
   !===============================================================================
#endif


#if defined(USE_MPI)
   !===============================================================================
   !> author: Seyed Ali Ghasemi
   !> Stops the timer and calculates the MPI time.
   !> Optionally, it can print a message along with the MPI time.
   impure subroutine mtimer_stop(this, nloops, message, print, color)
      ! include 'mpif.h'
      class(timer), intent(inout)        :: this
      integer,      intent(in), optional :: nloops
      character(*), intent(in), optional :: message
      character(:), allocatable          :: msg
      logical,      intent(in), optional :: print
      character(*), intent(in), optional :: color

      interface
         function mpi_wtime()
            import rk
            real(rk) :: mpi_wtime
         end function mpi_wtime
      end interface

      ! Stop the timer
      this%mpi_end = mpi_wtime()

      ! Calculate the elapsed MPI time
      this%mpi_elapsed = this%mpi_end - this%mpi_start

      ! Convert MPI time to seconds
      if (.not.present(nloops)) this%mpi_time = this%mpi_elapsed
      if (     present(nloops)) this%mpi_time = this%mpi_elapsed / real(nloops, kind=rk)

      ! Print the elapsed time
      if (.not. present(message)) then
         msg = "MPI time:"
      else
         msg = message
      end if

      if (present(print)) then
         if (print) call print_time(this%mpi_time, msg, color)
      else
         call print_time(this%mpi_time, msg, color)
      end if

      ! Deallocate the message
      if (allocated(msg)) deallocate(msg)

   end subroutine mtimer_stop
   !===============================================================================
#endif


#if defined(USE_MPI)
   !===============================================================================
   !> author: Seyed Ali Ghasemi
   !> Writes the MPI time to a file.
   impure subroutine mtimer_write(this, file_name)
      class(timer), intent(in) :: this
      character(*), intent(in) :: file_name
      logical                  :: file_exists
      integer                  :: nunit

      ! Check if the file exists
      inquire(file=file_name, exist=file_exists)

      ! Open the file in appropriate mode
      if (file_exists) then
         open(newunit=nunit, file=file_name, status='old', action='write', position='append')
      else
         open(newunit=nunit, file=file_name, status='new', action='write')
      end if

      ! Write the MPI time to the file
      write(nunit, '(g0)') this%mpi_time

      ! Close the file
      close(nunit)

   end subroutine mtimer_write
   !===============================================================================
#endif


   !===============================================================================
   !> author: Seyed Ali Ghasemi
   !> Starts the timer by recording the current processor clock value.
   !> This value is used to calculate the elapsed time later.
   impure subroutine dtimer_start(this)
      class(timer), intent(inout) :: this

      ! Start the timer
      call date_and_time(values=this%values_start)

   end subroutine dtimer_start
   !===============================================================================


   !===============================================================================
   !> author: Seyed Ali Ghasemi
   !> Stops the timer and calculates the elapsed time.
   !> Optionally, it can print a message along with the elapsed time.
   impure subroutine dtimer_stop(this, nloops, message, print, color)
      class(timer), intent(inout)        :: this
      integer,      intent(in), optional :: nloops
      character(*), intent(in), optional :: message
      character(:), allocatable          :: msg
      logical,      intent(in), optional :: print
      character(*), intent(in), optional :: color

      ! Stop the timer
      call date_and_time(values=this%values_end)

      ! Calculate the elapsed processor ticks
      this%values_elapsed = this%values_end - this%values_start

      ! Convert processor ticks to seconds
      if (.not.present(nloops)) &
         this%elapsed_dtime = to_seconds(this%values_elapsed)
      if (     present(nloops)) &
         this%elapsed_dtime = to_seconds(this%values_elapsed) / real(nloops, kind=rk)

      ! Print the elapsed time
      if (.not. present(message)) then
         msg = "Elapsed time:"
      else
         msg = message
      end if

      if (present(print)) then
         if (print) call print_time(this%elapsed_dtime, msg, color)
      else
         call print_time(this%elapsed_dtime, msg, color)
      end if

      ! Deallocate the message
      if (allocated(msg)) deallocate(msg)

   end subroutine dtimer_stop
   !===============================================================================


   !===============================================================================
   !> author: Seyed Ali Ghasemi
   !> Writes the elapsed time to a file.
   impure subroutine dtimer_write(this, file_name)
      class(timer), intent(in) :: this
      character(*), intent(in) :: file_name
      logical                  :: file_exists
      integer                  :: nunit

      ! Check if the file exists
      inquire(file=file_name, exist=file_exists)

      ! Open the file in appropriate mode
      if (file_exists) then
         open(newunit=nunit, file=file_name, status='old', action='write', position='append')
      else
         open(newunit=nunit, file=file_name, status='new', action='write')
      end if

      ! Write the elapsed time to the file
      write(nunit, '(g0)') this%elapsed_dtime

      ! Close the file
      close(nunit)

   end subroutine dtimer_write
   !===============================================================================


   !===============================================================================
   !> author: Seyed Ali Ghasemi
   pure function to_seconds(values) result(seconds)
      integer, dimension(8), intent(in) :: values
      real(rk)                          :: seconds

      seconds = real(values(3), rk) * 24.0_rk * 60.0_rk * 60.0_rk + &
                real(values(5), rk) * 60.0_rk * 60.0_rk + &
                real(values(6), rk) * 60.0_rk + &
                real(values(7), rk) + & 
                real(values(8), rk) / 1000.0_rk

   end function to_seconds
   !===============================================================================


   !===============================================================================
   !> author: Seyed Ali Ghasemi
   impure subroutine print_time(time, message, color)
      use face
      real(rk),     intent(in) :: time
      character(*), intent(in) :: message
      character(*), intent(in), optional :: color

      if (present(color)) then
         print '(A, F16.9, A)', colorize(trim(message), color_fg=trim(color)), time, colorize(" [s]", color_fg=trim(color))
      else
         print '(A, F16.9, A)', colorize(trim(message), color_fg='blue'), time, colorize(" [s]", color_fg='blue')
      end if
   end subroutine print_time
   !===============================================================================

end module fortime