MOM6
MOM_write_cputime.F90
Go to the documentation of this file.
2 !***********************************************************************
3 !* GNU General Public License *
4 !* This file is a part of MOM. *
5 !* *
6 !* MOM is free software; you can redistribute it and/or modify it and *
7 !* are expected to follow the terms of the GNU General Public License *
8 !* as published by the Free Software Foundation; either version 2 of *
9 !* the License, or (at your option) any later version. *
10 !* *
11 !* MOM is distributed in the hope that it will be useful, but WITHOUT *
12 !* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
13 !* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public *
14 !* License for more details. *
15 !* *
16 !* For the full text of the GNU General Public License, *
17 !* write to: Free Software Foundation, Inc., *
18 !* 675 Mass Ave, Cambridge, MA 02139, USA. *
19 !* or see: http://www.gnu.org/licenses/gpl.html *
20 !***********************************************************************
21 
22 !********+*********+*********+*********+*********+*********+*********+**
23 !* *
24 !* By Robert Hallberg, May 2006. *
25 !* *
26 !* This file contains the subroutine (write_cputime) that writes *
27 !* the summed CPU time across all processors to an output file. In *
28 !* addition, write_cputime estimates how many more time steps can be *
29 !* taken before 95% of the available CPU time is used, so that the *
30 !* model can be checkpointed at that time. *
31 !* *
32 !********+*********+*********+*********+*********+*********+*********+**
33 
34 use mom_coms, only : sum_across_pes, pe_here, num_pes
35 use mom_error_handler, only : mom_error, fatal, is_root_pe
36 use mom_io, only : open_file, append_file, ascii_file, writeonly_file
38 use mom_time_manager, only : time_type, get_time, operator(>)
39 
40 implicit none ; private
41 
43 
44 !-----------------------------------------------------------------------
45 
46 integer :: clocks_per_sec = 1000
47 integer :: max_ticks = 1000
48 
49 type, public :: write_cputime_cs ; private
50  real :: maxcpu ! The maximum amount of cpu time per processor
51  ! for which MOM should run before saving a restart
52  ! file and quiting with a return value that
53  ! indicates that further execution is required to
54  ! complete the simulation, in wall-clock seconds.
55  type(time_type) :: start_time ! The start time of the simulation.
56  ! Start_time is set in MOM_initialization.F90
57  real :: startup_cputime ! The CPU time used in the startup phase of the model.
58  real :: prev_cputime = 0.0 ! The last measured CPU time.
59  real :: dn_dcpu_min = -1.0 ! The minimum derivative of timestep with CPU time.
60  real :: cputime2 = 0.0 ! The accumulated cpu time.
61  integer :: previous_calls = 0 ! The number of times write_CPUtime has been called.
62  integer :: prev_n = 0 ! The value of n from the last call.
63  integer :: filecpu_ascii ! The unit number of the CPU time file.
64  character(len=200) :: cpufile ! The name of the CPU time file.
65 end type write_cputime_cs
66 
67 contains
68 
69 subroutine write_cputime_start_clock(CS)
70  type(write_cputime_cs), pointer :: CS
71 ! Argument: CS - A pointer that is set to point to the control structure
72 ! for this module
73  integer :: new_cputime ! The CPU time returned by SYSTEM_CLOCK
74  if (.not.associated(cs)) allocate(cs)
75 
76  call system_clock(new_cputime, clocks_per_sec, max_ticks)
77  cs%prev_cputime = new_cputime
78 end subroutine write_cputime_start_clock
79 
80 subroutine mom_write_cputime_init(param_file, directory, Input_start_time, CS)
81  type(param_file_type), intent(in) :: param_file !< A structure to parse for run-time parameters
82  character(len=*), intent(in) :: directory
83  type(time_type), intent(in) :: Input_start_time
84  type(write_cputime_cs), pointer :: CS
85 ! Arguments: param_file - A structure indicating the open file to parse for
86 ! model parameter values.
87 ! (in) directory - The directory where the energy file goes.
88 ! (in) Input_start_time - The start time of the simulation.
89 ! (in/out) CS - A pointer that may be set to point to the control structure
90 ! for this module.
91  integer :: new_cputime ! The CPU time returned by SYSTEM_CLOCK
92 ! This include declares and sets the variable "version".
93 #include "version_variable.h"
94  character(len=40) :: mdl = 'MOM_write_cputime' ! This module's name.
95 
96  if (.not.associated(cs)) then
97  allocate(cs)
98  call system_clock(new_cputime, clocks_per_sec, max_ticks)
99  cs%prev_cputime = new_cputime
100  endif
101 
102  ! Read all relevant parameters and write them to the model log.
103  call log_version(param_file, mdl, version, "")
104  call get_param(param_file, mdl, "MAXCPU", cs%maxcpu, &
105  "The maximum amount of cpu time per processor for which \n"//&
106  "MOM should run before saving a restart file and \n"//&
107  "quitting with a return value that indicates that a \n"//&
108  "further run is required to complete the simulation. \n"//&
109  "If automatic restarts are not desired, use a negative \n"//&
110  "value for MAXCPU. MAXCPU has units of wall-clock \n"//&
111  "seconds, so the actual CPU time used is larger by a \n"//&
112  "factor of the number of processors used.", &
113  units="wall-clock seconds", default=-1.0)
114  call get_param(param_file, mdl, "CPU_TIME_FILE", cs%CPUfile, &
115  "The file into which CPU time is written.",default="CPU_stats")
116  cs%CPUfile = trim(directory)//trim(cs%CPUfile)
117  call log_param(param_file, mdl, "directory/CPU_TIME_FILE", cs%CPUfile)
118 #ifdef STATSLABEL
119  cs%CPUfile = trim(cs%CPUfile)//"."//trim(adjustl(statslabel))
120 #endif
121 
122  cs%Start_time = input_start_time
123 
124 end subroutine mom_write_cputime_init
125 
126 subroutine write_cputime(day, n, nmax, CS)
127  type(time_type), intent(inout) :: day
128  integer, intent(in) :: n
129  integer, intent(inout) :: nmax
130  type(write_cputime_cs), pointer :: CS
131 ! This subroutine assesses how much CPU time the model has
132 ! taken and determines how long the model should be run before it
133 ! saves a restart file and stops itself.
134 
135 ! Arguments: day - The current model time.
136 ! (in) n - The time step number of the current execution.
137 ! (out) nmax - The number of iterations after which to stop so
138 ! that the simulation will not run out of CPU time.
139 ! (in) G - The ocean's grid structure.
140 ! (in) CS - The control structure returned by a previous call to
141 ! MOM_write_cputime_init.
142  real :: d_cputime ! The change in CPU time since the last call
143  ! this subroutine.
144  integer :: new_cputime ! The CPU time returned by SYSTEM_CLOCK
145  real :: reday ! A real version of day.
146  integer :: start_of_day, num_days
147 
148  if (.not.associated(cs)) call mom_error(fatal, &
149  "write_energy: Module must be initialized before it is used.")
150 
151  call system_clock(new_cputime, clocks_per_sec, max_ticks)
152 ! The following lines extract useful information even if the clock has rolled
153 ! over, assuming a 32-bit SYSTEM_CLOCK. With more bits, rollover is essentially
154 ! impossible. Negative fluctuations of less than 10 seconds are not interpreted
155 ! as the clock rolling over. This should be unnecessary but is sometimes needed
156 ! on the GFDL SGI/O3k.
157  if (new_cputime < cs%prev_cputime-(10.0*clocks_per_sec)) then
158  d_cputime = new_cputime - cs%prev_cputime + max_ticks
159  else
160  d_cputime = new_cputime - cs%prev_cputime
161  endif
162 
163  call sum_across_pes(d_cputime)
164  if (cs%previous_calls == 0) cs%startup_cputime = d_cputime
165 
166  cs%cputime2 = cs%cputime2 + d_cputime
167 
168  if ((cs%previous_calls >= 1) .and. (cs%maxcpu > 0.0)) then
169  ! Determine the slowest rate at which time steps are executed.
170  if ((n > cs%prev_n) .and. (d_cputime > 0.0) .and. &
171  ((cs%dn_dcpu_min*d_cputime < (n - cs%prev_n)) .or. &
172  (cs%dn_dcpu_min < 0.0))) &
173  cs%dn_dcpu_min = (n - cs%prev_n) / d_cputime
174  if (cs%dn_dcpu_min >= 0.0) then
175  ! Have the model stop itself after 95% of the CPU time has been used.
176  nmax = n + int( cs%dn_dcpu_min * &
177  (0.95*cs%maxcpu * REAL(num_pes())*CLOCKS_PER_SEC - &
178  (cs%startup_cputime + cs%cputime2)) )
179 ! if (is_root_pe() ) then
180 ! write(*,*) "Resetting nmax to ",nmax," at day",reday
181 ! endif
182  endif
183  endif
184  cs%prev_cputime = new_cputime ; cs%prev_n = n
185 
186  call get_time(day, start_of_day, num_days)
187  reday = REAL(num_days)+ (REAL(start_of_day)/86400.0)
188 
189  ! Reopen or create a text output file.
190  if ((cs%previous_calls == 0) .and. (is_root_pe())) then
191  if (day > cs%Start_time) then
192  call open_file(cs%fileCPU_ascii, trim(cs%CPUfile), &
193  action=append_file, form=ascii_file, nohdrs=.true.)
194  else
195  call open_file(cs%fileCPU_ascii, trim(cs%CPUfile), &
196  action=writeonly_file, form=ascii_file, nohdrs=.true.)
197  endif
198  endif
199 
200  if (is_root_pe()) then
201  if (cs%previous_calls == 0) then
202  write(cs%fileCPU_ascii, &
203  '("Startup CPU time: ", F12.3, " sec summed across", I5, " PEs.")') &
204  (cs%startup_cputime / clocks_per_sec), num_pes()
205  write(cs%fileCPU_ascii,*)" Day, Step number, CPU time, CPU time change"
206  endif
207  write(cs%fileCPU_ascii,'(F12.3,", "I11,", ", F12.3,", ", F12.3)') &
208  reday, n, (cs%cputime2 / real(clocks_per_sec)), &
209  d_cputime / real(clocks_per_sec)
210  endif
211  cs%previous_calls = cs%previous_calls + 1
212 
213 end subroutine write_cputime
214 
215 end module mom_write_cputime
subroutine, public write_cputime_start_clock(CS)
subroutine, public mom_write_cputime_init(param_file, directory, Input_start_time, CS)
subroutine, public write_cputime(day, n, nmax, CS)
This module contains I/O framework code.
Definition: MOM_io.F90:2
logical function, public is_root_pe()
subroutine, public mom_error(level, message, all_print)