Octopus
walltimer.F90
Go to the documentation of this file.
1!! Copyright (C) 2019 M. Lueders, Heiko Appel
2!! Copyright (C) 2021 I-Te Lu
3!!
4!! This program is free software; you can redistribute it and/or modify
5!! it under the terms of the GNU General Public License as published by
6!! the Free Software Foundation; either version 2, or (at your option)
7!! any later version.
8!!
9!! This program is distributed in the hope that it will be useful,
10!! but WITHOUT ANY WARRANTY; without even the implied warranty of
11!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12!! GNU General Public License for more details.
13!!
14!! You should have received a copy of the GNU General Public License
15!! along with this program; if not, write to the Free Software
16!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17!! 02110-1301, USA.
18!!
19
25
26#include "global.h"
27
28module walltimer_oct_m
29 use debug_oct_m
30 use global_oct_m
31 use io_oct_m
32 use, intrinsic :: iso_fortran_env
33 use loct_oct_m
35 use mpi_oct_m
37 use parser_oct_m
38
39 implicit none
40
41 private
42
43 real(real64) :: start_time
44 real(real64) :: last_tap
45 real(real64) :: iteration_time
46 real(real64) :: margin
47 real(real64) :: duration
48 real(real64) :: restart_last_tap
49 real(real64) :: restart_duration
50
51 logical :: active
52 logical :: auto_tap
53 logical :: restart_active
54
55 public :: &
61
62contains
63
65 subroutine walltimer_init(auto)
66 logical, optional, intent(in) :: auto
67
68 real(real64) :: alarm_time, write_time, restart_alarm_time
69
70 push_sub(walltimer_init)
71
72 start_time = m_zero
73 last_tap = m_zero
74 iteration_time = m_zero
75 margin = m_zero
76
77 active = .false.
78 auto_tap = optional_default(auto, .true.)
79
80 ! The following have to be moved to the right place, after the names for the variables have been confirmed:
81
82 !%Variable Walltime
83 !%Type float
84 !%Default 0
85 !%Section Execution::IO
86 !%Description
87 !% Time in minutes before which the restart file will be written. This is to make sure that at least one restart
88 !% file can be written before the code might be killed to to exceeding the given CPU time.
89 !% If a finite time (in minutes) is specified, the code will write the restart file when the next
90 !% iteration (plus the RestartWriteTime) would exceed the given time.
91 !% A value less than 1 second (1/60 minutes) will disable the timer.
92 !%End
93 call parse_variable(global_namespace, 'Walltime', m_zero, alarm_time)
94 call set_alarm(alarm_time*60.0_real64)
95
96 !%Variable RestartWriteTime
97 !%Type float
98 !%Default 5
99 !%Section Execution::IO
100 !%Description
101 !% The RestartWriteTime (in minutes) will be subtracted from the WallTime to allow time for writing the restart file.
102 !% In huge calculations, this value should be increased.
103 !%End
104 call parse_variable(global_namespace, 'RestartWriteTime', 5.0_real64, write_time)
105 if (write_time > alarm_time/m_four) write_time = alarm_time/m_four
106 call set_margin(write_time*60.0_real64)
107
108 !%Variable RestartWallTimePeriod
109 !%Type float
110 !%Default 120
111 !%Section Execution::IO
112 !%Description
113 !% Period Time (in minutes) at which the restart file will be written.
114 !% If a finite time (in minutes) is specified, the code will write the restart file every period.
115 !%End
116 call parse_variable(global_namespace, 'RestartWallTimePeriod', 120.0_real64, restart_alarm_time)
117 call set_restart_alarm(restart_alarm_time*60.0_real64)
118 restart_active = .false.
119
120 call start()
122 pop_sub(walltimer_init)
123 end subroutine walltimer_init
124
126 subroutine walltimer_end()
127
128 push_sub(walltimer_end)
129
130 active = .false.
131
132 pop_sub(walltimer_end)
133 end subroutine walltimer_end
134
136 subroutine set_alarm(time)
137 real(real64) :: time
139 push_sub(set_alarm)
141 duration = time
143 pop_sub(set_alarm)
144 end subroutine set_alarm
147 subroutine set_restart_alarm(time)
148 real(real64) :: time
149
150 push_sub(set_restart_alarm)
151
152 restart_duration = time
153
154 pop_sub(set_restart_alarm)
155 end subroutine set_restart_alarm
156
158 subroutine set_margin(time)
159
160 real(real64) :: time
161
162 push_sub(set_margin)
163
164 margin = time
165
166 pop_sub(set_margin)
167 end subroutine set_margin
168
170 subroutine start()
171
172 push_sub(start)
173
174 start_time = loct_clock()
175 last_tap = start_time
176 restart_last_tap = start_time
177
179 if (duration > m_one) active = .true.
181 if (restart_duration > 60.0_real64) restart_active = .true.
182
183 pop_sub(start)
184 end subroutine start
185
187 subroutine walltimer_tap(print)
188 logical, optional, intent(in) :: print
189
190 real(real64) :: now
191
192 push_sub(walltimer_tap)
193
194 now = loct_clock()
195
196 iteration_time = now - last_tap
197 last_tap = now
198
199 if (optional_default(print, .false.)) then
200 write(message(1), '("Walltimer_tap: elapsed time = ",F6.2," (", 3F10.5, "), active = ",L1 )') &
201 now - start_time, duration, iteration_time, margin, active
202 call messages_info(1, all_nodes=.true.)
203 end if
204
205 pop_sub(walltimer_tap)
206 end subroutine walltimer_tap
207
209 logical function walltimer_alarm(comm, print)
210 type(mpi_comm), intent(in) :: comm
211 logical, optional, intent(in) :: print
212
213#ifdef HAVE_MPI
214 logical :: alarm
215#endif
216 real(real64) :: now
217
218 push_sub(walltimer_alarm)
220 now = loct_clock()
221
222 if (optional_default(print, .false.)) then
223 write(message(1), '("Walltimer_alarm: elapsed time = ",F6.2," (", 3F10.5, "), active = ",L1 )') &
224 now - start_time, duration, iteration_time, margin, active
225 call messages_info(1, all_nodes=.true.)
226 end if
227
228 if (auto_tap) call walltimer_tap()
230 walltimer_alarm = active .and. (now > start_time + duration - iteration_time - margin)
231
232 ! All processes need to know that the walltimer was triggered.
233#ifdef HAVE_MPI
234 call mpi_allreduce(walltimer_alarm, alarm, 1, mpi_logical, mpi_lor, comm, mpi_err)
235 walltimer_alarm = alarm
236#endif
237
238 if (walltimer_alarm) then
239 write(message(1), '("Walltimer stopping execution after = ",F6.2," minutes.")') (now - start_time)/60.0_real64
241 ! Switch status to indicate that the walltimer aborted the calculation.
242 ! This can be used to communicate the status of octopus to a queuing system and to daisy-chain jobs.
243 call messages_switch_status('walltimer-aborted')
244 end if
245
246 pop_sub(walltimer_alarm)
247 end function walltimer_alarm
248
249 logical function restart_walltime_period_alarm(comm)
250 type(mpi_comm), intent(in) :: comm
252#ifdef HAVE_MPI
253 logical :: alarm
254#endif
255 real(real64) :: now
256
258
259 now = loct_clock()
260
261 restart_walltime_period_alarm = restart_active .and. (now > restart_last_tap + restart_duration)
262
263 ! All processes need to know that the walltimer was triggered.
264#ifdef HAVE_MPI
265 call mpi_allreduce(restart_walltime_period_alarm, alarm, 1, mpi_logical, mpi_lor, comm, mpi_err)
267#endif
268
270 restart_last_tap = now
271 write(message(1), '(a)') "Restart walltime period is reached: writing restart data"
272 call messages_info(1)
273 end if
274
277
278end module walltimer_oct_m
279
280!! Local Variables:
281!! mode: f90
282!! coding: utf-8
283!! End:
real(real64), parameter, public m_zero
Definition: global.F90:187
real(real64), parameter, public m_four
Definition: global.F90:191
real(real64), parameter, public m_one
Definition: global.F90:188
Definition: io.F90:114
subroutine, public messages_switch_status(status)
create status file for asynchronous communication
Definition: messages.F90:677
subroutine, public messages_info(no_lines, iunit, verbose_limit, stress, all_nodes, namespace)
Definition: messages.F90:624
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:160
integer, public mpi_err
used to store return values of mpi calls
Definition: mpi.F90:269
type(namespace_t), public global_namespace
Definition: namespace.F90:132
This module provices a simple timer class which can be used to trigger the writing of a restart file ...
Definition: walltimer.F90:121
subroutine, public walltimer_init(auto)
initialize the timer
Definition: walltimer.F90:159
subroutine, public walltimer_end()
destructor
Definition: walltimer.F90:220
subroutine set_alarm(time)
set alarm interval in seconds
Definition: walltimer.F90:230
logical function, public walltimer_alarm(comm, print)
indicate whether time is up
Definition: walltimer.F90:303
logical function, public restart_walltime_period_alarm(comm)
Definition: walltimer.F90:343
subroutine start()
start the timer (save starting time)
Definition: walltimer.F90:264
subroutine, public walltimer_tap(print)
measure time of one iteration
Definition: walltimer.F90:281
subroutine set_restart_alarm(time)
set restart alarm interval in seconds
Definition: walltimer.F90:241
subroutine set_margin(time)
set safty margin in seconds
Definition: walltimer.F90:252
int true(void)