MOM6
MOM_write_cputime.F90
1 !> A module to monitor the overall CPU time used by MOM6 and project when to stop the model
3 
4 ! This file is part of MOM6. See LICENSE.md for the license.
5 
6 use mom_coms, only : sum_across_pes, num_pes
7 use mom_error_handler, only : mom_error, mom_mesg, fatal, is_root_pe
8 use mom_io, only : open_file, close_file, append_file, ascii_file, writeonly_file
10 use mom_time_manager, only : time_type, get_time, operator(>)
11 
12 implicit none ; private
13 
14 public write_cputime, mom_write_cputime_init, mom_write_cputime_end, write_cputime_start_clock
15 
16 !-----------------------------------------------------------------------
17 
18 integer :: clocks_per_sec = 1000 !< The number of clock cycles per second, used by the system clock
19 integer :: max_ticks = 1000 !< The number of ticks per second, used by the system clock
20 
21 !> A control structure that regulates the writing of CPU time
22 type, public :: write_cputime_cs ; private
23  real :: maxcpu !< The maximum amount of cpu time per processor
24  !! for which MOM should run before saving a restart
25  !! file and quiting with a return value that
26  !! indicates that further execution is required to
27  !! complete the simulation, in wall-clock seconds.
28  type(time_type) :: start_time !< The start time of the simulation.
29  !! Start_time is set in MOM_initialization.F90
30  real :: startup_cputime !< The CPU time used in the startup phase of the model.
31  real :: prev_cputime = 0.0 !< The last measured CPU time.
32  real :: dn_dcpu_min = -1.0 !< The minimum derivative of timestep with CPU time.
33  real :: cputime2 = 0.0 !< The accumulated cpu time.
34  integer :: previous_calls = 0 !< The number of times write_CPUtime has been called.
35  integer :: prev_n = 0 !< The value of n from the last call.
36  integer :: filecpu_ascii= -1 !< The unit number of the CPU time file.
37  character(len=200) :: cpufile !< The name of the CPU time file.
38 end type write_cputime_cs
39 
40 contains
41 
42 !> Evaluate the CPU time returned by SYSTEM_CLOCK at the start of a run
43 subroutine write_cputime_start_clock(CS)
44  type(write_cputime_cs), pointer :: cs !< The control structure set up by a previous
45  !! call to MOM_write_cputime_init.
46  integer :: new_cputime ! The CPU time returned by SYSTEM_CLOCK
47  if (.not.associated(cs)) allocate(cs)
48 
49  call system_clock(new_cputime, clocks_per_sec, max_ticks)
50  cs%prev_cputime = new_cputime
51 end subroutine write_cputime_start_clock
52 
53 !> Initialize the MOM_write_cputime module.
54 subroutine mom_write_cputime_init(param_file, directory, Input_start_time, CS)
55  type(param_file_type), intent(in) :: param_file !< A structure to parse for run-time parameters
56  character(len=*), intent(in) :: directory !< The directory where the CPU time file goes.
57  type(time_type), intent(in) :: input_start_time !< The start model time of the simulation.
58  type(write_cputime_cs), pointer :: cs !< A pointer that may be set to point to the
59  !! control structure for this module.
60 
61  ! Local variables
62  integer :: new_cputime ! The CPU time returned by SYSTEM_CLOCK
63  ! This include declares and sets the variable "version".
64 # include "version_variable.h"
65  character(len=40) :: mdl = 'MOM_write_cputime' ! This module's name.
66  logical :: all_default ! If true, all parameters are using their default values.
67 
68  if (.not.associated(cs)) then
69  allocate(cs)
70  call system_clock(new_cputime, clocks_per_sec, max_ticks)
71  cs%prev_cputime = new_cputime
72  endif
73 
74  ! Read all relevant parameters and write them to the model log.
75 
76  ! Determine whether all paramters are set to their default values.
77  call get_param(param_file, mdl, "MAXCPU", cs%maxcpu, default=-1.0, do_not_log=.true.)
78  call get_param(param_file, mdl, "CPU_TIME_FILE", cs%CPUfile, default="CPU_stats", do_not_log=.true.)
79  all_default = (cs%maxcpu == -1.0) .and. (trim(cs%CPUfile) == trim("CPU_stats"))
80 
81  call log_version(param_file, mdl, version, "", all_default=all_default)
82  call get_param(param_file, mdl, "MAXCPU", cs%maxcpu, &
83  "The maximum amount of cpu time per processor for which "//&
84  "MOM should run before saving a restart file and "//&
85  "quitting with a return value that indicates that a "//&
86  "further run is required to complete the simulation. "//&
87  "If automatic restarts are not desired, use a negative "//&
88  "value for MAXCPU. MAXCPU has units of wall-clock "//&
89  "seconds, so the actual CPU time used is larger by a "//&
90  "factor of the number of processors used.", &
91  units="wall-clock seconds", default=-1.0)
92  call get_param(param_file, mdl, "CPU_TIME_FILE", cs%CPUfile, &
93  "The file into which CPU time is written.",default="CPU_stats")
94  cs%CPUfile = trim(directory)//trim(cs%CPUfile)
95  call log_param(param_file, mdl, "directory/CPU_TIME_FILE", cs%CPUfile)
96 #ifdef STATSLABEL
97  cs%CPUfile = trim(cs%CPUfile)//"."//trim(adjustl(statslabel))
98 #endif
99 
100  cs%Start_time = input_start_time
101 
102 end subroutine mom_write_cputime_init
103 
104 !> Close the MOM_write_cputime module.
105 subroutine mom_write_cputime_end(CS)
106  type(write_cputime_cs), pointer :: cs !< The control structure set up by a previous
107  !! call to MOM_write_cputime_init.
108 
109  if (.not.associated(cs)) return
110 
111  ! Flush and close the output files.
112  if (is_root_pe() .and. cs%fileCPU_ascii > 0) then
113  call flush(cs%fileCPU_ascii)
114  call close_file(cs%fileCPU_ascii)
115  endif
116 
117  deallocate(cs)
118 
119 end subroutine mom_write_cputime_end
120 
121 !> This subroutine assesses how much CPU time the model has taken and determines how long the model
122 !! should be run before it saves a restart file and stops itself. Optionally this may also be used
123 !! to trigger this module's end routine.
124 subroutine write_cputime(day, n, CS, nmax, call_end)
125  type(time_type), intent(inout) :: day !< The current model time.
126  integer, intent(in) :: n !< The time step number of the current execution.
127  type(write_cputime_cs), pointer :: cs !< The control structure set up by a previous
128  !! call to MOM_write_cputime_init.
129  integer, optional, intent(inout) :: nmax !< The number of iterations after which to stop so
130  !! that the simulation will not run out of CPU time.
131  logical, optional, intent(in) :: call_end !< If true, also call MOM_write_cputime_end.
132 
133  ! Local variables
134  real :: d_cputime ! The change in CPU time since the last call
135  ! this subroutine.
136  integer :: new_cputime ! The CPU time returned by SYSTEM_CLOCK
137  real :: reday ! A real version of day.
138  character(len=256) :: mesg ! The text of an error message
139  integer :: start_of_day, num_days
140 
141  if (.not.associated(cs)) call mom_error(fatal, &
142  "write_energy: Module must be initialized before it is used.")
143 
144  call system_clock(new_cputime, clocks_per_sec, max_ticks)
145 ! The following lines extract useful information even if the clock has rolled
146 ! over, assuming a 32-bit SYSTEM_CLOCK. With more bits, rollover is essentially
147 ! impossible. Negative fluctuations of less than 10 seconds are not interpreted
148 ! as the clock rolling over. This should be unnecessary but is sometimes needed
149 ! on the GFDL SGI/O3k.
150  if (new_cputime < cs%prev_cputime-(10.0*clocks_per_sec)) then
151  d_cputime = new_cputime - cs%prev_cputime + max_ticks
152  else
153  d_cputime = new_cputime - cs%prev_cputime
154  endif
155 
156  call sum_across_pes(d_cputime)
157  if (cs%previous_calls == 0) cs%startup_cputime = d_cputime
158 
159  cs%cputime2 = cs%cputime2 + d_cputime
160 
161  if ((cs%previous_calls >= 1) .and. (cs%maxcpu > 0.0)) then
162  ! Determine the slowest rate at which time steps are executed.
163  if ((n > cs%prev_n) .and. (d_cputime > 0.0) .and. &
164  ((cs%dn_dcpu_min*d_cputime < (n - cs%prev_n)) .or. &
165  (cs%dn_dcpu_min < 0.0))) &
166  cs%dn_dcpu_min = (n - cs%prev_n) / d_cputime
167  if (present(nmax) .and. (cs%dn_dcpu_min >= 0.0)) then
168  ! Have the model stop itself after 95% of the CPU time has been used.
169  nmax = n + int( cs%dn_dcpu_min * &
170  (0.95*cs%maxcpu * real(num_pes())*clocks_per_sec - &
171  (cs%startup_cputime + cs%cputime2)) )
172 ! write(mesg,*) "Resetting nmax to ",nmax," at day",reday
173 ! call MOM_mesg(mesg)
174  endif
175  endif
176  cs%prev_cputime = new_cputime ; cs%prev_n = n
177 
178  call get_time(day, start_of_day, num_days)
179  reday = real(num_days)+ (real(start_of_day)/86400.0)
180 
181  ! Reopen or create a text output file.
182  if ((cs%previous_calls == 0) .and. (is_root_pe())) then
183  if (day > cs%Start_time) then
184  call open_file(cs%fileCPU_ascii, trim(cs%CPUfile), &
185  action=append_file, form=ascii_file, nohdrs=.true.)
186  else
187  call open_file(cs%fileCPU_ascii, trim(cs%CPUfile), &
188  action=writeonly_file, form=ascii_file, nohdrs=.true.)
189  endif
190  endif
191 
192  if (is_root_pe()) then
193  if (cs%previous_calls == 0) then
194  write(cs%fileCPU_ascii, &
195  '("Startup CPU time: ", F12.3, " sec summed across", I5, " PEs.")') &
196  (cs%startup_cputime / clocks_per_sec), num_pes()
197  write(cs%fileCPU_ascii,*)" Day, Step number, CPU time, CPU time change"
198  endif
199  write(cs%fileCPU_ascii,'(F12.3,", "I11,", ", F12.3,", ", F12.3)') &
200  reday, n, (cs%cputime2 / real(clocks_per_sec)), &
201  d_cputime / real(clocks_per_sec)
202 
203  call flush(cs%fileCPU_ascii)
204  endif
205  cs%previous_calls = cs%previous_calls + 1
206 
207  if (present(call_end)) then
208  if (call_end) call mom_write_cputime_end(cs)
209  endif
210 
211 end subroutine write_cputime
212 
213 !> \namespace mom_write_cputime
214 !!
215 !! By Robert Hallberg, May 2006.
216 !!
217 !! This file contains the subroutine (write_cputime) that writes
218 !! the summed CPU time across all processors to an output file. In
219 !! addition, write_cputime estimates how many more time steps can be
220 !! taken before 95% of the available CPU time is used, so that the
221 !! model can be checkpointed at that time.
222 
223 end module mom_write_cputime
Wraps the FMS time manager functions.
A control structure that regulates the writing of CPU time.
A structure that can be parsed to read and document run-time parameters.
A module to monitor the overall CPU time used by MOM6 and project when to stop the model.
This module contains I/O framework code.
Definition: MOM_io.F90:2
The MOM6 facility to parse input files for runtime parameters.
An overloaded interface to log the values of various types of parameters.
Interfaces to non-domain-oriented communication subroutines, including the MOM6 reproducing sums faci...
Definition: MOM_coms.F90:3
Routines for error handling and I/O management.
An overloaded interface to log version information about modules.
An overloaded interface to read and log the values of various types of parameters.