(git:d18deda)
Loading...
Searching...
No Matches
cp_output_handling.F
Go to the documentation of this file.
1!--------------------------------------------------------------------------------------------------!
2! CP2K: A general program to perform molecular dynamics simulations !
3! Copyright 2000-2025 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! **************************************************************************************************
26 USE cp_files, ONLY: close_file,&
49 USE kinds, ONLY: default_path_length,&
51 USE machine, ONLY: m_mov
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'
69
70 INTEGER, PARAMETER, PUBLIC :: add_last_no = 0, &
71 add_last_numeric = 1, &
73 INTEGER, PARAMETER, PUBLIC :: silent_print_level = 0, &
74 low_print_level = 1, &
76 high_print_level = 3, &
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, &
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), &
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
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
150CONTAINS
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 SUBROUTINE cp_print_key_section_create(print_key_section, location, name, description, &
172 print_level, each_iter_names, each_iter_values, add_last, filename, &
173 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 cpassert(.NOT. ASSOCIATED(print_key_section))
195 my_print_level = debug_print_level
196 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 citations=citations)
201
202 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, &
211 CALL section_add_keyword(print_key_section, keyword)
212 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 default_i_val=cp_out_default)
218 CALL section_add_keyword(print_key_section, keyword)
219 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 citations=citations)
231
232 ! Enforce the presence or absence of both.. or give an error
233 check = (PRESENT(each_iter_names)) .EQV. (PRESENT(each_iter_values))
234 cpassert(check)
235 ext_each = (PRESENT(each_iter_names)) .AND. (PRESENT(each_iter_values))
236
237 DO i_each = 1, SIZE(each_possible_labels)
238 my_value = 1
239 IF (ext_each) THEN
240 check = sum(index(each_iter_names, each_possible_labels(i_each))) <= 1
241 cpassert(check)
242 DO i_iter = 1, SIZE(each_iter_names)
243 IF (index(trim(each_iter_names(i_iter)), trim(each_possible_labels(i_each))) /= 0) THEN
244 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 default_i_val=my_value)
252 CALL section_add_keyword(subsection, keyword)
253 CALL keyword_release(keyword)
254 END DO
255 CALL section_add_subsection(print_key_section, subsection)
256 CALL section_release(subsection)
257
258 my_add_last = add_last_no
259 IF (PRESENT(add_last)) THEN
260 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"), &
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 default_i_val=my_add_last)
276 CALL section_add_keyword(print_key_section, keyword)
277 CALL keyword_release(keyword)
278
279 my_comm_iter_levels = 0
280 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 default_i_val=my_comm_iter_levels)
287 CALL section_add_keyword(print_key_section, keyword)
288 CALL keyword_release(keyword)
289
290 my_filename = ""
291 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 default_lc_val=my_filename)
305 CALL section_add_keyword(print_key_section, keyword)
306 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 usage="LOG_PRINT_KEY <LOGICAL>", default_l_val=.false., lone_keyword_l_val=.true.)
312 CALL section_add_keyword(print_key_section, keyword)
313 CALL keyword_release(keyword)
314
315 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 usage="UNIT angstrom", default_c_val=trim(unit_str))
320 CALL section_add_keyword(print_key_section, keyword)
321 CALL keyword_release(keyword)
322 END IF
323 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 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 res = 0
358 IF (PRESENT(first_time)) first_time = .false.
359 cpassert(basis_section%ref_count > 0)
360 IF (PRESENT(used_print_key)) NULLIFY (used_print_key)
361
362 IF (PRESENT(print_key_path)) THEN
363 end_str = len_trim(print_key_path)
364 to_path = index(print_key_path, "/")
365 IF (to_path < 1) THEN
366 to_path = end_str + 1
367 END IF
368
369 IF (to_path > 1) THEN
370 print_key => section_vals_get_subs_vals(basis_section, &
371 print_key_path(1:(to_path - 1)))
372 ELSE
373 print_key => basis_section
374 END IF
375 cpassert(ASSOCIATED(print_key))
376 cpassert(print_key%ref_count > 0)
377 IF (to_path + 1 < end_str) THEN
378 CALL section_vals_val_get(print_key, print_key_path((to_path + 1):end_str), &
379 l_val=flags)
380 ELSE
381 flags = .true.
382 END IF
383 ELSE
384 print_key => basis_section
385 flags = .true.
386 END IF
387 IF (PRESENT(used_print_key)) used_print_key => print_key
388
389 IF (.NOT. flags) RETURN
390
391 CALL section_vals_val_get(print_key, "__CONTROL_VAL", &
392 i_val=my_control_val)
393 is_on = cp_printkey_is_on(iteration_info, print_key)
394
395 ! a shortcut for most common case
396 IF (my_control_val == cp_out_default .AND. .NOT. is_on) RETURN
397
398 is_iter = cp_printkey_is_iter(iteration_info, print_key, first_time=first_time)
399
400 IF (btest(my_control_val, cp_p_store)) THEN
401 res = ibset(res, cp_p_store)
402 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 ELSE IF (btest(my_control_val, cp_p_store_each) .AND. is_iter) THEN
405 res = ibset(res, cp_p_store)
406 END IF
407
408 IF (btest(my_control_val, cp_p_file)) THEN
409 res = ibset(res, cp_p_file)
410 ELSE IF (btest(my_control_val, cp_p_file_if) .AND. is_iter .AND. is_on) THEN
411 res = ibset(res, cp_p_file)
412 ELSE IF (btest(my_control_val, cp_p_file_each) .AND. is_iter) THEN
413 res = ibset(res, cp_p_file)
414 END IF
415 IF (btest(my_control_val, cp_p_calc) .OR. res /= 0) THEN
416 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 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 cpassert(iteration_info%ref_count > 0)
436 IF (.NOT. ASSOCIATED(print_key)) THEN
437 res = (iteration_info%print_level > debug_print_level)
438 ELSE
439 cpassert(print_key%ref_count > 0)
440 CALL section_vals_val_get(print_key, "_SECTION_PARAMETERS_", i_val=print_level)
441 res = iteration_info%print_level >= print_level
442 END IF
443 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 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 cpassert(iteration_info%ref_count > 0)
467 IF (.NOT. ASSOCIATED(print_key)) THEN
468 res = (iteration_info%print_level > debug_print_level)
469 first = all(iteration_info%iteration(1:iteration_info%n_rlevel) == 1)
470 ELSE
471 cpassert(print_key%ref_count > 0)
472 res = .false.
473 first = .false.
474 CALL section_vals_val_get(print_key, "ADD_LAST", i_val=add_last)
475 res = .true.
476 first = .true.
477 DO ilevel = 1, iteration_info%n_rlevel
478 level_passed = .false.
479 CALL section_vals_val_get(print_key, "EACH%"//trim(iteration_info%level_name(ilevel)), &
480 i_val=ival)
481 IF (ival > 0) THEN
482 iter_nr = iteration_info%iteration(ilevel)
483 IF (iter_nr/ival > 1) first = .false.
484 IF (modulo(iter_nr, ival) == 0) THEN
485 level_passed = .true.
486 END IF
487 END IF
488 IF (add_last == add_last_numeric .OR. add_last == add_last_symbolic) THEN
489 IF (iteration_info%last_iter(ilevel)) THEN
490 level_passed = .true.
491 END IF
492 END IF
493 IF (.NOT. level_passed) res = .false.
494 END DO
495 END IF
496 first = first .AND. res
497 IF (PRESENT(first_time)) first_time = first
498 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 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 res = ""
528 my_for_file = .false.
529 IF (PRESENT(for_file)) my_for_file = for_file
530 cpassert(ASSOCIATED(iter_info))
531 cpassert(iter_info%ref_count > 0)
532 NULLIFY (my_print_key)
533 IF (PRESENT(print_key)) my_print_key => print_key
534 s_level = 1
535 IF (ASSOCIATED(my_print_key)) THEN
536 CALL section_vals_val_get(my_print_key, "ADD_LAST", i_val=add_last)
537 CALL section_vals_val_get(my_print_key, "COMMON_ITERATION_LEVELS", i_val=c_i_level)
538 n_rlevel = iter_info%n_rlevel
539 IF (my_for_file) n_rlevel = min(n_rlevel, max(0, n_rlevel - c_i_level))
540 DO ilevel = s_level, n_rlevel
541 IF (iter_info%last_iter(ilevel)) THEN
542 IF (add_last == add_last_symbolic) THEN
543 WRITE (res(9*ilevel - 8:9*ilevel), "('l_')")
544 ELSE
545 WRITE (res(9*ilevel - 8:9*ilevel), "(i8,'_')") iter_info%iteration(ilevel)
546 END IF
547 ELSE
548 WRITE (res(9*ilevel - 8:9*ilevel), "(i8,'_')") iter_info%iteration(ilevel)
549 END IF
550 END DO
551 ELSE
552 DO ilevel = s_level, iter_info%n_rlevel
553 WRITE (res(9*ilevel - 8:9*ilevel), "(i8,'_')") iter_info%iteration(ilevel)
554 END DO
555 END IF
556 CALL compress(res, .true.)
557 IF (len_trim(res) > 0) THEN
558 res(len_trim(res):len_trim(res)) = " "
559 END IF
560 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 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 my_last = .false.
583 my_increment = 1
584 IF (PRESENT(last)) my_last = last
585 IF (PRESENT(increment)) my_increment = increment
586 IF (PRESENT(iter_nr_out)) iter_nr_out = -1
587
588 cpassert(ASSOCIATED(iteration_info))
589 cpassert(iteration_info%ref_count > 0)
590 IF (PRESENT(iter_nr)) THEN
591 iteration_info%iteration(iteration_info%n_rlevel) = iter_nr
592 ELSE
593 iteration_info%iteration(iteration_info%n_rlevel) = &
594 iteration_info%iteration(iteration_info%n_rlevel) + my_increment
595 END IF
596 ! If requested provide the value of the iteration level
597 IF (PRESENT(iter_nr_out)) iter_nr_out = iteration_info%iteration(iteration_info%n_rlevel)
598
599 ! Possibly setup the LAST flag
600 iteration_info%last_iter(iteration_info%n_rlevel) = my_last
601 END SUBROUTINE cp_iterate
602
603! **************************************************************************************************
604!> \brief Return the index of an iteration level by its name.
605!> \param iteration_info the iteration info to query
606!> \param level_name level name to query.
607!> \return iteration level index or 0 if there is no such level
608!> \author Sergey Chulkov
609! **************************************************************************************************
610 FUNCTION cp_get_iter_level_by_name(iteration_info, level_name) RESULT(rlevel)
611 TYPE(cp_iteration_info_type), INTENT(IN), POINTER :: iteration_info
612 CHARACTER(LEN=*), INTENT(IN) :: level_name
613 INTEGER :: rlevel
614
615 cpassert(ASSOCIATED(iteration_info))
616 cpassert(iteration_info%ref_count > 0)
617 DO rlevel = iteration_info%n_rlevel, 1, -1
618 IF (iteration_info%level_name(rlevel) == level_name) EXIT
619 END DO
620
621 END FUNCTION cp_get_iter_level_by_name
622
623! **************************************************************************************************
624!> \brief Return the current iteration number at a given level.
625!> \param iteration_info the iteration info to query
626!> \param rlevel index of the iteration level. Use the level on top of the stack,
627!> if it is not given
628!> \param iter_nr iteration number [out]
629!> \param last_iter last iteration flag [out]
630!> \author Sergey Chulkov
631! **************************************************************************************************
632 SUBROUTINE cp_get_iter_nr(iteration_info, rlevel, iter_nr, last_iter)
633 TYPE(cp_iteration_info_type), INTENT(IN), POINTER :: iteration_info
634 INTEGER, INTENT(IN), OPTIONAL :: rlevel
635 INTEGER, INTENT(OUT), OPTIONAL :: iter_nr
636 LOGICAL, INTENT(OUT), OPTIONAL :: last_iter
637
638 INTEGER :: ilevel
639
640 cpassert(ASSOCIATED(iteration_info))
641 cpassert(iteration_info%ref_count > 0)
642 IF (PRESENT(rlevel)) THEN
643 cpassert(rlevel > 0 .AND. rlevel <= iteration_info%n_rlevel)
644 ilevel = rlevel
645 ELSE
646 ilevel = iteration_info%n_rlevel
647 END IF
648
649 IF (PRESENT(iter_nr)) iter_nr = iteration_info%iteration(ilevel)
650 IF (PRESENT(last_iter)) last_iter = iteration_info%last_iter(ilevel)
651 END SUBROUTINE cp_get_iter_nr
652
653! **************************************************************************************************
654!> \brief Adds an iteration level
655!> \param iteration_info the iteration info to which an iteration level has
656!> to be added
657!> \param level_name the name of this level, for pretty printing only, right now
658!> \param n_rlevel_new number of iteration levels after this call
659!> \author fawzi
660! **************************************************************************************************
661 SUBROUTINE cp_add_iter_level(iteration_info, level_name, n_rlevel_new)
662 TYPE(cp_iteration_info_type), POINTER :: iteration_info
663 CHARACTER(LEN=*), INTENT(IN) :: level_name
664 INTEGER, INTENT(OUT), OPTIONAL :: n_rlevel_new
665
666 INTEGER :: i
667 LOGICAL :: found
668
669 cpassert(ASSOCIATED(iteration_info))
670 cpassert(iteration_info%ref_count > 0)
671 found = .false.
672 DO i = 1, SIZE(each_possible_labels)
673 IF (trim(level_name) == trim(each_possible_labels(i))) THEN
674 found = .true.
675 EXIT
676 END IF
677 END DO
678 IF (found) THEN
679 CALL cp_iteration_info_retain(iteration_info)
680 iteration_info%n_rlevel = iteration_info%n_rlevel + 1
681 CALL reallocate(iteration_info%iteration, 1, iteration_info%n_rlevel)
682 CALL reallocate(iteration_info%level_name, 1, iteration_info%n_rlevel)
683 CALL reallocate(iteration_info%last_iter, 1, iteration_info%n_rlevel)
684 iteration_info%iteration(iteration_info%n_rlevel) = 0
685 iteration_info%level_name(iteration_info%n_rlevel) = level_name
686 iteration_info%last_iter(iteration_info%n_rlevel) = .false.
687 IF (PRESENT(n_rlevel_new)) n_rlevel_new = iteration_info%n_rlevel
688 ELSE
689 CALL cp_abort(__location__, &
690 "Trying to create an iteration level ("//trim(level_name)//") not defined. "// &
691 "Please update the module: cp_iter_types.")
692 END IF
693
694 END SUBROUTINE cp_add_iter_level
695
696! **************************************************************************************************
697!> \brief Removes an iteration level
698!> \param iteration_info the iteration info to which an iteration level has
699!> to be removed
700!> \param level_name level_name to be destroyed (if does not match gives an error)
701!> \param n_rlevel_att iteration level before the call (to do some checks)
702!> \author fawzi
703! **************************************************************************************************
704 SUBROUTINE cp_rm_iter_level(iteration_info, level_name, n_rlevel_att)
705 TYPE(cp_iteration_info_type), POINTER :: iteration_info
706 CHARACTER(LEN=*), INTENT(IN) :: level_name
707 INTEGER, INTENT(IN), OPTIONAL :: n_rlevel_att
708
709 LOGICAL :: check
710
711 cpassert(ASSOCIATED(iteration_info))
712 cpassert(iteration_info%ref_count > 0)
713 IF (PRESENT(n_rlevel_att)) THEN
714 cpassert(n_rlevel_att == iteration_info%n_rlevel)
715 END IF
716 CALL cp_iteration_info_release(iteration_info)
717 ! This check that the iteration levels are consistently created and destroyed..
718 ! Never remove this check..
719 check = iteration_info%level_name(iteration_info%n_rlevel) == level_name
720 cpassert(check)
721 iteration_info%n_rlevel = iteration_info%n_rlevel - 1
722 CALL reallocate(iteration_info%iteration, 1, iteration_info%n_rlevel)
723 CALL reallocate(iteration_info%level_name, 1, iteration_info%n_rlevel)
724 CALL reallocate(iteration_info%last_iter, 1, iteration_info%n_rlevel)
725 END SUBROUTINE cp_rm_iter_level
726
727! **************************************************************************************************
728!> \brief Utility function that returns a unit number to write the print key.
729!> Might open a file with a unique filename, generated from
730!> the print_key name and iteration info.
731!>
732!> Normally a valid unit (>0) is returned only if cp_print_key_should_output
733!> says that the print_key should be printed, and if the unit is global
734!> only the io node has a valid unit.
735!> So in many cases you can decide if you should print just checking if
736!> the returned units is bigger than 0.
737!>
738!> IMPORTANT you should call cp_finished_output when an iteration output is
739!> finished (to immediately close the file that might have been opened)
740!> \param logger the logger for the parallel environment, iteration info
741!> and filename generation
742!> \param print_key ...
743!> \param middle_name name to be added to the generated filename, useful when
744!> print_key activates different distinct outputs, to be able to
745!> distinguish them
746!> \param extension extension to be applied to the filename (including the ".")
747!> \param my_local if the unit should be local to this task, or global to the
748!> program (defaults to false).
749!> \return ...
750!> \author Fawzi Mohamed
751! **************************************************************************************************
752 FUNCTION cp_print_key_generate_filename(logger, print_key, middle_name, extension, &
753 my_local) RESULT(filename)
754 TYPE(cp_logger_type), POINTER :: logger
755 TYPE(section_vals_type), POINTER :: print_key
756 CHARACTER(len=*), INTENT(IN), OPTIONAL :: middle_name
757 CHARACTER(len=*), INTENT(IN) :: extension
758 LOGICAL, INTENT(IN) :: my_local
759 CHARACTER(len=default_path_length) :: filename
760
761 CHARACTER(len=default_path_length) :: outpath, postfix, root
762 CHARACTER(len=default_string_length) :: my_middle_name, outname
763 INTEGER :: my_ind1, my_ind2
764 LOGICAL :: has_root
765
766 CALL section_vals_val_get(print_key, "FILENAME", c_val=outpath)
767 IF (outpath(1:1) == '=') THEN
768 cpassert(len(outpath) - 1 <= len(filename))
769 filename = outpath(2:)
770 RETURN
771 END IF
772 IF (outpath == "__STD_OUT__") outpath = ""
773 outname = outpath
774 has_root = .false.
775 my_ind1 = index(outpath, "/")
776 my_ind2 = len_trim(outpath)
777 IF (my_ind1 /= 0) THEN
778 has_root = .true.
779 DO WHILE (index(outpath(my_ind1 + 1:my_ind2), "/") /= 0)
780 my_ind1 = index(outpath(my_ind1 + 1:my_ind2), "/") + my_ind1
781 END DO
782 IF (my_ind1 == my_ind2) THEN
783 outname = ""
784 ELSE
785 outname = outpath(my_ind1 + 1:my_ind2)
786 END IF
787 END IF
788
789 IF (PRESENT(middle_name)) THEN
790 IF (outname /= "") THEN
791 my_middle_name = "-"//trim(outname)//"-"//middle_name
792 ELSE
793 my_middle_name = "-"//middle_name
794 END IF
795 ELSE
796 IF (outname /= "") THEN
797 my_middle_name = "-"//trim(outname)
798 ELSE
799 my_middle_name = ""
800 END IF
801 END IF
802
803 IF (.NOT. has_root) THEN
804 root = trim(logger%iter_info%project_name)//trim(my_middle_name)
805 ELSE IF (outname == "") THEN
806 root = outpath(1:my_ind1)//trim(logger%iter_info%project_name)//trim(my_middle_name)
807 ELSE
808 root = outpath(1:my_ind1)//my_middle_name(2:len_trim(my_middle_name))
809 END IF
810
811 ! use the cp_iter_string as a postfix
812 postfix = "-"//trim(cp_iter_string(logger%iter_info, print_key=print_key, for_file=.true.))
813 IF (trim(postfix) == "-") postfix = ""
814
815 ! and add the extension
816 postfix = trim(postfix)//extension
817 ! and let the logger generate the filename
818 CALL cp_logger_generate_filename(logger, res=filename, &
819 root=root, postfix=postfix, local=my_local)
820
822
823! **************************************************************************************************
824!> \brief ...
825!> \param logger ...
826!> \param basis_section ...
827!> \param print_key_path ...
828!> \param extension ...
829!> \param middle_name ...
830!> \param local ...
831!> \param log_filename ...
832!> \param ignore_should_output ...
833!> \param file_form ...
834!> \param file_position ...
835!> \param file_action ...
836!> \param file_status ...
837!> \param do_backup ...
838!> \param on_file ...
839!> \param is_new_file true if this rank created a new (or rewound) file, false otherwise
840!> \param mpi_io True if the file should be opened in parallel on all processors belonging to
841!> the communicator group. Automatically disabled if the file form or access mode
842!> is unsuitable for MPI IO. Return value indicates whether MPI was actually used
843!> and therefore the flag must also be passed to the file closing directive.
844!> \param fout Name of the actual file where the output will be written. Needed mainly for MPI IO
845!> because inquiring the filename from the MPI filehandle does not work across
846!> all MPI libraries.
847!> \return ...
848! **************************************************************************************************
849 FUNCTION cp_print_key_unit_nr(logger, basis_section, print_key_path, extension, &
850 middle_name, local, log_filename, ignore_should_output, file_form, file_position, &
851 file_action, file_status, do_backup, on_file, is_new_file, mpi_io, &
852 fout) RESULT(res)
853 TYPE(cp_logger_type), POINTER :: logger
854 TYPE(section_vals_type), INTENT(IN) :: basis_section
855 CHARACTER(len=*), INTENT(IN), OPTIONAL :: print_key_path
856 CHARACTER(len=*), INTENT(IN) :: extension
857 CHARACTER(len=*), INTENT(IN), OPTIONAL :: middle_name
858 LOGICAL, INTENT(IN), OPTIONAL :: local, log_filename, ignore_should_output
859 CHARACTER(len=*), INTENT(IN), OPTIONAL :: file_form, file_position, file_action, &
860 file_status
861 LOGICAL, INTENT(IN), OPTIONAL :: do_backup, on_file
862 LOGICAL, INTENT(OUT), OPTIONAL :: is_new_file
863 LOGICAL, INTENT(INOUT), OPTIONAL :: mpi_io
864 CHARACTER(len=default_path_length), INTENT(OUT), &
865 OPTIONAL :: fout
866 INTEGER :: res
867
868 CHARACTER(len=default_path_length) :: filename, filename_bak, filename_bak_1, &
869 filename_bak_2
870 CHARACTER(len=default_string_length) :: my_file_action, my_file_form, &
871 my_file_position, my_file_status, &
872 outpath
873 INTEGER :: c_i_level, f_backup_level, i, mpi_amode, &
874 my_backup_level, my_nbak, nbak, &
875 s_backup_level, unit_nr
876 LOGICAL :: do_log, found, my_do_backup, my_local, &
877 my_mpi_io, my_on_file, &
878 my_should_output, replace
879 TYPE(cp_iteration_info_type), POINTER :: iteration_info
880 TYPE(mp_file_type) :: mp_unit
881 TYPE(section_vals_type), POINTER :: print_key
882
883 my_local = .false.
884 my_do_backup = .false.
885 my_mpi_io = .false.
886 replace = .false.
887 found = .false.
888 res = -1
889 my_file_form = "FORMATTED"
890 my_file_position = "APPEND"
891 my_file_action = "WRITE"
892 my_file_status = "UNKNOWN"
893 my_on_file = .false.
894 mpi_amode = 0
895 IF (PRESENT(file_form)) my_file_form = file_form
896 IF (PRESENT(file_position)) my_file_position = file_position
897 IF (PRESENT(file_action)) my_file_action = file_action
898 IF (PRESENT(file_status)) my_file_status = file_status
899 IF (PRESENT(do_backup)) my_do_backup = do_backup
900 IF (PRESENT(on_file)) my_on_file = on_file
901 IF (PRESENT(local)) my_local = local
902 IF (PRESENT(is_new_file)) is_new_file = .false.
903 IF (PRESENT(mpi_io)) THEN
904#if defined(__parallel)
905 IF (cp_mpi_io_get() .AND. logger%para_env%num_pe > 1 .AND. mpi_io) THEN
906 my_mpi_io = .true.
907 ELSE
908 my_mpi_io = .false.
909 END IF
910 IF (my_mpi_io) THEN
911 CALL mp_file_get_amode(mpi_io, replace, mpi_amode, trim(my_file_form), &
912 trim(my_file_action), trim(my_file_status), trim(my_file_position))
913 replace = replace .AND. logger%para_env%is_source()
914 END IF
915#else
916 my_mpi_io = .false.
917#endif
918 ! Set return value
919 mpi_io = my_mpi_io
920 END IF
921 NULLIFY (print_key)
922 cpassert(ASSOCIATED(logger))
923 cpassert(basis_section%ref_count > 0)
924 cpassert(logger%ref_count > 0)
925 my_should_output = btest(cp_print_key_should_output(logger%iter_info, &
926 basis_section, print_key_path, used_print_key=print_key), cp_p_file)
927 IF (PRESENT(ignore_should_output)) my_should_output = my_should_output .OR. ignore_should_output
928 IF (.NOT. my_should_output) RETURN
929 IF (my_local .OR. &
930 logger%para_env%is_source() .OR. &
931 my_mpi_io) THEN
932
933 CALL section_vals_val_get(print_key, "FILENAME", c_val=outpath)
934 IF (outpath == '__STD_OUT__' .AND. .NOT. my_on_file) THEN
935 res = cp_logger_get_default_unit_nr(logger, local=my_local)
936 ELSE
937 !
938 ! complex logic to build filename:
939 ! 1) Try to avoid '--' and '-.'
940 ! 2) If outPath contains '/' (as in ./filename) do not prepend the project_name
941 !
942 ! if it is actually a full path, use it as the root
943 filename = cp_print_key_generate_filename(logger, print_key, middle_name, extension, &
944 my_local)
945 ! Give back info about a possible existence of the file if required
946 IF (PRESENT(is_new_file)) THEN
947 INQUIRE (file=filename, exist=found)
948 is_new_file = .NOT. found
949 IF (my_file_position == "REWIND") is_new_file = .true.
950 END IF
951 ! Check is we have to log any operation performed on the file..
952 do_log = .false.
953 IF (PRESENT(log_filename)) THEN
954 do_log = log_filename
955 ELSE
956 CALL section_vals_val_get(print_key, "LOG_PRINT_KEY", l_val=do_log)
957 END IF
958 ! If required do a backup
959 IF (my_do_backup) THEN
960 INQUIRE (file=filename, exist=found)
961 CALL section_vals_val_get(print_key, "BACKUP_COPIES", i_val=nbak)
962 IF (nbak /= 0) THEN
963 iteration_info => logger%iter_info
964 s_backup_level = 0
965 IF (ASSOCIATED(print_key%ibackup)) s_backup_level = SIZE(print_key%ibackup)
966 CALL section_vals_val_get(print_key, "COMMON_ITERATION_LEVELS", i_val=c_i_level)
967 my_backup_level = max(1, iteration_info%n_rlevel - c_i_level + 1)
968 f_backup_level = max(s_backup_level, my_backup_level)
969 IF (f_backup_level > s_backup_level) THEN
970 CALL reallocate(print_key%ibackup, 1, f_backup_level)
971 DO i = s_backup_level + 1, f_backup_level
972 print_key%ibackup(i) = 0
973 END DO
974 END IF
975 IF (found) THEN
976 print_key%ibackup(my_backup_level) = print_key%ibackup(my_backup_level) + 1
977 my_nbak = print_key%ibackup(my_backup_level)
978 ! Recent backup copies correspond to lower backup indexes
979 DO i = min(nbak, my_nbak), 2, -1
980 filename_bak_1 = trim(filename)//".bak-"//adjustl(cp_to_string(i))
981 filename_bak_2 = trim(filename)//".bak-"//adjustl(cp_to_string(i - 1))
982 IF (do_log) THEN
983 unit_nr = cp_logger_get_unit_nr(logger, local=my_local)
984 IF (unit_nr > 0) &
985 WRITE (unit_nr, *) "Moving file "//trim(filename_bak_2)// &
986 " into file "//trim(filename_bak_1)//"."
987 END IF
988 INQUIRE (file=filename_bak_2, exist=found)
989 IF (.NOT. found) THEN
990 IF (do_log) THEN
991 unit_nr = cp_logger_get_unit_nr(logger, local=my_local)
992 IF (unit_nr > 0) &
993 WRITE (unit_nr, *) "File "//trim(filename_bak_2)//" not existing.."
994 END IF
995 ELSE
996 CALL m_mov(trim(filename_bak_2), trim(filename_bak_1))
997 END IF
998 END DO
999 ! The last backup is always the one with index 1
1000 filename_bak = trim(filename)//".bak-"//adjustl(cp_to_string(1))
1001 IF (do_log) THEN
1002 unit_nr = cp_logger_get_unit_nr(logger, local=my_local)
1003 IF (unit_nr > 0) &
1004 WRITE (unit_nr, *) "Moving file "//trim(filename)//" into file "//trim(filename_bak)//"."
1005 END IF
1006 CALL m_mov(trim(filename), trim(filename_bak))
1007 ELSE
1008 ! Zero the backup history for this new iteration level..
1009 print_key%ibackup(my_backup_level) = 0
1010 END IF
1011 END IF
1012 END IF
1013
1014 IF (.NOT. my_mpi_io) THEN
1015 CALL open_file(file_name=filename, file_status=my_file_status, &
1016 file_form=my_file_form, file_action=my_file_action, &
1017 file_position=my_file_position, unit_number=res)
1018 ELSE
1019 IF (replace) CALL mp_file_delete(filename)
1020 CALL mp_unit%open(groupid=logger%para_env, &
1021 filepath=filename, amode_status=mpi_amode)
1022 IF (PRESENT(fout)) fout = filename
1023 res = mp_unit%get_handle()
1024 END IF
1025 IF (do_log) THEN
1026 unit_nr = cp_logger_get_unit_nr(logger, local=my_local)
1027 IF (unit_nr > 0) &
1028 WRITE (unit_nr, *) "Writing "//trim(print_key%section%name)//" "// &
1029 trim(cp_iter_string(logger%iter_info))//" to "// &
1030 trim(filename)
1031 END IF
1032 END IF
1033 ELSE
1034 res = -1
1035 END IF
1036 END FUNCTION cp_print_key_unit_nr
1037
1038! **************************************************************************************************
1039!> \brief should be called after you finish working with a unit obtained with
1040!> cp_print_key_unit_nr, so that the file that might have been opened
1041!> can be closed.
1042!>
1043!> the inputs should be exactly the same of the corresponding
1044!> cp_print_key_unit_nr
1045!> \param unit_nr ...
1046!> \param logger ...
1047!> \param basis_section ...
1048!> \param print_key_path ...
1049!> \param local ...
1050!> \param ignore_should_output ...
1051!> \param on_file ...
1052!> \param mpi_io True if file was opened in parallel with MPI
1053!> \par History
1054!> 08.2002 created [fawzi]
1055!> \author Fawzi Mohamed
1056!> \note
1057!> closes if the corresponding filename of the printkey is
1058!> not __STD_OUT__
1059! **************************************************************************************************
1060 SUBROUTINE cp_print_key_finished_output(unit_nr, logger, basis_section, &
1061 print_key_path, local, ignore_should_output, on_file, &
1062 mpi_io)
1063 INTEGER, INTENT(INOUT) :: unit_nr
1064 TYPE(cp_logger_type), POINTER :: logger
1065 TYPE(section_vals_type), INTENT(IN) :: basis_section
1066 CHARACTER(len=*), INTENT(IN), OPTIONAL :: print_key_path
1067 LOGICAL, INTENT(IN), OPTIONAL :: local, ignore_should_output, on_file, &
1068 mpi_io
1069
1070 CHARACTER(len=default_string_length) :: outpath
1071 LOGICAL :: my_local, my_mpi_io, my_on_file, &
1072 my_should_output
1073 TYPE(mp_file_type) :: mp_unit
1074 TYPE(section_vals_type), POINTER :: print_key
1075
1076 my_local = .false.
1077 my_on_file = .false.
1078 my_mpi_io = .false.
1079 NULLIFY (print_key)
1080 IF (PRESENT(local)) my_local = local
1081 IF (PRESENT(on_file)) my_on_file = on_file
1082 IF (PRESENT(mpi_io)) my_mpi_io = mpi_io
1083 cpassert(ASSOCIATED(logger))
1084 cpassert(basis_section%ref_count > 0)
1085 cpassert(logger%ref_count > 0)
1086 my_should_output = btest(cp_print_key_should_output(logger%iter_info, basis_section, &
1087 print_key_path, used_print_key=print_key), cp_p_file)
1088 IF (PRESENT(ignore_should_output)) my_should_output = my_should_output .OR. ignore_should_output
1089 IF (my_should_output .AND. (my_local .OR. &
1090 logger%para_env%is_source() .OR. &
1091 my_mpi_io)) THEN
1092 CALL section_vals_val_get(print_key, "FILENAME", c_val=outpath)
1093 IF (my_on_file .OR. outpath .NE. '__STD_OUT__') THEN
1094 cpassert(unit_nr > 0)
1095 IF (.NOT. my_mpi_io) THEN
1096 CALL close_file(unit_nr, "KEEP")
1097 ELSE
1098 CALL mp_unit%set_handle(unit_nr)
1099 CALL mp_unit%close()
1100 END IF
1101 unit_nr = -1
1102 ELSE
1103 unit_nr = -1
1104 END IF
1105 END IF
1106 cpassert(unit_nr == -1)
1107 unit_nr = -1
1108 END SUBROUTINE cp_print_key_finished_output
1109
1110! **************************************************************************************************
1111!> \brief Sets flag which determines whether or not to use MPI I/O for I/O routines that
1112!> have been parallized with MPI
1113!> \param flag ...
1114!> \par History
1115!> 09.2018 created [Nico Holmberg]
1116! **************************************************************************************************
1117 SUBROUTINE cp_mpi_io_set(flag)
1118 LOGICAL, INTENT(IN) :: flag
1119
1120 enable_mpi_io = flag
1121 END SUBROUTINE cp_mpi_io_set
1122
1123! **************************************************************************************************
1124!> \brief Gets flag which determines whether or not to use MPI I/O for I/O routines that
1125!> have been parallized with MPI
1126!> \return ...
1127!> \par History
1128!> 09.2018 created [Nico Holmberg]
1129! **************************************************************************************************
1130 FUNCTION cp_mpi_io_get() RESULT(flag)
1131 LOGICAL :: flag
1132
1133 flag = enable_mpi_io
1134 END FUNCTION cp_mpi_io_get
1135
1136END MODULE cp_output_handling
static GRID_HOST_DEVICE int modulo(int a, int m)
Equivalent of Fortran's MODULO, which always return a positive number. https://gcc....
Utility routines to open and close files. Tracking of preconnections.
Definition cp_files.F:16
subroutine, public open_file(file_name, file_status, file_form, file_action, file_position, file_pad, unit_number, debug, skip_get_unit_number, file_access)
Opens the requested file using a free unit number.
Definition cp_files.F:308
subroutine, public close_file(unit_number, file_status, keep_preconnection)
Close an open file given by its logical unit number. Optionally, keep the file and unit preconnected.
Definition cp_files.F:119
Collection of routines to handle the iteration info.
character(len=default_path_length), dimension(18), parameter, public each_possible_labels
subroutine, public cp_iteration_info_retain(iteration_info)
retains the iteration_info (see doc/ReferenceCounting.html)
subroutine, public cp_iteration_info_release(iteration_info)
releases the iteration_info (see doc/ReferenceCounting.html)
character(len=default_path_length), dimension(18), parameter, public each_desc_labels
various routines to log and control the output. The idea is that decisions about where to log should ...
recursive integer function, public cp_logger_get_default_unit_nr(logger, local, skip_not_ionode)
asks the default unit number of the given logger. try to use cp_logger_get_unit_nr
integer function, public cp_logger_get_unit_nr(logger, local)
returns the unit nr for the requested kind of log.
subroutine, public cp_logger_generate_filename(logger, res, root, postfix, local)
generates a unique filename (ie adding eventual suffixes and process ids)
routines to handle the output, The idea is to remove the decision of wheter to output and what to out...
integer, parameter, public cp_out_calc
integer, parameter, public cp_out_file_each
integer, parameter, public cp_p_store_each
character(len=default_string_length) function, public cp_iter_string(iter_info, print_key, for_file)
returns the iteration string, a string that is useful to create unique filenames (once you trim it)
subroutine, public cp_mpi_io_set(flag)
Sets flag which determines whether or not to use MPI I/O for I/O routines that have been parallized w...
integer, parameter, public cp_out_default
integer, parameter, public cp_out_store_if
integer, parameter, public debug_print_level
integer, parameter, public cp_out_store_each
integer, parameter, public cp_p_calc
integer, parameter, public cp_p_store_if
integer function, public cp_print_key_unit_nr(logger, basis_section, print_key_path, extension, middle_name, local, log_filename, ignore_should_output, file_form, file_position, file_action, file_status, do_backup, on_file, is_new_file, mpi_io, fout)
...
integer, parameter, public cp_out_file_if
integer, parameter, public cp_out_store
integer, parameter, public low_print_level
integer, parameter, public medium_print_level
character(len=default_path_length) function, public cp_print_key_generate_filename(logger, print_key, middle_name, extension, my_local)
Utility function that returns a unit number to write the print key. Might open a file with a unique f...
subroutine, public cp_print_key_finished_output(unit_nr, logger, basis_section, print_key_path, local, ignore_should_output, on_file, mpi_io)
should be called after you finish working with a unit obtained with cp_print_key_unit_nr,...
integer, parameter, public cp_p_file
integer, parameter, public cp_out_none
integer, parameter, public high_print_level
logical function, public cp_mpi_io_get()
Gets flag which determines whether or not to use MPI I/O for I/O routines that have been parallized w...
logical function, public cp_printkey_is_on(iteration_info, print_key)
returns true if the printlevel activates this printkey does not look if this iteration it should be p...
subroutine, public cp_iterate(iteration_info, last, iter_nr, increment, iter_nr_out)
adds one to the actual iteration
integer, parameter, public add_last_symbolic
integer, parameter, public cp_p_file_if
subroutine, public cp_rm_iter_level(iteration_info, level_name, n_rlevel_att)
Removes an iteration level.
integer function, public cp_print_key_should_output(iteration_info, basis_section, print_key_path, used_print_key, first_time)
returns what should be done with the given property if btest(res,cp_p_store) then the property should...
integer, parameter, public add_last_numeric
integer, parameter, public silent_print_level
integer function, public cp_get_iter_level_by_name(iteration_info, level_name)
Return the index of an iteration level by its name.
integer, parameter, public cp_out_file
integer, parameter, public cp_p_file_each
integer, parameter, public cp_p_store
integer, parameter, public add_last_no
subroutine, public cp_get_iter_nr(iteration_info, rlevel, iter_nr, last_iter)
Return the current iteration number at a given level.
subroutine, public cp_print_key_section_create(print_key_section, location, name, description, print_level, each_iter_names, each_iter_values, add_last, filename, common_iter_levels, citations, unit_str)
creates a print_key section
subroutine, public cp_add_iter_level(iteration_info, level_name, n_rlevel_new)
Adds an iteration level.
represents keywords in an input
subroutine, public keyword_release(keyword)
releases the given keyword (see doc/ReferenceCounting.html)
subroutine, public keyword_create(keyword, location, name, description, usage, type_of_var, n_var, repeats, variants, default_val, default_l_val, default_r_val, default_lc_val, default_c_val, default_i_val, default_l_vals, default_r_vals, default_c_vals, default_i_vals, lone_keyword_val, lone_keyword_l_val, lone_keyword_r_val, lone_keyword_c_val, lone_keyword_i_val, lone_keyword_l_vals, lone_keyword_r_vals, lone_keyword_c_vals, lone_keyword_i_vals, enum_c_vals, enum_i_vals, enum, enum_strict, enum_desc, unit_str, citations, deprecation_notice, removed)
creates a keyword object
objects that represent the structure of input sections and the data contained in an input section
subroutine, public section_create(section, location, name, description, n_keywords, n_subsections, repeats, citations, deprecation_notice)
creates a list of keywords
subroutine, public section_add_keyword(section, keyword)
adds a keyword to the given section
subroutine, public section_add_subsection(section, subsection)
adds a subsection to the given section
recursive type(section_vals_type) function, pointer, public section_vals_get_subs_vals(section_vals, subsection_name, i_rep_section, can_return_null)
returns the values of the requested subsection
recursive subroutine, public section_release(section)
releases the given keyword list (see doc/ReferenceCounting.html)
subroutine, public section_vals_val_get(section_vals, keyword_name, i_rep_section, i_rep_val, n_rep_val, val, l_val, i_val, r_val, c_val, l_vals, i_vals, r_vals, c_vals, explicit)
returns the requested value
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public default_string_length
Definition kinds.F:57
integer, parameter, public default_path_length
Definition kinds.F:58
Machine interface based on Fortran 2003 and POSIX.
Definition machine.F:17
subroutine, public m_mov(source, target)
...
Definition machine.F:701
Utility routines for the memory handling.
Interface to the message passing library MPI.
subroutine, public mp_file_delete(filepath, info)
Deletes a file. Auxiliary routine to emulate 'replace' action for mp_file_open. Only the master proce...
subroutine, public mp_file_get_amode(mpi_io, replace, amode, form, action, status, position)
(parallel) Utility routine to determine MPI file access mode based on variables
Utilities for string manipulations.
subroutine, public compress(string, full)
Eliminate multiple space characters in a string. If full is .TRUE., then all spaces are eliminated.
contains the information about the current state of the program to be able to decide if output is nec...
type of a logger, at the moment it contains just a print level starting at which level it should be l...
represent a keyword in the input
represent a section of the input file