Line data Source code
1 : !--------------------------------------------------------------------------------------------------!
2 : ! CP2K: A general program to perform molecular dynamics simulations !
3 : ! Copyright 2000-2023 CP2K developers group <https://cp2k.org> !
4 : ! !
5 : ! SPDX-License-Identifier: GPL-2.0-or-later !
6 : !--------------------------------------------------------------------------------------------------!
7 :
8 : ! **************************************************************************************************
9 : !> \brief routines to handle the output, The idea is to remove the
10 : !> decision of wheter to output and what to output from the code
11 : !> that does the output, and centralize it here.
12 : !> \note
13 : !> These were originally together with the log handling routines,
14 : !> but have been spawned off. Some dependencies are still there,
15 : !> and some of the comments about log handling also applies to output
16 : !> handling: @see cp_log_handling
17 : !> \par History
18 : !> 12.2001 created [fawzi]
19 : !> 08.2002 updated to new logger [fawzi]
20 : !> 10.2004 big rewrite of the output methods, connected to the new
21 : !> input, and iteration_info [fawzi]
22 : !> 08.2005 property flags [fawzi]
23 : !> \author Fawzi Mohamed
24 : ! **************************************************************************************************
25 : MODULE cp_output_handling
26 : USE cp_files, ONLY: close_file,&
27 : open_file
28 : USE cp_iter_types, ONLY: cp_iteration_info_release,&
29 : cp_iteration_info_retain,&
30 : cp_iteration_info_type,&
31 : each_desc_labels,&
32 : each_possible_labels
33 : USE cp_log_handling, ONLY: cp_logger_generate_filename,&
34 : cp_logger_get_default_unit_nr,&
35 : cp_logger_get_unit_nr,&
36 : cp_logger_type,&
37 : cp_to_string
38 : USE input_keyword_types, ONLY: keyword_create,&
39 : keyword_release,&
40 : keyword_type
41 : USE input_section_types, ONLY: section_add_keyword,&
42 : section_add_subsection,&
43 : section_create,&
44 : section_release,&
45 : section_type,&
46 : section_vals_get_subs_vals,&
47 : section_vals_type,&
48 : section_vals_val_get
49 : USE kinds, ONLY: default_path_length,&
50 : default_string_length
51 : USE machine, ONLY: m_mov
52 : USE memory_utilities, ONLY: reallocate
53 : USE message_passing, ONLY: mp_file_delete,&
54 : mp_file_get_amode,&
55 : mp_file_type
56 : USE string_utilities, ONLY: compress,&
57 : s2a
58 : #include "../base/base_uses.f90"
59 :
60 : IMPLICIT NONE
61 : PRIVATE
62 :
63 : LOGICAL, PRIVATE, PARAMETER :: debug_this_module = .TRUE.
64 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'cp_output_handling'
65 : PUBLIC :: cp_print_key_should_output, cp_iterate, cp_add_iter_level, cp_rm_iter_level
66 : PUBLIC :: cp_iter_string, cp_print_key_section_create
67 : PUBLIC :: cp_print_key_unit_nr, cp_print_key_finished_output
68 : PUBLIC :: cp_print_key_generate_filename, cp_printkey_is_on
69 :
70 : INTEGER, PARAMETER, PUBLIC :: add_last_no = 0, &
71 : add_last_numeric = 1, &
72 : add_last_symbolic = 2
73 : INTEGER, PARAMETER, PUBLIC :: silent_print_level = 0, &
74 : low_print_level = 1, &
75 : medium_print_level = 2, &
76 : high_print_level = 3, &
77 : debug_print_level = 4
78 :
79 : !! flags controlling the printing and storing of a property.
80 : !!
81 : !! cp_out_none: do not calculate the property
82 : !! cp_out_file_if : if the printkey says it calculate and output the property
83 : !! cp_out_store_if : if the printkey says it calculate and store in memory
84 : !! the property
85 : !! cp_out_file_each: calculate and output the property with the same periodicity
86 : !! as said in the printkey (irrespective of the activation of
87 : !! the printkey)
88 : !! cp_out_store_each: calculate and store the property with the same periodicity
89 : !! as said in the printkey (irrespective of the activation of
90 : !! the printkey)
91 : !! cp_out_file: always calculate and output the property
92 : !! cp_out_store: always calculate and store in memory the property
93 : !! cp_out_calc: just calculate the value (independently from the fact that there
94 : !! should be output)
95 : !! cp_out_default: the default value for property flags (cp_out_file_if)
96 : !!
97 : !! this flags can be ior-ed together:
98 : !! ior(cp_out_file_if,cp_out_store_if): if the printkey says it both print
99 : !! and store the property
100 : !!
101 : !! there is no guarantee that a property is not stored if it is not necessary
102 : !! not all printkeys have a control flag
103 : INTEGER, PUBLIC, PARAMETER :: cp_p_file_if = 3, cp_p_store_if = 4, &
104 : cp_p_store = 2, cp_p_file = 1, cp_p_file_each = 5, cp_p_store_each = 6, cp_p_calc = 7
105 : INTEGER, PUBLIC, PARAMETER :: cp_out_none = 0, cp_out_file_if = IBSET(0, cp_p_file_if), &
106 : cp_out_store_if = IBSET(0, cp_p_store_if), cp_out_file = IBSET(0, cp_p_file), &
107 : cp_out_store = IBSET(0, cp_p_store), cp_out_calc = IBSET(0, cp_p_calc), &
108 : cp_out_file_each = IBSET(0, cp_p_file_each), &
109 : cp_out_store_each = IBSET(0, cp_p_store_each), &
110 : cp_out_default = cp_out_file_if
111 :
112 : ! Flag determining if MPI I/O should be enabled for functions that support it
113 : LOGICAL, PRIVATE, SAVE :: enable_mpi_io = .FALSE.
114 : ! Public functions to set/get the flags
115 : PUBLIC :: cp_mpi_io_set, cp_mpi_io_get
116 :
117 : ! **************************************************************************************************
118 : !> \brief stores the flags_env controlling the output of properties
119 : !> \param ref_count reference count (see doc/ReferenceCounting.html)
120 : !> \param n_flags number of flags stored in this type
121 : !> \param names names of the stored flags
122 : !> \param control_val value of the flag
123 : !> \param input the input (with all the printkeys)
124 : !> \param logger logger and iteration information (to know if output is needed)
125 : !> \param strict if flags that were not stored can be read
126 : !> \param default_val default value of the flags that are not explicitly
127 : !> stored
128 : !> \note
129 : !> Two features of this object should be:
130 : !> 1) easy state storage, one should be able to store the state of the
131 : !> flags, to some changes to them just for one (or few) force evaluations
132 : !> and then reset the original state. The actual implementation is good
133 : !> in this respect
134 : !> 2) work well with subsections. This is a problem at the moment, as
135 : !> if you pass just a subsection of the input the control flags get lost.
136 : !> A better implementation should be done storing the flags also in the
137 : !> input itself to be transparent
138 : !> \author fawzi
139 : ! **************************************************************************************************
140 : TYPE cp_out_flags_type
141 : INTEGER :: ref_count = 0, n_flags = 0
142 : CHARACTER(default_string_length), DIMENSION(:), POINTER :: names => NULL()
143 : INTEGER, DIMENSION(:), POINTER :: control_val => NULL()
144 : TYPE(section_vals_type), POINTER :: input => NULL()
145 : TYPE(cp_logger_type), POINTER :: logger => NULL()
146 : LOGICAL :: strict = .FALSE.
147 : INTEGER :: default_val = 0
148 : END TYPE cp_out_flags_type
149 :
150 : CONTAINS
151 :
152 : ! **************************************************************************************************
153 : !> \brief creates a print_key section
154 : !> \param print_key_section the print key to create
155 : !> \param location from where in the source code cp_print_key_section_create() is called
156 : !> \param name the name of the print key
157 : !> \param description the description of the print key
158 : !> \param print_level print level starting at which the printing takes place
159 : !> (defaults to debug_print_level)
160 : !> \param each_iter_names ...
161 : !> \param each_iter_values ...
162 : !> \param add_last ...
163 : !> \param filename ...
164 : !> \param common_iter_levels ...
165 : !> \param citations ...
166 : !> \param unit_str specifies an unit of measure for output quantity. If not
167 : !> provided the control is totally left to how the output was coded
168 : !> (i.e. USERS have no possibility to change it)
169 : !> \author fawzi
170 : ! **************************************************************************************************
171 5272039 : SUBROUTINE cp_print_key_section_create(print_key_section, location, name, description, &
172 5272039 : print_level, each_iter_names, each_iter_values, add_last, filename, &
173 157352 : common_iter_levels, citations, unit_str)
174 : TYPE(section_type), POINTER :: print_key_section
175 : CHARACTER(len=*), INTENT(IN) :: location, name, description
176 : INTEGER, INTENT(IN), OPTIONAL :: print_level
177 : CHARACTER(LEN=*), DIMENSION(:), INTENT(IN), &
178 : OPTIONAL :: each_iter_names
179 : INTEGER, DIMENSION(:), INTENT(IN), OPTIONAL :: each_iter_values
180 : INTEGER, INTENT(IN), OPTIONAL :: add_last
181 : CHARACTER(LEN=*), INTENT(IN), OPTIONAL :: filename
182 : INTEGER, INTENT(IN), OPTIONAL :: common_iter_levels
183 : INTEGER, DIMENSION(:), OPTIONAL :: citations
184 : CHARACTER(LEN=*), INTENT(IN), OPTIONAL :: unit_str
185 :
186 : CHARACTER(len=default_path_length) :: my_filename
187 : INTEGER :: i_each, i_iter, my_add_last, &
188 : my_comm_iter_levels, my_print_level, &
189 : my_value
190 : LOGICAL :: check, ext_each
191 : TYPE(keyword_type), POINTER :: keyword
192 : TYPE(section_type), POINTER :: subsection
193 :
194 5272039 : CPASSERT(.NOT. ASSOCIATED(print_key_section))
195 5272039 : my_print_level = debug_print_level
196 5272039 : IF (PRESENT(print_level)) my_print_level = print_level
197 :
198 : CALL section_create(print_key_section, location=location, name=name, description=description, &
199 : n_keywords=2, n_subsections=0, repeats=.FALSE., &
200 10386726 : citations=citations)
201 :
202 5272039 : NULLIFY (keyword, subsection)
203 : CALL keyword_create(keyword, __LOCATION__, name="_SECTION_PARAMETERS_", &
204 : description="Level starting at which this property is printed", &
205 : usage="silent", &
206 : default_i_val=my_print_level, lone_keyword_i_val=silent_print_level, &
207 : enum_c_vals=s2a("on", "off", "silent", "low", "medium", "high", "debug"), &
208 : enum_i_vals=(/silent_print_level - 1, debug_print_level + 1, &
209 : silent_print_level, low_print_level, &
210 5272039 : medium_print_level, high_print_level, debug_print_level/))
211 5272039 : CALL section_add_keyword(print_key_section, keyword)
212 5272039 : CALL keyword_release(keyword)
213 :
214 : CALL keyword_create(keyword, __LOCATION__, name="__CONTROL_VAL", &
215 : description=' hidden parameter that controls storage, printing,...'// &
216 : ' of the print_key', &
217 5272039 : default_i_val=cp_out_default)
218 5272039 : CALL section_add_keyword(print_key_section, keyword)
219 5272039 : CALL keyword_release(keyword)
220 :
221 : CALL section_create(subsection, __LOCATION__, name="EACH", &
222 : description="This section specifies how often this property is printed."// &
223 : "Each keyword inside this section is mapping to a specific iteration level and "// &
224 : "the value of each of these keywords is matched with the iteration level during "// &
225 : "the calculation. How to handle the last iteration is treated "// &
226 : "separately in ADD_LAST (this mean that each iteration level (MD, GEO_OPT, etc..), "// &
227 : "though equal to 0, might print the last iteration). If an iteration level is specified "// &
228 : "that is not present in the flow of the calculation it is just ignored.", &
229 : n_keywords=2, n_subsections=0, repeats=.FALSE., &
230 10386726 : citations=citations)
231 :
232 : ! Enforce the presence or absence of both.. or give an error
233 5272039 : check = (PRESENT(each_iter_names)) .EQV. (PRESENT(each_iter_values))
234 5272039 : CPASSERT(check)
235 5272039 : ext_each = (PRESENT(each_iter_names)) .AND. (PRESENT(each_iter_values))
236 :
237 100168741 : DO i_each = 1, SIZE(each_possible_labels)
238 94896702 : my_value = 1
239 94896702 : IF (ext_each) THEN
240 15974640 : check = SUM(INDEX(each_iter_names, each_possible_labels(i_each))) <= 1
241 6500160 : CPASSERT(check)
242 15974640 : DO i_iter = 1, SIZE(each_iter_names)
243 15974640 : IF (INDEX(TRIM(each_iter_names(i_iter)), TRIM(each_possible_labels(i_each))) /= 0) THEN
244 498820 : my_value = each_iter_values(i_iter)
245 : END IF
246 : END DO
247 : END IF
248 : CALL keyword_create(keyword, __LOCATION__, name=TRIM(each_possible_labels(i_each)), &
249 : description=TRIM(each_desc_labels(i_each)), &
250 : usage=TRIM(each_possible_labels(i_each))//" <INTEGER>", &
251 94896702 : default_i_val=my_value)
252 94896702 : CALL section_add_keyword(subsection, keyword)
253 100168741 : CALL keyword_release(keyword)
254 : END DO
255 5272039 : CALL section_add_subsection(print_key_section, subsection)
256 5272039 : CALL section_release(subsection)
257 :
258 5272039 : my_add_last = add_last_no
259 5272039 : IF (PRESENT(add_last)) THEN
260 2058593 : my_add_last = add_last
261 : END IF
262 : CALL keyword_create(keyword, __LOCATION__, name="ADD_LAST", &
263 : description="If the last iteration should be added, and if it "// &
264 : "should be marked symbolically (with lowercase letter l) or with "// &
265 : "the iteration number. "// &
266 : "Not every iteration level is able to identify the last iteration "// &
267 : "early enough to be able to output. When this keyword is activated "// &
268 : "all iteration levels are checked for the last iteration step.", &
269 : usage="ADD_LAST (NO|NUMERIC|SYMBOLIC)", &
270 : enum_c_vals=s2a("no", "numeric", "symbolic"), &
271 : enum_i_vals=(/add_last_no, add_last_numeric, add_last_symbolic/), &
272 : enum_desc=s2a("Do not mark last iteration specifically", &
273 : "Mark last iteration with its iteration number", &
274 : "Mark last iteration with lowercase letter l"), &
275 5272039 : default_i_val=my_add_last)
276 5272039 : CALL section_add_keyword(print_key_section, keyword)
277 5272039 : CALL keyword_release(keyword)
278 :
279 5272039 : my_comm_iter_levels = 0
280 5272039 : IF (PRESENT(common_iter_levels)) my_comm_iter_levels = common_iter_levels
281 : CALL keyword_create(keyword, __LOCATION__, name="COMMON_ITERATION_LEVELS", &
282 : description="How many iterations levels should be written"// &
283 : " in the same file (no extra information about the actual"// &
284 : " iteration level is written to the file)", &
285 : usage="COMMON_ITERATION_LEVELS <INTEGER>", &
286 5272039 : default_i_val=my_comm_iter_levels)
287 5272039 : CALL section_add_keyword(print_key_section, keyword)
288 5272039 : CALL keyword_release(keyword)
289 :
290 5272039 : my_filename = ""
291 5272039 : IF (PRESENT(filename)) my_filename = filename
292 : CALL keyword_create(keyword, __LOCATION__, name="FILENAME", &
293 : description=' controls part of the filename for output. '// &
294 : ' use __STD_OUT__ (exactly as written here) for the screen or standard logger. '// &
295 : ' use filename to obtain projectname-filename. '// &
296 : ' use ./filename to get filename.'// &
297 : ' A middle name (if present), iteration numbers'// &
298 : ' and extension are always added to the filename.'// &
299 : ' if you want to avoid it use =filename, in this'// &
300 : ' case the filename is always exactly as typed.'// &
301 : ' Please note that this can lead to clashes of'// &
302 : ' filenames.', &
303 : usage="FILENAME ./filename ", &
304 5272039 : default_lc_val=my_filename)
305 5272039 : CALL section_add_keyword(print_key_section, keyword)
306 5272039 : CALL keyword_release(keyword)
307 :
308 : CALL keyword_create(keyword, __LOCATION__, name="LOG_PRINT_KEY", &
309 : description="This keywords enables the logger for the print_key (a message is printed on "// &
310 : "screen everytime data, controlled by this print_key, are written)", &
311 5272039 : usage="LOG_PRINT_KEY <LOGICAL>", default_l_val=.FALSE., lone_keyword_l_val=.TRUE.)
312 5272039 : CALL section_add_keyword(print_key_section, keyword)
313 5272039 : CALL keyword_release(keyword)
314 :
315 5272039 : IF (PRESENT(unit_str)) THEN
316 : CALL keyword_create(keyword, __LOCATION__, name="UNIT", &
317 : description='Specify the unit of measurement for the quantity in output. '// &
318 : "All available CP2K units can be used.", &
319 297696 : usage="UNIT angstrom", default_c_val=TRIM(unit_str))
320 297696 : CALL section_add_keyword(print_key_section, keyword)
321 297696 : CALL keyword_release(keyword)
322 : END IF
323 5272039 : END SUBROUTINE cp_print_key_section_create
324 :
325 : ! **************************************************************************************************
326 : !> \brief returns what should be done with the given property
327 : !> if btest(res,cp_p_store) then the property should be stored in memory
328 : !> if btest(res,cp_p_file) then the property should be print ed to a file
329 : !> if res==0 then nothing should be done
330 : !> \param iteration_info information about the actual iteration level
331 : !> \param basis_section section that contains the printkey
332 : !> \param print_key_path path to the printkey- "%" between sections, and
333 : !> optionally a "/" and a logical flag to check). Might be empty.
334 : !> \param used_print_key here the print_key that was used is returned
335 : !> \param first_time if it ist the first time that an output is written
336 : !> (not fully correct, but most of the time)
337 : !> \return ...
338 : !> \author fawzi
339 : !> \note
340 : !> not all the propreties support can be stored
341 : ! **************************************************************************************************
342 15302112 : FUNCTION cp_print_key_should_output(iteration_info, basis_section, &
343 : print_key_path, used_print_key, first_time) &
344 : RESULT(res)
345 : TYPE(cp_iteration_info_type), INTENT(IN) :: iteration_info
346 : TYPE(section_vals_type), INTENT(IN), TARGET :: basis_section
347 : CHARACTER(len=*), INTENT(IN), OPTIONAL :: print_key_path
348 : TYPE(section_vals_type), INTENT(INOUT), OPTIONAL, &
349 : POINTER :: used_print_key
350 : LOGICAL, INTENT(OUT), OPTIONAL :: first_time
351 : INTEGER :: res
352 :
353 : INTEGER :: end_str, my_control_val, to_path
354 : LOGICAL :: flags, is_iter, is_on
355 : TYPE(section_vals_type), POINTER :: print_key
356 :
357 8183985 : res = 0
358 8183985 : IF (PRESENT(first_time)) first_time = .FALSE.
359 8183985 : CPASSERT(basis_section%ref_count > 0)
360 8183985 : IF (PRESENT(used_print_key)) NULLIFY (used_print_key)
361 :
362 8183985 : IF (PRESENT(print_key_path)) THEN
363 7706919 : end_str = LEN_TRIM(print_key_path)
364 7706919 : to_path = INDEX(print_key_path, "/")
365 7706919 : IF (to_path < 1) THEN
366 6404862 : to_path = end_str + 1
367 : END IF
368 :
369 7706919 : IF (to_path > 1) THEN
370 : print_key => section_vals_get_subs_vals(basis_section, &
371 7544288 : print_key_path(1:(to_path - 1)))
372 : ELSE
373 162631 : print_key => basis_section
374 : END IF
375 7706919 : CPASSERT(ASSOCIATED(print_key))
376 7706919 : CPASSERT(print_key%ref_count > 0)
377 7706919 : IF (to_path + 1 < end_str) THEN
378 : CALL section_vals_val_get(print_key, print_key_path((to_path + 1):end_str), &
379 1302057 : l_val=flags)
380 : ELSE
381 6404862 : flags = .TRUE.
382 : END IF
383 : ELSE
384 477066 : print_key => basis_section
385 477066 : flags = .TRUE.
386 : END IF
387 8183985 : IF (PRESENT(used_print_key)) used_print_key => print_key
388 :
389 8183985 : IF (.NOT. flags) RETURN
390 :
391 : CALL section_vals_val_get(print_key, "__CONTROL_VAL", &
392 7118127 : i_val=my_control_val)
393 7118127 : is_on = cp_printkey_is_on(iteration_info, print_key)
394 :
395 : ! a shortcut for most common case
396 7118127 : IF (my_control_val == cp_out_default .AND. .NOT. is_on) RETURN
397 :
398 2177521 : is_iter = cp_printkey_is_iter(iteration_info, print_key, first_time=first_time)
399 :
400 2177521 : IF (BTEST(my_control_val, cp_p_store)) THEN
401 : res = IBSET(res, cp_p_store)
402 2177521 : ELSE IF (BTEST(my_control_val, cp_p_store_if) .AND. is_iter .AND. is_on) THEN
403 : res = IBSET(res, cp_p_store)
404 2177521 : ELSE IF (BTEST(my_control_val, cp_p_store_each) .AND. is_iter) THEN
405 0 : res = IBSET(res, cp_p_store)
406 : END IF
407 :
408 2177521 : IF (BTEST(my_control_val, cp_p_file)) THEN
409 0 : res = IBSET(res, cp_p_file)
410 2177521 : ELSE IF (BTEST(my_control_val, cp_p_file_if) .AND. is_iter .AND. is_on) THEN
411 1789477 : res = IBSET(res, cp_p_file)
412 388044 : ELSE IF (BTEST(my_control_val, cp_p_file_each) .AND. is_iter) THEN
413 0 : res = IBSET(res, cp_p_file)
414 : END IF
415 2177521 : IF (BTEST(my_control_val, cp_p_calc) .OR. res /= 0) THEN
416 1789477 : res = IBSET(res, cp_p_calc)
417 : END IF
418 : END FUNCTION cp_print_key_should_output
419 :
420 : ! **************************************************************************************************
421 : !> \brief returns true if the printlevel activates this printkey
422 : !> does not look if this iteration it should be printed
423 : !> \param iteration_info information about the actual iteration level
424 : !> \param print_key the section values of the key to be printed
425 : !> \return ...
426 : !> \author fawzi
427 : ! **************************************************************************************************
428 7124631 : FUNCTION cp_printkey_is_on(iteration_info, print_key) RESULT(res)
429 : TYPE(cp_iteration_info_type), INTENT(IN) :: iteration_info
430 : TYPE(section_vals_type), POINTER :: print_key
431 : LOGICAL :: res
432 :
433 : INTEGER :: print_level
434 :
435 7124631 : CPASSERT(iteration_info%ref_count > 0)
436 7124631 : IF (.NOT. ASSOCIATED(print_key)) THEN
437 0 : res = (iteration_info%print_level > debug_print_level)
438 : ELSE
439 7124631 : CPASSERT(print_key%ref_count > 0)
440 7124631 : CALL section_vals_val_get(print_key, "_SECTION_PARAMETERS_", i_val=print_level)
441 7124631 : res = iteration_info%print_level >= print_level
442 : END IF
443 7124631 : END FUNCTION cp_printkey_is_on
444 :
445 : ! **************************************************************************************************
446 : !> \brief returns if the actual iteration matches those selected by the
447 : !> given printkey. Does not check it the prinkey is active (at the
448 : !> actual print_level)
449 : !> \param iteration_info information about the actual iteration level
450 : !> \param print_key the section values of the key to be printed
451 : !> \param first_time returns if it is the first time that output is written
452 : !> (not fully correct, but most of the time)
453 : !> \return ...
454 : !> \author fawzi
455 : ! **************************************************************************************************
456 2177521 : FUNCTION cp_printkey_is_iter(iteration_info, print_key, first_time) &
457 : RESULT(res)
458 : TYPE(cp_iteration_info_type), INTENT(IN) :: iteration_info
459 : TYPE(section_vals_type), POINTER :: print_key
460 : LOGICAL, INTENT(OUT), OPTIONAL :: first_time
461 : LOGICAL :: res
462 :
463 : INTEGER :: add_last, ilevel, iter_nr, ival
464 : LOGICAL :: first, level_passed
465 :
466 2177521 : CPASSERT(iteration_info%ref_count > 0)
467 2177521 : IF (.NOT. ASSOCIATED(print_key)) THEN
468 0 : res = (iteration_info%print_level > debug_print_level)
469 0 : first = ALL(iteration_info%iteration(1:iteration_info%n_rlevel) == 1)
470 : ELSE
471 2177521 : CPASSERT(print_key%ref_count > 0)
472 2177521 : res = .FALSE.
473 2177521 : first = .FALSE.
474 2177521 : CALL section_vals_val_get(print_key, "ADD_LAST", i_val=add_last)
475 2177521 : res = .TRUE.
476 2177521 : first = .TRUE.
477 6412417 : DO ilevel = 1, iteration_info%n_rlevel
478 4234896 : level_passed = .FALSE.
479 : CALL section_vals_val_get(print_key, "EACH%"//TRIM(iteration_info%level_name(ilevel)), &
480 4234896 : i_val=ival)
481 4234896 : IF (ival > 0) THEN
482 4203524 : iter_nr = iteration_info%iteration(ilevel)
483 4203524 : IF (iter_nr/ival > 1) first = .FALSE.
484 4203524 : IF (MODULO(iter_nr, ival) == 0) THEN
485 3576465 : level_passed = .TRUE.
486 : END IF
487 : END IF
488 4234896 : IF (add_last == add_last_numeric .OR. add_last == add_last_symbolic) THEN
489 2340580 : IF (iteration_info%last_iter(ilevel)) THEN
490 : level_passed = .TRUE.
491 : END IF
492 : END IF
493 6269233 : IF (.NOT. level_passed) res = .FALSE.
494 : END DO
495 : END IF
496 2177521 : first = first .AND. res
497 2177521 : IF (PRESENT(first_time)) first_time = first
498 2177521 : END FUNCTION cp_printkey_is_iter
499 :
500 : ! **************************************************************************************************
501 : !> \brief returns the iteration string, a string that is useful to create
502 : !> unique filenames (once you trim it)
503 : !> \param iter_info the iteration info from where to take the iteration
504 : !> number
505 : !> \param print_key the print key to optionally show the last iteration
506 : !> symbolically
507 : !> \param for_file if the string is to be used for file generation
508 : !> (and should consequently ignore some iteration levels depending
509 : !> on COMMON_ITERATION_LEVELS).
510 : !> Defaults to false.
511 : !> \return ...
512 : !> \author fawzi
513 : !> \note
514 : !> If the root level is 1 removes it
515 : ! **************************************************************************************************
516 96462 : FUNCTION cp_iter_string(iter_info, print_key, for_file) RESULT(res)
517 : TYPE(cp_iteration_info_type), POINTER :: iter_info
518 : TYPE(section_vals_type), OPTIONAL, POINTER :: print_key
519 : LOGICAL, INTENT(IN), OPTIONAL :: for_file
520 : CHARACTER(len=default_string_length) :: res
521 :
522 : INTEGER :: add_last, c_i_level, ilevel, n_rlevel, &
523 : s_level
524 : LOGICAL :: my_for_file
525 : TYPE(section_vals_type), POINTER :: my_print_key
526 :
527 96462 : res = ""
528 96462 : my_for_file = .FALSE.
529 96462 : IF (PRESENT(for_file)) my_for_file = for_file
530 96462 : CPASSERT(ASSOCIATED(iter_info))
531 96462 : CPASSERT(iter_info%ref_count > 0)
532 96462 : NULLIFY (my_print_key)
533 96462 : IF (PRESENT(print_key)) my_print_key => print_key
534 96462 : s_level = 1
535 95123 : IF (ASSOCIATED(my_print_key)) THEN
536 95123 : CALL section_vals_val_get(my_print_key, "ADD_LAST", i_val=add_last)
537 95123 : CALL section_vals_val_get(my_print_key, "COMMON_ITERATION_LEVELS", i_val=c_i_level)
538 95123 : n_rlevel = iter_info%n_rlevel
539 95123 : IF (my_for_file) n_rlevel = MIN(n_rlevel, MAX(0, n_rlevel - c_i_level))
540 171566 : DO ilevel = s_level, n_rlevel
541 171566 : IF (iter_info%last_iter(ilevel)) THEN
542 634 : IF (add_last == add_last_symbolic) THEN
543 0 : WRITE (res(9*ilevel - 8:9*ilevel), "('l_')")
544 : ELSE
545 634 : WRITE (res(9*ilevel - 8:9*ilevel), "(i8,'_')") iter_info%iteration(ilevel)
546 : END IF
547 : ELSE
548 75809 : WRITE (res(9*ilevel - 8:9*ilevel), "(i8,'_')") iter_info%iteration(ilevel)
549 : END IF
550 : END DO
551 : ELSE
552 3636 : DO ilevel = s_level, iter_info%n_rlevel
553 3636 : WRITE (res(9*ilevel - 8:9*ilevel), "(i8,'_')") iter_info%iteration(ilevel)
554 : END DO
555 : END IF
556 96462 : CALL compress(res, .TRUE.)
557 96462 : IF (LEN_TRIM(res) > 0) THEN
558 71944 : res(LEN_TRIM(res):LEN_TRIM(res)) = " "
559 : END IF
560 96462 : END FUNCTION cp_iter_string
561 :
562 : ! **************************************************************************************************
563 : !> \brief adds one to the actual iteration
564 : !> \param iteration_info the iteration info to update
565 : !> \param last if this iteration is the last one (defaults to false)
566 : !> \param iter_nr ...
567 : !> \param increment ...
568 : !> \param iter_nr_out ...
569 : !> \author fawzi
570 : !> \note
571 : !> this is supposed to be called at the beginning of each iteration
572 : ! **************************************************************************************************
573 270992 : SUBROUTINE cp_iterate(iteration_info, last, iter_nr, increment, iter_nr_out)
574 : TYPE(cp_iteration_info_type), POINTER :: iteration_info
575 : LOGICAL, INTENT(IN), OPTIONAL :: last
576 : INTEGER, INTENT(IN), OPTIONAL :: iter_nr, increment
577 : INTEGER, INTENT(OUT), OPTIONAL :: iter_nr_out
578 :
579 : INTEGER :: my_increment
580 : LOGICAL :: my_last
581 :
582 270992 : my_last = .FALSE.
583 270992 : my_increment = 1
584 270992 : IF (PRESENT(last)) my_last = last
585 270992 : IF (PRESENT(increment)) my_increment = increment
586 270992 : IF (PRESENT(iter_nr_out)) iter_nr_out = -1
587 :
588 270992 : CPASSERT(ASSOCIATED(iteration_info))
589 270992 : CPASSERT(iteration_info%ref_count > 0)
590 270992 : IF (PRESENT(iter_nr)) THEN
591 230643 : iteration_info%iteration(iteration_info%n_rlevel) = iter_nr
592 : ELSE
593 : iteration_info%iteration(iteration_info%n_rlevel) = &
594 40349 : iteration_info%iteration(iteration_info%n_rlevel) + my_increment
595 : END IF
596 : ! If requested provide the value of the iteration level
597 270992 : IF (PRESENT(iter_nr_out)) iter_nr_out = iteration_info%iteration(iteration_info%n_rlevel)
598 :
599 : ! Possibly setup the LAST flag
600 270992 : iteration_info%last_iter(iteration_info%n_rlevel) = my_last
601 270992 : END SUBROUTINE cp_iterate
602 :
603 : ! **************************************************************************************************
604 : !> \brief Adds an iteration level
605 : !> \param iteration_info the iteration info to which an iteration level has
606 : !> to be added
607 : !> \param level_name the name of this level, for pretty printing only, right now
608 : !> \param n_rlevel_new number of iteration levels after this call
609 : !> \author fawzi
610 : ! **************************************************************************************************
611 38617 : SUBROUTINE cp_add_iter_level(iteration_info, level_name, n_rlevel_new)
612 : TYPE(cp_iteration_info_type), POINTER :: iteration_info
613 : CHARACTER(LEN=*), INTENT(IN) :: level_name
614 : INTEGER, INTENT(OUT), OPTIONAL :: n_rlevel_new
615 :
616 : INTEGER :: i
617 : LOGICAL :: found
618 :
619 0 : CPASSERT(ASSOCIATED(iteration_info))
620 38617 : CPASSERT(iteration_info%ref_count > 0)
621 38617 : found = .FALSE.
622 222562 : DO i = 1, SIZE(each_possible_labels)
623 222562 : IF (TRIM(level_name) == TRIM(each_possible_labels(i))) THEN
624 : found = .TRUE.
625 : EXIT
626 : END IF
627 : END DO
628 38617 : IF (found) THEN
629 38617 : CALL cp_iteration_info_retain(iteration_info)
630 38617 : iteration_info%n_rlevel = iteration_info%n_rlevel + 1
631 38617 : CALL reallocate(iteration_info%iteration, 1, iteration_info%n_rlevel)
632 38617 : CALL reallocate(iteration_info%level_name, 1, iteration_info%n_rlevel)
633 38617 : CALL reallocate(iteration_info%last_iter, 1, iteration_info%n_rlevel)
634 38617 : iteration_info%iteration(iteration_info%n_rlevel) = 0
635 38617 : iteration_info%level_name(iteration_info%n_rlevel) = level_name
636 38617 : iteration_info%last_iter(iteration_info%n_rlevel) = .FALSE.
637 38617 : IF (PRESENT(n_rlevel_new)) n_rlevel_new = iteration_info%n_rlevel
638 : ELSE
639 : CALL cp_abort(__LOCATION__, &
640 : "Trying to create an iteration level ("//TRIM(level_name)//") not defined."// &
641 0 : "Please update the module: cp_iter_types.")
642 : END IF
643 :
644 38617 : END SUBROUTINE cp_add_iter_level
645 :
646 : ! **************************************************************************************************
647 : !> \brief Removes an iteration level
648 : !> \param iteration_info the iteration info to which an iteration level has
649 : !> to be removed
650 : !> \param level_name level_name to be destroyed (if does not match gives an error)
651 : !> \param n_rlevel_att iteration level before the call (to do some checks)
652 : !> \author fawzi
653 : ! **************************************************************************************************
654 38617 : SUBROUTINE cp_rm_iter_level(iteration_info, level_name, n_rlevel_att)
655 : TYPE(cp_iteration_info_type), POINTER :: iteration_info
656 : CHARACTER(LEN=*), INTENT(IN) :: level_name
657 : INTEGER, INTENT(IN), OPTIONAL :: n_rlevel_att
658 :
659 : LOGICAL :: check
660 :
661 38617 : CPASSERT(ASSOCIATED(iteration_info))
662 38617 : CPASSERT(iteration_info%ref_count > 0)
663 38617 : IF (PRESENT(n_rlevel_att)) THEN
664 4312 : CPASSERT(n_rlevel_att == iteration_info%n_rlevel)
665 : END IF
666 38617 : CALL cp_iteration_info_release(iteration_info)
667 : ! This check that the iteration levels are consistently created and destroyed..
668 : ! Never remove this check..
669 38617 : check = iteration_info%level_name(iteration_info%n_rlevel) == level_name
670 38617 : CPASSERT(check)
671 38617 : iteration_info%n_rlevel = iteration_info%n_rlevel - 1
672 38617 : CALL reallocate(iteration_info%iteration, 1, iteration_info%n_rlevel)
673 38617 : CALL reallocate(iteration_info%level_name, 1, iteration_info%n_rlevel)
674 38617 : CALL reallocate(iteration_info%last_iter, 1, iteration_info%n_rlevel)
675 38617 : END SUBROUTINE cp_rm_iter_level
676 :
677 : ! **************************************************************************************************
678 : !> \brief Utility function that returns a unit number to write the print key.
679 : !> Might open a file with a unique filename, generated from
680 : !> the print_key name and iteration info.
681 : !>
682 : !> Normally a valid unit (>0) is returned only if cp_print_key_should_output
683 : !> says that the print_key should be printed, and if the unit is global
684 : !> only the io node has a valid unit.
685 : !> So in many cases you can decide if you should print just checking if
686 : !> the returned units is bigger than 0.
687 : !>
688 : !> IMPORTANT you should call cp_finished_output when an iteration output is
689 : !> finished (to immediately close the file that might have been opened)
690 : !> \param logger the logger for the parallel environment, iteration info
691 : !> and filename generation
692 : !> \param print_key ...
693 : !> \param middle_name name to be added to the generated filename, useful when
694 : !> print_key activates different distinct outputs, to be able to
695 : !> distinguish them
696 : !> \param extension extension to be applied to the filename (including the ".")
697 : !> \param my_local if the unit should be local to this task, or global to the
698 : !> program (defaults to false).
699 : !> \return ...
700 : !> \author Fawzi Mohamed
701 : ! **************************************************************************************************
702 95659 : FUNCTION cp_print_key_generate_filename(logger, print_key, middle_name, extension, &
703 : my_local) RESULT(filename)
704 : TYPE(cp_logger_type), POINTER :: logger
705 : TYPE(section_vals_type), POINTER :: print_key
706 : CHARACTER(len=*), INTENT(IN), OPTIONAL :: middle_name
707 : CHARACTER(len=*), INTENT(IN) :: extension
708 : LOGICAL, INTENT(IN) :: my_local
709 : CHARACTER(len=default_path_length) :: filename
710 :
711 : CHARACTER(len=default_path_length) :: outPath, postfix, root
712 : CHARACTER(len=default_string_length) :: my_middle_name, outName
713 : INTEGER :: my_ind1, my_ind2
714 : LOGICAL :: has_root
715 :
716 95659 : CALL section_vals_val_get(print_key, "FILENAME", c_val=outPath)
717 95659 : IF (outPath(1:1) == '=') THEN
718 : CPASSERT(LEN(outPath) - 1 <= LEN(filename))
719 597 : filename = outPath(2:)
720 597 : RETURN
721 : END IF
722 95062 : IF (outPath == "__STD_OUT__") outPath = ""
723 95062 : outName = outPath
724 95062 : has_root = .FALSE.
725 95062 : my_ind1 = INDEX(outPath, "/")
726 95062 : my_ind2 = LEN_TRIM(outPath)
727 95062 : IF (my_ind1 /= 0) THEN
728 3726 : has_root = .TRUE.
729 3726 : DO WHILE (INDEX(outPath(my_ind1 + 1:my_ind2), "/") /= 0)
730 3726 : my_ind1 = INDEX(outPath(my_ind1 + 1:my_ind2), "/") + my_ind1
731 : END DO
732 3726 : IF (my_ind1 == my_ind2) THEN
733 0 : outName = ""
734 : ELSE
735 3726 : outName = outPath(my_ind1 + 1:my_ind2)
736 : END IF
737 : END IF
738 :
739 95062 : IF (PRESENT(middle_name)) THEN
740 38090 : IF (outName /= "") THEN
741 606 : my_middle_name = "-"//TRIM(outName)//"-"//middle_name
742 : ELSE
743 37484 : my_middle_name = "-"//middle_name
744 : END IF
745 : ELSE
746 56972 : IF (outName /= "") THEN
747 22884 : my_middle_name = "-"//TRIM(outName)
748 : ELSE
749 34088 : my_middle_name = ""
750 : END IF
751 : END IF
752 :
753 95062 : IF (.NOT. has_root) THEN
754 91336 : root = TRIM(logger%iter_info%project_name)//TRIM(my_middle_name)
755 3726 : ELSE IF (outName == "") THEN
756 0 : root = outPath(1:my_ind1)//TRIM(logger%iter_info%project_name)//TRIM(my_middle_name)
757 : ELSE
758 3726 : root = outPath(1:my_ind1)//my_middle_name(2:LEN_TRIM(my_middle_name))
759 : END IF
760 :
761 : ! use the cp_iter_string as a postfix
762 95062 : postfix = "-"//TRIM(cp_iter_string(logger%iter_info, print_key=print_key, for_file=.TRUE.))
763 95062 : IF (TRIM(postfix) == "-") postfix = ""
764 :
765 : ! and add the extension
766 95062 : postfix = TRIM(postfix)//extension
767 : ! and let the logger generate the filename
768 : CALL cp_logger_generate_filename(logger, res=filename, &
769 95062 : root=root, postfix=postfix, local=my_local)
770 :
771 : END FUNCTION cp_print_key_generate_filename
772 :
773 : ! **************************************************************************************************
774 : !> \brief ...
775 : !> \param logger ...
776 : !> \param basis_section ...
777 : !> \param print_key_path ...
778 : !> \param extension ...
779 : !> \param middle_name ...
780 : !> \param local ...
781 : !> \param log_filename ...
782 : !> \param ignore_should_output ...
783 : !> \param file_form ...
784 : !> \param file_position ...
785 : !> \param file_action ...
786 : !> \param file_status ...
787 : !> \param do_backup ...
788 : !> \param on_file ...
789 : !> \param is_new_file true if this rank created a new (or rewound) file, false otherwise
790 : !> \param mpi_io True if the file should be opened in parallel on all processors belonging to
791 : !> the communicator group. Automatically disabled if the file form or access mode
792 : !> is unsuitable for MPI IO. Return value indicates whether MPI was actually used
793 : !> and therefore the flag must also be passed to the file closing directive.
794 : !> \param fout Name of the actual file where the output will be written. Needed mainly for MPI IO
795 : !> because inquiring the filename from the MPI filehandle does not work across
796 : !> all MPI libraries.
797 : !> \return ...
798 : ! **************************************************************************************************
799 2819222 : FUNCTION cp_print_key_unit_nr(logger, basis_section, print_key_path, extension, &
800 : middle_name, local, log_filename, ignore_should_output, file_form, file_position, &
801 : file_action, file_status, do_backup, on_file, is_new_file, mpi_io, &
802 : fout) RESULT(res)
803 : TYPE(cp_logger_type), POINTER :: logger
804 : TYPE(section_vals_type), INTENT(IN) :: basis_section
805 : CHARACTER(len=*), INTENT(IN), OPTIONAL :: print_key_path
806 : CHARACTER(len=*), INTENT(IN) :: extension
807 : CHARACTER(len=*), INTENT(IN), OPTIONAL :: middle_name
808 : LOGICAL, INTENT(IN), OPTIONAL :: local, log_filename, ignore_should_output
809 : CHARACTER(len=*), INTENT(IN), OPTIONAL :: file_form, file_position, file_action, &
810 : file_status
811 : LOGICAL, INTENT(IN), OPTIONAL :: do_backup, on_file
812 : LOGICAL, INTENT(OUT), OPTIONAL :: is_new_file
813 : LOGICAL, INTENT(INOUT), OPTIONAL :: mpi_io
814 : CHARACTER(len=default_path_length), INTENT(OUT), &
815 : OPTIONAL :: fout
816 : INTEGER :: res
817 :
818 : CHARACTER(len=default_path_length) :: filename, filename_bak, filename_bak_1, &
819 : filename_bak_2
820 : CHARACTER(len=default_string_length) :: my_file_action, my_file_form, &
821 : my_file_position, my_file_status, &
822 : outPath
823 : INTEGER :: c_i_level, f_backup_level, i, mpi_amode, &
824 : my_backup_level, my_nbak, nbak, &
825 : s_backup_level, unit_nr
826 : LOGICAL :: do_log, found, my_do_backup, my_local, &
827 : my_mpi_io, my_on_file, &
828 : my_should_output, replace
829 : TYPE(cp_iteration_info_type), POINTER :: iteration_info
830 : TYPE(mp_file_type) :: mp_unit
831 : TYPE(section_vals_type), POINTER :: print_key
832 :
833 2819222 : my_local = .FALSE.
834 2819222 : my_do_backup = .FALSE.
835 2819222 : my_mpi_io = .FALSE.
836 2819222 : replace = .FALSE.
837 2819222 : found = .FALSE.
838 2819222 : res = -1
839 2819222 : my_file_form = "FORMATTED"
840 2819222 : my_file_position = "APPEND"
841 2819222 : my_file_action = "WRITE"
842 2819222 : my_file_status = "UNKNOWN"
843 2819222 : my_on_file = .FALSE.
844 2819222 : mpi_amode = 0
845 357655 : IF (PRESENT(file_form)) my_file_form = file_form
846 2819222 : IF (PRESENT(file_position)) my_file_position = file_position
847 2819222 : IF (PRESENT(file_action)) my_file_action = file_action
848 2819222 : IF (PRESENT(file_status)) my_file_status = file_status
849 2819222 : IF (PRESENT(do_backup)) my_do_backup = do_backup
850 2819222 : IF (PRESENT(on_file)) my_on_file = on_file
851 2819222 : IF (PRESENT(local)) my_local = local
852 2819222 : IF (PRESENT(is_new_file)) is_new_file = .FALSE.
853 2819222 : IF (PRESENT(mpi_io)) THEN
854 : #if defined(__parallel)
855 1664 : IF (cp_mpi_io_get() .AND. logger%para_env%num_pe > 1 .AND. mpi_io) THEN
856 : my_mpi_io = .TRUE.
857 : ELSE
858 : my_mpi_io = .FALSE.
859 : END IF
860 : IF (my_mpi_io) THEN
861 : CALL mp_file_get_amode(mpi_io, replace, mpi_amode, TRIM(my_file_form), &
862 1664 : TRIM(my_file_action), TRIM(my_file_status), TRIM(my_file_position))
863 3166 : replace = replace .AND. logger%para_env%is_source()
864 : END IF
865 : #else
866 : my_mpi_io = .FALSE.
867 : #endif
868 : ! Set return value
869 1664 : mpi_io = my_mpi_io
870 : END IF
871 2819222 : NULLIFY (print_key)
872 2819222 : CPASSERT(ASSOCIATED(logger))
873 2819222 : CPASSERT(basis_section%ref_count > 0)
874 2819222 : CPASSERT(logger%ref_count > 0)
875 : my_should_output = BTEST(cp_print_key_should_output(logger%iter_info, &
876 2823356 : basis_section, print_key_path, used_print_key=print_key), cp_p_file)
877 2819222 : IF (PRESENT(ignore_should_output)) my_should_output = my_should_output .OR. ignore_should_output
878 2819222 : IF (.NOT. my_should_output) RETURN
879 : IF (my_local .OR. &
880 915967 : logger%para_env%is_source() .OR. &
881 : my_mpi_io) THEN
882 :
883 482462 : CALL section_vals_val_get(print_key, "FILENAME", c_val=outPath)
884 482462 : IF (outPath == '__STD_OUT__' .AND. .NOT. my_on_file) THEN
885 394613 : res = cp_logger_get_default_unit_nr(logger, local=my_local)
886 : ELSE
887 : !
888 : ! complex logic to build filename:
889 : ! 1) Try to avoid '--' and '-.'
890 : ! 2) If outPath contains '/' (as in ./filename) do not prepend the project_name
891 : !
892 : ! if it is actually a full path, use it as the root
893 : filename = cp_print_key_generate_filename(logger, print_key, middle_name, extension, &
894 198821 : my_local)
895 : ! Give back info about a possible existence of the file if required
896 87849 : IF (PRESENT(is_new_file)) THEN
897 49446 : INQUIRE (FILE=filename, EXIST=found)
898 49446 : is_new_file = .NOT. found
899 49446 : IF (my_file_position == "REWIND") is_new_file = .TRUE.
900 : END IF
901 : ! Check is we have to log any operation performed on the file..
902 : do_log = .FALSE.
903 87849 : IF (PRESENT(log_filename)) THEN
904 1870 : do_log = log_filename
905 : ELSE
906 85979 : CALL section_vals_val_get(print_key, "LOG_PRINT_KEY", l_val=do_log)
907 : END IF
908 : ! If required do a backup
909 87849 : IF (my_do_backup) THEN
910 16877 : INQUIRE (FILE=filename, EXIST=found)
911 16877 : CALL section_vals_val_get(print_key, "BACKUP_COPIES", i_val=nbak)
912 16877 : IF (nbak /= 0) THEN
913 14933 : iteration_info => logger%iter_info
914 14933 : s_backup_level = 0
915 14933 : IF (ASSOCIATED(print_key%ibackup)) s_backup_level = SIZE(print_key%ibackup)
916 14933 : CALL section_vals_val_get(print_key, "COMMON_ITERATION_LEVELS", i_val=c_i_level)
917 14933 : my_backup_level = MAX(1, iteration_info%n_rlevel - c_i_level + 1)
918 14933 : f_backup_level = MAX(s_backup_level, my_backup_level)
919 14933 : IF (f_backup_level > s_backup_level) THEN
920 3714 : CALL reallocate(print_key%ibackup, 1, f_backup_level)
921 8732 : DO i = s_backup_level + 1, f_backup_level
922 8732 : print_key%ibackup(i) = 0
923 : END DO
924 : END IF
925 14933 : IF (found) THEN
926 12325 : print_key%ibackup(my_backup_level) = print_key%ibackup(my_backup_level) + 1
927 12325 : my_nbak = print_key%ibackup(my_backup_level)
928 : ! Recent backup copies correspond to lower backup indexes
929 12337 : DO i = MIN(nbak, my_nbak), 2, -1
930 12 : filename_bak_1 = TRIM(filename)//".bak-"//ADJUSTL(cp_to_string(i))
931 12 : filename_bak_2 = TRIM(filename)//".bak-"//ADJUSTL(cp_to_string(i - 1))
932 12 : IF (do_log) THEN
933 12 : unit_nr = cp_logger_get_unit_nr(logger, local=my_local)
934 12 : IF (unit_nr > 0) &
935 : WRITE (unit_nr, *) "Moving file "//TRIM(filename_bak_2)// &
936 12 : " into file "//TRIM(filename_bak_1)//"."
937 : END IF
938 12 : INQUIRE (FILE=filename_bak_2, EXIST=found)
939 12337 : IF (.NOT. found) THEN
940 0 : IF (do_log) THEN
941 0 : unit_nr = cp_logger_get_unit_nr(logger, local=my_local)
942 0 : IF (unit_nr > 0) &
943 0 : WRITE (unit_nr, *) "File "//TRIM(filename_bak_2)//" not existing.."
944 : END IF
945 : ELSE
946 12 : CALL m_mov(TRIM(filename_bak_2), TRIM(filename_bak_1))
947 : END IF
948 : END DO
949 : ! The last backup is always the one with index 1
950 12325 : filename_bak = TRIM(filename)//".bak-"//ADJUSTL(cp_to_string(1))
951 12325 : IF (do_log) THEN
952 95 : unit_nr = cp_logger_get_unit_nr(logger, local=my_local)
953 95 : IF (unit_nr > 0) &
954 95 : WRITE (unit_nr, *) "Moving file "//TRIM(filename)//" into file "//TRIM(filename_bak)//"."
955 : END IF
956 12325 : CALL m_mov(TRIM(filename), TRIM(filename_bak))
957 : ELSE
958 : ! Zero the backup history for this new iteration level..
959 2608 : print_key%ibackup(my_backup_level) = 0
960 : END IF
961 : END IF
962 : END IF
963 :
964 87849 : IF (.NOT. my_mpi_io) THEN
965 : CALL open_file(file_name=filename, file_status=my_file_status, &
966 : file_form=my_file_form, file_action=my_file_action, &
967 86185 : file_position=my_file_position, unit_number=res)
968 : ELSE
969 1664 : IF (replace) CALL mp_file_delete(filename)
970 : CALL mp_unit%open(groupid=logger%para_env, &
971 1664 : filepath=filename, amode_status=mpi_amode)
972 1664 : IF (PRESENT(fout)) fout = filename
973 1664 : res = mp_unit%get_handle()
974 : END IF
975 87849 : IF (do_log) THEN
976 105 : unit_nr = cp_logger_get_unit_nr(logger, local=my_local)
977 105 : IF (unit_nr > 0) &
978 : WRITE (unit_nr, *) "Writing "//TRIM(print_key%section%name)//" "// &
979 : TRIM(cp_iter_string(logger%iter_info))//" to "// &
980 105 : TRIM(filename)
981 : END IF
982 : END IF
983 : ELSE
984 433505 : res = -1
985 : END IF
986 3735189 : END FUNCTION cp_print_key_unit_nr
987 :
988 : ! **************************************************************************************************
989 : !> \brief should be called after you finish working with a unit obtained with
990 : !> cp_print_key_unit_nr, so that the file that might have been opened
991 : !> can be closed.
992 : !>
993 : !> the inputs should be exactly the same of the corresponding
994 : !> cp_print_key_unit_nr
995 : !> \param unit_nr ...
996 : !> \param logger ...
997 : !> \param basis_section ...
998 : !> \param print_key_path ...
999 : !> \param local ...
1000 : !> \param ignore_should_output ...
1001 : !> \param on_file ...
1002 : !> \param mpi_io True if file was opened in parallel with MPI
1003 : !> \par History
1004 : !> 08.2002 created [fawzi]
1005 : !> \author Fawzi Mohamed
1006 : !> \note
1007 : !> closes if the corresponding filename of the printkey is
1008 : !> not __STD_OUT__
1009 : ! **************************************************************************************************
1010 2583920 : SUBROUTINE cp_print_key_finished_output(unit_nr, logger, basis_section, &
1011 : print_key_path, local, ignore_should_output, on_file, &
1012 : mpi_io)
1013 : INTEGER, INTENT(INOUT) :: unit_nr
1014 : TYPE(cp_logger_type), POINTER :: logger
1015 : TYPE(section_vals_type), INTENT(IN) :: basis_section
1016 : CHARACTER(len=*), INTENT(IN), OPTIONAL :: print_key_path
1017 : LOGICAL, INTENT(IN), OPTIONAL :: local, ignore_should_output, on_file, &
1018 : mpi_io
1019 :
1020 : CHARACTER(len=default_string_length) :: outPath
1021 : LOGICAL :: my_local, my_mpi_io, my_on_file, &
1022 : my_should_output
1023 : TYPE(mp_file_type) :: mp_unit
1024 : TYPE(section_vals_type), POINTER :: print_key
1025 :
1026 2583920 : my_local = .FALSE.
1027 2583920 : my_on_file = .FALSE.
1028 2583920 : my_mpi_io = .FALSE.
1029 2583920 : NULLIFY (print_key)
1030 2290 : IF (PRESENT(local)) my_local = local
1031 2583920 : IF (PRESENT(on_file)) my_on_file = on_file
1032 2583920 : IF (PRESENT(mpi_io)) my_mpi_io = mpi_io
1033 2583920 : CPASSERT(ASSOCIATED(logger))
1034 2583920 : CPASSERT(basis_section%ref_count > 0)
1035 2583920 : CPASSERT(logger%ref_count > 0)
1036 : my_should_output = BTEST(cp_print_key_should_output(logger%iter_info, basis_section, &
1037 2634104 : print_key_path, used_print_key=print_key), cp_p_file)
1038 2583920 : IF (PRESENT(ignore_should_output)) my_should_output = my_should_output .OR. ignore_should_output
1039 2583920 : IF (my_should_output .AND. (my_local .OR. &
1040 : logger%para_env%is_source() .OR. &
1041 : my_mpi_io)) THEN
1042 372180 : CALL section_vals_val_get(print_key, "FILENAME", c_val=outPath)
1043 372180 : IF (my_on_file .OR. outPath .NE. '__STD_OUT__') THEN
1044 86296 : CPASSERT(unit_nr > 0)
1045 86296 : IF (.NOT. my_mpi_io) THEN
1046 84632 : CALL close_file(unit_nr, "KEEP")
1047 : ELSE
1048 1664 : CALL mp_unit%set_handle(unit_nr)
1049 1664 : CALL mp_unit%close()
1050 : END IF
1051 86296 : unit_nr = -1
1052 : ELSE
1053 285884 : unit_nr = -1
1054 : END IF
1055 : END IF
1056 2583920 : CPASSERT(unit_nr == -1)
1057 2583920 : unit_nr = -1
1058 2583920 : END SUBROUTINE cp_print_key_finished_output
1059 :
1060 : ! **************************************************************************************************
1061 : !> \brief Sets flag which determines whether or not to use MPI I/O for I/O routines that
1062 : !> have been parallized with MPI
1063 : !> \param flag ...
1064 : !> \par History
1065 : !> 09.2018 created [Nico Holmberg]
1066 : ! **************************************************************************************************
1067 8859 : SUBROUTINE cp_mpi_io_set(flag)
1068 : LOGICAL, INTENT(IN) :: flag
1069 :
1070 8859 : enable_mpi_io = flag
1071 8859 : END SUBROUTINE cp_mpi_io_set
1072 :
1073 : ! **************************************************************************************************
1074 : !> \brief Gets flag which determines whether or not to use MPI I/O for I/O routines that
1075 : !> have been parallized with MPI
1076 : !> \return ...
1077 : !> \par History
1078 : !> 09.2018 created [Nico Holmberg]
1079 : ! **************************************************************************************************
1080 1702 : FUNCTION cp_mpi_io_get() RESULT(flag)
1081 : LOGICAL :: flag
1082 :
1083 1702 : flag = enable_mpi_io
1084 1702 : END FUNCTION cp_mpi_io_get
1085 :
1086 0 : END MODULE cp_output_handling
|