diff --git a/src/main/swiftest_driver.f90 b/src/main/swiftest_driver.f90 index 965c89d1d..791194635 100644 --- a/src/main/swiftest_driver.f90 +++ b/src/main/swiftest_driver.f90 @@ -20,7 +20,9 @@ program swiftest_driver integer(I8B) :: ioutput_t0 !! The output frame counter at time 0 integer(I8B) :: nloops !! Number of steps to take in the simulation real(DP) :: old_t_final = 0.0_DP !! Output time at which writing should start, in order to prevent duplicate lines being written for restarts - type(walltimer) :: timer !! Object used for computing elapsed wall time + type(walltimer) :: integration_timer !! Object used for computing elapsed wall time + type(walltimer) :: file_io_timer !! Object used for computing elapsed wall time + integer(I4B) :: nout ierr = io_get_args(integrator, param_file_name) if (ierr /= 0) then @@ -72,11 +74,17 @@ program swiftest_driver !$ write(*,'(a)') ' OpenMP parameters:' !$ write(*,'(a)') ' ------------------' !$ write(*,'(a,i3,/)') ' Number of threads = ', nthreads - call timer%reset(param) + call integration_timer%reset() + call integration_timer%pause() + call file_io_timer%reset() + call file_io_timer%pause() + nout = 0 write(*, *) " *************** Main Loop *************** " do iloop = 1, nloops !> Step the system forward in time + call integration_timer%resume() call nbody_system%step(param, t, dt) + call integration_timer%pause() t = t0 + iloop * dt @@ -88,7 +96,10 @@ program swiftest_driver iout = iout - 1 if (iout == 0) then ioutput = ioutput_t0 + iloop / istep_out + call file_io_timer%resume() if (t > old_t_final) call nbody_system%write_frame(param) + nout = nout + 1 + call file_io_timer%pause() iout = istep_out end if end if @@ -97,8 +108,13 @@ program swiftest_driver if (istep_dump > 0) then idump = idump - 1 if (idump == 0) then - call timer%finish(nsubsteps=istep_dump, message="Integration steps:", param=param) + call integration_timer%report(nsubsteps=istep_dump, message="Integration steps:", param=param) + call file_io_timer%resume() call nbody_system%dump(param) + nout = nout + 1 + call file_io_timer%pause() + call file_io_timer%report(nsubsteps=nout, message=" File I/O:", param=param) + nout = 0 idump = istep_dump end if end if diff --git a/src/modules/walltime_classes.f90 b/src/modules/walltime_classes.f90 index 1d1ac5142..b0847bcba 100644 --- a/src/modules/walltime_classes.f90 +++ b/src/modules/walltime_classes.f90 @@ -16,13 +16,18 @@ module walltime_classes integer(I8B) :: count_start_main !! Value of the clock ticker at when the timer is first called integer(I8B) :: count_start_step !! Value of the clock ticker at the start of a timed step integer(I8B) :: count_stop_step !! Value of the clock ticker at the end of a timed step + integer(I8B) :: count_pause !! Value of the clock ticker at the end of a timed step real(DP) :: wall_step !! Value of the step elapsed time - logical :: lmain_is_started = .false. !! Logical flag indicating whether or not the main timer has been reset or not + logical :: main_is_started = .false. !! Logical flag indicating whether or not the main timer has been reset or not + logical :: is_paused = .false. !! Logical flag indicating whether or not the timer is paused + contains procedure :: reset => walltime_reset !! Resets the clock ticker, settting main_start to the current ticker value procedure :: start => walltime_start !! Starts the timer, setting count_start_step to the current ticker value procedure :: stop => walltime_stop !! Stops the timer, setting count_stop_step to the current ticker value - procedure :: finish => walltime_finish !! Ends the timer, setting step_finish to the current ticker value and printing the elapsed time information to the terminal + procedure :: pause => walltime_pause !! Pauses the step timer (but not the main timer). Use resume to continue. + procedure :: resume => walltime_resume !! Resumes a paused step timer. + procedure :: report => walltime_report !! Prints the elapsed time information to the terminal end type walltimer type, extends(walltimer) :: interaction_timer @@ -45,34 +50,38 @@ module walltime_classes end type interaction_timer interface - module subroutine walltime_finish(self, nsubsteps, message, param) + module subroutine walltime_pause(self) + implicit none + class(walltimer), intent(inout) :: self !! Walltimer object + end subroutine walltime_pause + + module subroutine walltime_resume(self) + implicit none + class(walltimer), intent(inout) :: self !! Walltimer object + end subroutine walltime_resume + + module subroutine walltime_report(self, nsubsteps, message, param) use swiftest_classes, only : swiftest_parameters implicit none class(walltimer), intent(inout) :: self !! Walltimer object integer(I4B), intent(in) :: nsubsteps !! Number of substeps used to compute the time per step character(len=*), intent(in) :: message !! Message to prepend to the wall time terminal output class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters - end subroutine walltime_finish + end subroutine walltime_report - module subroutine walltime_reset(self, param) - use swiftest_classes, only : swiftest_parameters + module subroutine walltime_reset(self) implicit none class(walltimer), intent(inout) :: self !! Walltimer object - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters end subroutine walltime_reset - module subroutine walltime_start(self, param) - use swiftest_classes, only : swiftest_parameters + module subroutine walltime_start(self) implicit none class(walltimer), intent(inout) :: self !! Walltimer object - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters end subroutine walltime_start - module subroutine walltime_stop(self, param) - use swiftest_classes, only : swiftest_parameters + module subroutine walltime_stop(self) implicit none class(walltimer), intent(inout) :: self !! Walltimer object - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters end subroutine walltime_stop end interface diff --git a/src/walltime/walltime.f90 b/src/walltime/walltime.f90 index 6f8897d98..758c5397a 100644 --- a/src/walltime/walltime.f90 +++ b/src/walltime/walltime.f90 @@ -2,10 +2,35 @@ use swiftest contains - module subroutine walltime_finish(self, nsubsteps, message, param) + module subroutine walltime_pause(self) !! author: David A. Minton !! - !! Ends the timer, setting step_finish to the current ticker value and printing the elapsed time information to the terminal + !! Pauses the step timer (but not the main timer). Use resume to continue. + implicit none + ! Arguments + class(walltimer), intent(inout) :: self !! Walltimer object + + if (.not.self%main_is_started) then + write(*,*) "Wall timer error: Cannot pause the step time until reset is called at least once!" + return + end if + + if (self%is_paused) then + write(*,*) "Wall timer error: Timer is already paused!" + return + end if + + call system_clock(self%count_pause) + self%is_paused = .true. + + return + end subroutine walltime_pause + + + module subroutine walltime_report(self, nsubsteps, message, param) + !! author: David A. Minton + !! + !! Prints the elapsed time information to the terminal implicit none ! Arguments class(walltimer), intent(inout) :: self !! Walltimer object @@ -13,19 +38,19 @@ module subroutine walltime_finish(self, nsubsteps, message, param) character(len=*), intent(in) :: message !! Message to prepend to the wall time terminal output class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters ! Internals - character(len=*), parameter :: walltimefmt = '" Wall time (s): ", es12.5, "; Wall time/step in this interval (s): ", es12.5' + character(len=*), parameter :: walltimefmt = '" Total wall time: ", es12.5, "; Interval wall time: ", es12.5, "; Interval wall time/step: ", es12.5' character(len=STRMAX) :: fmt integer(I8B) :: count_delta_step, count_delta_main, count_finish_step real(DP) :: wall_main !! Value of total elapsed time at the end of a timed step real(DP) :: wall_step !! Value of elapsed time since the start of a timed step real(DP) :: wall_per_substep !! Value of time per substep - if (.not.self%lmain_is_started) then + if (.not.self%main_is_started) then write(*,*) "Wall timer error: The step finish time cannot be calculated because the timer is not started!" return end if - call self%stop(param) + call self%stop() count_finish_step = self%count_stop_step count_delta_step = count_finish_step - self%count_start_step @@ -34,41 +59,64 @@ module subroutine walltime_finish(self, nsubsteps, message, param) wall_per_substep = self%wall_step / nsubsteps fmt = '("' // adjustl(message) // '",' // walltimefmt // ')' - write(*,trim(adjustl(fmt))) wall_main, wall_per_substep + write(*,trim(adjustl(fmt))) wall_main, self%wall_step, wall_per_substep - call self%start(param) + call self%start() return - end subroutine walltime_finish + end subroutine walltime_report - module subroutine walltime_reset(self, param) + module subroutine walltime_reset(self) !! author: David A. Minton !! !! Resets the clock ticker, settting main_start to the current ticker value implicit none ! Arguments class(walltimer), intent(inout) :: self !! Walltimer object - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters call system_clock(self%count_start_main, self%count_rate, self%count_max) - self%lmain_is_started = .true. - call self%start(param) + self%main_is_started = .true. + call self%start() return - end subroutine walltime_reset + end subroutine walltime_reset - module subroutine walltime_start(self, param) + module subroutine walltime_resume(self) + !! author: David A. Minton + !! + !! Resumes a paused step timer. + implicit none + ! Arguments + class(walltimer), intent(inout) :: self !! Walltimer object + ! Internals + integer(I8B) :: count_resume, count_delta + + if (.not.self%is_paused) then + write(*,*) "Wall timer error: Timer is not paused, and so cannot resume!" + return + end if + + call system_clock(count_resume) + count_delta = count_resume - self%count_pause + self%count_pause = 0_I8B + self%count_start_step = self%count_start_step + count_delta + self%is_paused = .false. + + return + end subroutine walltime_resume + + + module subroutine walltime_start(self) !! author: David A. Minton !! !! Starts the timer, setting step_start to the current ticker value implicit none ! Arguments class(walltimer), intent(inout) :: self !! Walltimer object - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters - if (.not.self%lmain_is_started) then + if (.not.self%main_is_started) then write(*,*) "Wall timer error: Cannot start the step time until reset is called at least once!" return end if @@ -79,18 +127,17 @@ module subroutine walltime_start(self, param) end subroutine walltime_start - module subroutine walltime_stop(self, param) + module subroutine walltime_stop(self) !! author: David A. Minton !! !! Starts the timer, setting step_start to the current ticker value implicit none ! Arguments class(walltimer), intent(inout) :: self !! Walltimer object - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters ! Internals integer(I8B) :: count_delta - if (.not.self%lmain_is_started) then + if (.not.self%main_is_started) then write(*,*) "Wall timer error: Cannot start the step time until reset is called at least once!" return end if @@ -121,7 +168,7 @@ module subroutine walltime_interaction_adapt(self, param, pl, ninteractions) logical :: lflatten_final ! Record the elapsed time - call self%stop(param) + call self%stop() write(schar,'(I1)') self%stage write(nstr,*) ninteractions @@ -269,7 +316,7 @@ module subroutine walltime_interaction_time_this_loop(self, param, pl, ninteract write(schar,'(I1)') self%stage call io_log_one_message(INTERACTION_TIMER_LOG_OUT, trim(adjustl(self%loopname)) // ": stage " // schar ) - call self%reset(param) + call self%reset() return end subroutine walltime_interaction_time_this_loop