LCOV - code coverage report
Current view: top level - src/input - cp_output_handling.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:123285f) Lines: 94.7 % 414 392
Test Date: 2026-11-04 00:58:17 Functions: 93.8 % 16 15

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 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              :                                               iter_notice,&
      34              :                                               iter_silent
      35              :    USE cp_log_handling,                 ONLY: cp_logger_generate_filename,&
      36              :                                               cp_logger_get_default_unit_nr,&
      37              :                                               cp_logger_get_unit_nr,&
      38              :                                               cp_logger_type,&
      39              :                                               cp_to_string
      40              :    USE input_keyword_types,             ONLY: keyword_create,&
      41              :                                               keyword_release,&
      42              :                                               keyword_type
      43              :    USE input_section_types,             ONLY: section_add_keyword,&
      44              :                                               section_add_subsection,&
      45              :                                               section_create,&
      46              :                                               section_release,&
      47              :                                               section_type,&
      48              :                                               section_vals_get_subs_vals,&
      49              :                                               section_vals_type,&
      50              :                                               section_vals_val_get
      51              :    USE kinds,                           ONLY: default_path_length,&
      52              :                                               default_string_length
      53              :    USE machine,                         ONLY: m_mov
      54              :    USE memory_utilities,                ONLY: reallocate
      55              :    USE message_passing,                 ONLY: mp_file_delete,&
      56              :                                               mp_file_get_amode,&
      57              :                                               mp_file_type
      58              :    USE string_utilities,                ONLY: compress,&
      59              :                                               newline,&
      60              :                                               s2a
      61              : #include "../base/base_uses.f90"
      62              : 
      63              :    IMPLICIT NONE
      64              :    PRIVATE
      65              : 
      66              :    LOGICAL, PRIVATE, PARAMETER :: debug_this_module = .TRUE.
      67              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'cp_output_handling'
      68              :    PUBLIC :: cp_print_key_should_output, cp_iterate, cp_get_iter_level_by_name, cp_get_iter_nr
      69              :    PUBLIC :: cp_add_iter_level, cp_rm_iter_level
      70              :    PUBLIC :: cp_iter_string, cp_print_key_section_create
      71              :    PUBLIC :: cp_print_key_unit_nr, cp_print_key_finished_output
      72              :    PUBLIC :: cp_print_key_generate_filename, cp_printkey_is_on
      73              : 
      74              :    INTEGER, PARAMETER, PUBLIC               :: add_last_no = 0, &
      75              :                                                add_last_numeric = 1, &
      76              :                                                add_last_symbolic = 2
      77              :    INTEGER, PARAMETER, PUBLIC               :: silent_print_level = 0, &
      78              :                                                low_print_level = 1, &
      79              :                                                medium_print_level = 2, &
      80              :                                                high_print_level = 3, &
      81              :                                                debug_print_level = 4
      82              : 
      83              : !! flags controlling the printing and storing of a property.
      84              : !!
      85              : !! cp_out_none: do not calculate the property
      86              : !! cp_out_file_if  : if the printkey says it calculate and output the property
      87              : !! cp_out_store_if : if the printkey says it calculate and store in memory
      88              : !!                   the property
      89              : !! cp_out_file_each: calculate and output the property with the same periodicity
      90              : !!                   as said in the printkey (irrespective of the activation of
      91              : !!                   the printkey)
      92              : !! cp_out_store_each: calculate and store the property with the same periodicity
      93              : !!                   as said in the printkey (irrespective of the activation of
      94              : !!                   the printkey)
      95              : !! cp_out_file: always calculate and output the property
      96              : !! cp_out_store: always calculate and store in memory the property
      97              : !! cp_out_calc: just calculate the value (independently from the fact that there
      98              : !!              should be output)
      99              : !! cp_out_default: the default value for property flags (cp_out_file_if)
     100              : !!
     101              : !! this flags can be ior-ed together:
     102              : !! ior(cp_out_file_if,cp_out_store_if): if the printkey says it both print
     103              : !!                                          and store the property
     104              : !!
     105              : !! there is no guarantee that a property is not stored if it is not necessary
     106              : !! not all printkeys have a control flag
     107              :    INTEGER, PUBLIC, PARAMETER :: cp_p_file_if = 3, cp_p_store_if = 4, &
     108              :                                  cp_p_store = 2, cp_p_file = 1, cp_p_file_each = 5, cp_p_store_each = 6, cp_p_calc = 7
     109              :    INTEGER, PUBLIC, PARAMETER :: cp_out_none = 0, cp_out_file_if = IBSET(0, cp_p_file_if), &
     110              :                                  cp_out_store_if = IBSET(0, cp_p_store_if), cp_out_file = IBSET(0, cp_p_file), &
     111              :                                  cp_out_store = IBSET(0, cp_p_store), cp_out_calc = IBSET(0, cp_p_calc), &
     112              :                                  cp_out_file_each = IBSET(0, cp_p_file_each), &
     113              :                                  cp_out_store_each = IBSET(0, cp_p_store_each), &
     114              :                                  cp_out_default = cp_out_file_if
     115              : 
     116              : ! Flag determining if MPI I/O should be enabled for functions that support it
     117              :    LOGICAL, PRIVATE, SAVE      :: enable_mpi_io = .FALSE.
     118              : ! Public functions to set/get the flags
     119              :    PUBLIC :: cp_mpi_io_set, cp_mpi_io_get
     120              : 
     121              : CONTAINS
     122              : 
     123              : ! **************************************************************************************************
     124              : !> \brief creates a print_key section
     125              : !> \param print_key_section the print key to create
     126              : !> \param location from where in the source code cp_print_key_section_create() is called
     127              : !> \param name the name of the print key
     128              : !> \param description the description of the print key
     129              : !> \param print_level print level starting at which the printing takes place
     130              : !>        (defaults to debug_print_level)
     131              : !> \param each_iter_names ...
     132              : !> \param each_iter_values ...
     133              : !> \param add_last ...
     134              : !> \param filename ...
     135              : !> \param common_iter_levels ...
     136              : !> \param citations ...
     137              : !> \param unit_str specifies an unit of measure for output quantity. If not
     138              : !>        provided the control is totally left to how the output was coded
     139              : !>        (i.e. USERS have no possibility to change it)
     140              : !> \param do_backup if the BACKUP_COPIES keyword should be added to allow for backup
     141              : !> \author fawzi
     142              : ! **************************************************************************************************
     143      1572159 :    SUBROUTINE cp_print_key_section_create(print_key_section, location, name, description, &
     144      1572159 :                                           print_level, each_iter_names, each_iter_values, add_last, filename, &
     145        37119 :                                           common_iter_levels, citations, unit_str, do_backup)
     146              :       TYPE(section_type), POINTER                        :: print_key_section
     147              :       CHARACTER(len=*), INTENT(IN)                       :: location, name, description
     148              :       INTEGER, INTENT(IN), OPTIONAL                      :: print_level
     149              :       CHARACTER(LEN=*), DIMENSION(:), INTENT(IN), &
     150              :          OPTIONAL                                        :: each_iter_names
     151              :       INTEGER, DIMENSION(:), INTENT(IN), OPTIONAL        :: each_iter_values
     152              :       INTEGER, INTENT(IN), OPTIONAL                      :: add_last
     153              :       CHARACTER(LEN=*), INTENT(IN), OPTIONAL             :: filename
     154              :       INTEGER, INTENT(IN), OPTIONAL                      :: common_iter_levels
     155              :       INTEGER, DIMENSION(:), OPTIONAL                    :: citations
     156              :       CHARACTER(LEN=*), INTENT(IN), OPTIONAL             :: unit_str
     157              :       LOGICAL, OPTIONAL                                  :: do_backup
     158              : 
     159              :       CHARACTER(len=default_path_length)                 :: my_filename
     160              :       INTEGER                                            :: i_each, i_iter, my_add_last, &
     161              :                                                             my_comm_iter_levels, my_print_level, &
     162              :                                                             my_value
     163              :       LOGICAL                                            :: check, ext_each, my_do_backup
     164              :       TYPE(keyword_type), POINTER                        :: keyword
     165              :       TYPE(section_type), POINTER                        :: subsection
     166              : 
     167      1572159 :       CPASSERT(.NOT. ASSOCIATED(print_key_section))
     168      1572159 :       my_print_level = debug_print_level
     169      1572159 :       IF (PRESENT(print_level)) my_print_level = print_level
     170      1572159 :       my_do_backup = .FALSE.
     171      1572159 :       IF (PRESENT(do_backup)) my_do_backup = do_backup
     172              : 
     173              :       CALL section_create(print_key_section, location=location, name=name, description=description, &
     174              :                           n_keywords=2, n_subsections=0, repeats=.FALSE., &
     175      3107199 :                           citations=citations)
     176              : 
     177      1572159 :       NULLIFY (keyword, subsection)
     178              :       CALL keyword_create(keyword, __LOCATION__, name="_SECTION_PARAMETERS_", &
     179              :                           description="Level starting at which this property is printed. "// &
     180              :                           "Printing is activated when the GLOBAL/PRINT_LEVEL of a task is "// &
     181              :                           "higher than or equal to the level as specified here; to override "// &
     182              :                           "this comparison, use ON to always print or OFF to never print. "// &
     183              :                           "Explicitly giving the section without a level or ON or OFF is "// &
     184              :                           "treated as if SILENT is specified, whereas omitting the section "// &
     185              :                           "is treated implicitly using the default value.", &
     186              :                           usage="silent", &
     187              :                           default_i_val=my_print_level, lone_keyword_i_val=silent_print_level, &
     188              :                           enum_c_vals=s2a("on", "off", "silent", "low", "medium", "high", "debug"), &
     189              :                           enum_i_vals=[silent_print_level - 1, debug_print_level + 1, &
     190              :                                        silent_print_level, low_print_level, &
     191      1572159 :                                        medium_print_level, high_print_level, debug_print_level])
     192      1572159 :       CALL section_add_keyword(print_key_section, keyword)
     193      1572159 :       CALL keyword_release(keyword)
     194              : 
     195              :       CALL keyword_create(keyword, __LOCATION__, name="__CONTROL_VAL", &
     196              :                           description=' hidden parameter that controls storage, printing,...'// &
     197              :                           ' of the print_key', &
     198      1572159 :                           default_i_val=cp_out_default)
     199      1572159 :       CALL section_add_keyword(print_key_section, keyword)
     200      1572159 :       CALL keyword_release(keyword)
     201              : 
     202              :       CALL section_create(subsection, __LOCATION__, name="EACH", &
     203              :                           description="This section specifies how often this property is printed. "// &
     204              :                           "Each keyword inside this section is mapping to a specific iteration level and "// &
     205              :                           "the value of each of these keywords is matched with the iteration level during "// &
     206              :                           "the calculation. A value of 0 or negative turns off printing for the iteration "// &
     207              :                           "level. How to handle the last iteration is treated separately in the ADD_LAST "// &
     208              :                           "keyword outside of this section; each iteration level might print the last "// &
     209              :                           "iteration even if the corresponding value is set to 0 or negative. "// &
     210              :                           "If an iteration level is specified that is not present in the flow of "// &
     211              :                           "the calculation, it is just ignored; switch GLOBAL/ITER_LEVEL_VERBOSITY "// &
     212              :                           "to NOTICE or STACK to print information about existing iteration levels.", &
     213              :                           n_keywords=2, n_subsections=0, repeats=.FALSE., &
     214      3107199 :                           citations=citations)
     215              : 
     216              :       ! Enforce the presence or absence of both.. or give an error
     217      1572159 :       check = (PRESENT(each_iter_names)) .EQV. (PRESENT(each_iter_values))
     218      1572159 :       CPASSERT(check)
     219      1572159 :       ext_each = (PRESENT(each_iter_names)) .AND. (PRESENT(each_iter_values))
     220              : 
     221     31443180 :       DO i_each = 1, SIZE(each_possible_labels)
     222     29871021 :          my_value = 1
     223     29871021 :          IF (ext_each) THEN
     224      4195884 :             check = SUM(INDEX(each_iter_names, each_possible_labels(i_each))) <= 1
     225      1611048 :             CPASSERT(check)
     226      4195884 :             DO i_iter = 1, SIZE(each_iter_names)
     227      4195884 :                IF (INDEX(TRIM(each_iter_names(i_iter)), TRIM(each_possible_labels(i_each))) /= 0) THEN
     228       127502 :                   my_value = each_iter_values(i_iter)
     229              :                END IF
     230              :             END DO
     231              :          END IF
     232              :          CALL keyword_create(keyword, __LOCATION__, name=TRIM(each_possible_labels(i_each)), &
     233              :                              description=TRIM(each_desc_labels(i_each)), &
     234              :                              usage=TRIM(each_possible_labels(i_each))//" <INTEGER>", &
     235     29871021 :                              default_i_val=my_value)
     236     29871021 :          CALL section_add_keyword(subsection, keyword)
     237     31443180 :          CALL keyword_release(keyword)
     238              :       END DO
     239      1572159 :       CALL section_add_subsection(print_key_section, subsection)
     240      1572159 :       CALL section_release(subsection)
     241              : 
     242      1572159 :       my_add_last = add_last_no
     243      1572159 :       IF (PRESENT(add_last)) THEN
     244       510516 :          my_add_last = add_last
     245              :       END IF
     246              :       CALL keyword_create(keyword, __LOCATION__, name="ADD_LAST", &
     247              :                           description="If the last iteration should be added, and if it "// &
     248              :                           "should be marked symbolically (with lowercase letter l) or with "// &
     249              :                           "the iteration number. "// &
     250              :                           "Not every iteration level is able to identify the last iteration "// &
     251              :                           "early enough to be able to output. When this keyword is activated "// &
     252              :                           "all iteration levels are checked for the last iteration step.", &
     253              :                           usage="ADD_LAST (NO|NUMERIC|SYMBOLIC)", &
     254              :                           enum_c_vals=s2a("no", "numeric", "symbolic"), &
     255              :                           enum_i_vals=[add_last_no, add_last_numeric, add_last_symbolic], &
     256              :                           enum_desc=s2a("Do not mark last iteration specifically", &
     257              :                                         "Mark last iteration with its iteration number", &
     258              :                                         "Mark last iteration with lowercase letter l"), &
     259      1572159 :                           default_i_val=my_add_last)
     260      1572159 :       CALL section_add_keyword(print_key_section, keyword)
     261      1572159 :       CALL keyword_release(keyword)
     262              : 
     263      1572159 :       my_comm_iter_levels = 0
     264      1572159 :       IF (PRESENT(common_iter_levels)) my_comm_iter_levels = common_iter_levels
     265              :       CALL keyword_create(keyword, __LOCATION__, name="COMMON_ITERATION_LEVELS", &
     266              :                           description="How many iteration levels should be written "// &
     267              :                           "in the same file (no extra information about the actual "// &
     268              :                           "iteration level is written to the file). Set to 0 to use "// &
     269              :                           "the current iteration level, 1 to use the next level, ..., "// &
     270              :                           "in the stack of iteration levels (printed by setting the "// &
     271              :                           "GLOBAL/ITER_LEVEL_VERBOSITY to STACK).", &
     272              :                           usage="COMMON_ITERATION_LEVELS <INTEGER>", &
     273      1572159 :                           default_i_val=my_comm_iter_levels)
     274      1572159 :       CALL section_add_keyword(print_key_section, keyword)
     275      1572159 :       CALL keyword_release(keyword)
     276              : 
     277      1572159 :       my_filename = ""
     278      1572159 :       IF (PRESENT(filename)) my_filename = filename
     279              :       CALL keyword_create(keyword, __LOCATION__, name="FILENAME", &
     280              :                           description="Controls part of the filename for output."//newline//newline// &
     281              :                           "* Use `__STD_OUT__` (exactly as written here) for the screen or "// &
     282              :                           "standard logger (stdout)."//newline// &
     283              :                           "* Use `filename` to obtain `projectname-filename` with "// &
     284              :                           "`projectname` defined by &GLOBAL/PROJECT_NAME."//newline// &
     285              :                           "* Use `./filename` to get a filename with a middle name (if present), "// &
     286              :                           "iteration numbers and extension always added to the filename."//newline// &
     287              :                           "* Use `=filename` to get `filename` always exactly as typed, but "// &
     288              :                           "please note that this can lead to clashes of filenames.", &
     289              :                           usage="FILENAME ./filename ", &
     290      1572159 :                           default_lc_val=my_filename)
     291      1572159 :       CALL section_add_keyword(print_key_section, keyword)
     292      1572159 :       CALL keyword_release(keyword)
     293              : 
     294              :       CALL keyword_create(keyword, __LOCATION__, name="LOG_PRINT_KEY", &
     295              :                           description="This keywords enables the logger for the print_key (a message is printed on "// &
     296              :                           "screen everytime data, controlled by this print_key, are written)", &
     297      1572159 :                           usage="LOG_PRINT_KEY <LOGICAL>", default_l_val=.FALSE., lone_keyword_l_val=.TRUE.)
     298      1572159 :       CALL section_add_keyword(print_key_section, keyword)
     299      1572159 :       CALL keyword_release(keyword)
     300              : 
     301      1572159 :       IF (PRESENT(unit_str)) THEN
     302              :          CALL keyword_create(keyword, __LOCATION__, name="UNIT", &
     303              :                              description='Specify the unit of measurement for the quantity in output. '// &
     304              :                              "All available CP2K units can be used.", &
     305        52869 :                              usage="UNIT angstrom", default_c_val=TRIM(unit_str))
     306        52869 :          CALL section_add_keyword(print_key_section, keyword)
     307        52869 :          CALL keyword_release(keyword)
     308              :       END IF
     309              : 
     310      1572159 :       IF (my_do_backup) THEN
     311              :          CALL keyword_create(keyword, __LOCATION__, name="BACKUP_COPIES", &
     312              :                              description="Specifies the maximum number of backup copies preserved "// &
     313              :                              "when iterations will repeatedly print to the same filename. If set to "// &
     314              :                              "N > 0, the files will be automatically rotated by appending a suffix: "// &
     315              :                              "the most recent print is `{filename}` (defined by FILENAME keyword), "// &
     316              :                              "the last one is moved to `{filename}.bak-1`, the second to last moved "// &
     317              :                              "to `{filename}.bak-2`, ..., up to `{filename}.bak-N`. Set to 0 to "// &
     318              :                              "disable backup preservation and rewrite always the same `{filename}`.", &
     319        33261 :                              usage="BACKUP_COPIES {int}", default_i_val=1)
     320        33261 :          CALL section_add_keyword(print_key_section, keyword)
     321        33261 :          CALL keyword_release(keyword)
     322              :       END IF
     323      1572159 :    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     19345188 :    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     10477533 :       res = 0
     358     10477533 :       IF (PRESENT(first_time)) first_time = .FALSE.
     359     10477533 :       CPASSERT(basis_section%ref_count > 0)
     360     10477533 :       IF (PRESENT(used_print_key)) NULLIFY (used_print_key)
     361              : 
     362     10477533 :       IF (PRESENT(print_key_path)) THEN
     363      9686346 :          end_str = LEN_TRIM(print_key_path)
     364      9686346 :          to_path = INDEX(print_key_path, "/")
     365      9686346 :          IF (to_path < 1) THEN
     366      7694529 :             to_path = end_str + 1
     367              :          END IF
     368              : 
     369      9686346 :          IF (to_path > 1) THEN
     370              :             print_key => section_vals_get_subs_vals(basis_section, &
     371      9403905 :                                                     print_key_path(1:(to_path - 1)))
     372              :          ELSE
     373       282441 :             print_key => basis_section
     374              :          END IF
     375      9686346 :          CPASSERT(ASSOCIATED(print_key))
     376      9686346 :          CPASSERT(print_key%ref_count > 0)
     377      9686346 :          IF (to_path + 1 < end_str) THEN
     378              :             CALL section_vals_val_get(print_key, print_key_path((to_path + 1):end_str), &
     379      1991817 :                                       l_val=flags)
     380              :          ELSE
     381      7694529 :             flags = .TRUE.
     382              :          END IF
     383              :       ELSE
     384       791187 :          print_key => basis_section
     385       791187 :          flags = .TRUE.
     386              :       END IF
     387     10477533 :       IF (PRESENT(used_print_key)) used_print_key => print_key
     388              : 
     389     10477533 :       IF (.NOT. flags) RETURN
     390              : 
     391              :       CALL section_vals_val_get(print_key, "__CONTROL_VAL", &
     392      8867655 :                                 i_val=my_control_val)
     393      8867655 :       is_on = cp_printkey_is_on(iteration_info, print_key)
     394              : 
     395              :       ! a shortcut for most common case
     396      8867655 :       IF (my_control_val == cp_out_default .AND. .NOT. is_on) RETURN
     397              : 
     398      2492902 :       is_iter = cp_printkey_is_iter(iteration_info, print_key, first_time=first_time)
     399              : 
     400      2492902 :       IF (BTEST(my_control_val, cp_p_store)) THEN
     401              :          res = IBSET(res, cp_p_store)
     402      2492902 :       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      2492902 :       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      2492902 :       IF (BTEST(my_control_val, cp_p_file)) THEN
     409            0 :          res = IBSET(res, cp_p_file)
     410      2492902 :       ELSE IF (BTEST(my_control_val, cp_p_file_if) .AND. is_iter .AND. is_on) THEN
     411      1975445 :          res = IBSET(res, cp_p_file)
     412       517457 :       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      2492902 :       IF (BTEST(my_control_val, cp_p_calc) .OR. res /= 0) THEN
     416      1975445 :          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      8901930 :    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      8901930 :       CPASSERT(iteration_info%ref_count > 0)
     436      8901930 :       IF (.NOT. ASSOCIATED(print_key)) THEN
     437            0 :          res = (iteration_info%print_level > debug_print_level)
     438              :       ELSE
     439      8901930 :          CPASSERT(print_key%ref_count > 0)
     440      8901930 :          CALL section_vals_val_get(print_key, "_SECTION_PARAMETERS_", i_val=print_level)
     441      8901930 :          res = iteration_info%print_level >= print_level
     442              :       END IF
     443      8901930 :    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      2492902 :    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      2492902 :       CPASSERT(iteration_info%ref_count > 0)
     467      2492902 :       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      2492902 :          CPASSERT(print_key%ref_count > 0)
     472      2492902 :          res = .FALSE.
     473      2492902 :          first = .FALSE.
     474      2492902 :          CALL section_vals_val_get(print_key, "ADD_LAST", i_val=add_last)
     475      2492902 :          res = .TRUE.
     476      2492902 :          first = .TRUE.
     477      7285945 :          DO ilevel = 1, iteration_info%n_rlevel
     478      4793043 :             level_passed = .FALSE.
     479              :             CALL section_vals_val_get(print_key, "EACH%"//TRIM(iteration_info%level_name(ilevel)), &
     480      4793043 :                                       i_val=ival)
     481      4793043 :             IF (ival > 0) THEN
     482      4779143 :                iter_nr = iteration_info%iteration(ilevel)
     483      4779143 :                IF (iter_nr/ival > 1) first = .FALSE.
     484      4779143 :                IF (MODULO(iter_nr, ival) == 0) THEN
     485      3891025 :                   level_passed = .TRUE.
     486              :                END IF
     487              :             END IF
     488      4793043 :             IF (add_last == add_last_numeric .OR. add_last == add_last_symbolic) THEN
     489      2561247 :                IF (iteration_info%last_iter(ilevel)) THEN
     490              :                   level_passed = .TRUE.
     491              :                END IF
     492              :             END IF
     493      7129114 :             IF (.NOT. level_passed) res = .FALSE.
     494              :          END DO
     495              :       END IF
     496      2492902 :       first = first .AND. res
     497      2492902 :       IF (PRESENT(first_time)) first_time = first
     498      2492902 :    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       107066 :    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       107066 :       res = ""
     528       107066 :       my_for_file = .FALSE.
     529       107066 :       IF (PRESENT(for_file)) my_for_file = for_file
     530       107066 :       CPASSERT(ASSOCIATED(iter_info))
     531       107066 :       CPASSERT(iter_info%ref_count > 0)
     532       107066 :       NULLIFY (my_print_key)
     533       107066 :       IF (PRESENT(print_key)) my_print_key => print_key
     534       107066 :       s_level = 1
     535       105625 :       IF (ASSOCIATED(my_print_key)) THEN
     536       105625 :          CALL section_vals_val_get(my_print_key, "ADD_LAST", i_val=add_last)
     537       105625 :          CALL section_vals_val_get(my_print_key, "COMMON_ITERATION_LEVELS", i_val=c_i_level)
     538       105625 :          n_rlevel = iter_info%n_rlevel
     539       105625 :          IF (my_for_file) n_rlevel = MIN(n_rlevel, MAX(0, n_rlevel - c_i_level))
     540       191765 :          DO ilevel = s_level, n_rlevel
     541       191765 :             IF (iter_info%last_iter(ilevel)) THEN
     542         4097 :                IF (add_last == add_last_symbolic) THEN
     543            0 :                   WRITE (res(9*ilevel - 8:9*ilevel), "('l_')")
     544              :                ELSE
     545         4097 :                   WRITE (res(9*ilevel - 8:9*ilevel), "(i8,'_')") iter_info%iteration(ilevel)
     546              :                END IF
     547              :             ELSE
     548        82043 :                WRITE (res(9*ilevel - 8:9*ilevel), "(i8,'_')") iter_info%iteration(ilevel)
     549              :             END IF
     550              :          END DO
     551              :       ELSE
     552         3920 :          DO ilevel = s_level, iter_info%n_rlevel
     553         3920 :             WRITE (res(9*ilevel - 8:9*ilevel), "(i8,'_')") iter_info%iteration(ilevel)
     554              :          END DO
     555              :       END IF
     556       107066 :       CALL compress(res, .TRUE.)
     557       107066 :       IF (LEN_TRIM(res) > 0) THEN
     558        78021 :          res(LEN_TRIM(res):LEN_TRIM(res)) = " "
     559              :       END IF
     560       107066 :    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       362719 :    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       362719 :       my_last = .FALSE.
     583       362719 :       my_increment = 1
     584       362719 :       IF (PRESENT(last)) my_last = last
     585       362719 :       IF (PRESENT(increment)) my_increment = increment
     586       362719 :       IF (PRESENT(iter_nr_out)) iter_nr_out = -1
     587              : 
     588       362719 :       CPASSERT(ASSOCIATED(iteration_info))
     589       362719 :       CPASSERT(iteration_info%ref_count > 0)
     590       362719 :       IF (PRESENT(iter_nr)) THEN
     591       327523 :          iteration_info%iteration(iteration_info%n_rlevel) = iter_nr
     592              :       ELSE
     593              :          iteration_info%iteration(iteration_info%n_rlevel) = &
     594        35196 :             iteration_info%iteration(iteration_info%n_rlevel) + my_increment
     595              :       END IF
     596              :       ! If requested provide the value of the iteration level
     597       362719 :       IF (PRESENT(iter_nr_out)) iter_nr_out = iteration_info%iteration(iteration_info%n_rlevel)
     598              : 
     599              :       ! Possibly setup the LAST flag
     600       362719 :       iteration_info%last_iter(iteration_info%n_rlevel) = my_last
     601       362719 :    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            0 :    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            0 :       CPASSERT(ASSOCIATED(iteration_info))
     616            0 :       CPASSERT(iteration_info%ref_count > 0)
     617            0 :       DO rlevel = iteration_info%n_rlevel, 1, -1
     618            0 :          IF (iteration_info%level_name(rlevel) == level_name) EXIT
     619              :       END DO
     620              : 
     621            0 :    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        47804 :    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        47804 :       CPASSERT(ASSOCIATED(iteration_info))
     641        47804 :       CPASSERT(iteration_info%ref_count > 0)
     642        47804 :       IF (PRESENT(rlevel)) THEN
     643        47804 :          CPASSERT(rlevel > 0 .AND. rlevel <= iteration_info%n_rlevel)
     644              :          ilevel = rlevel
     645              :       ELSE
     646            0 :          ilevel = iteration_info%n_rlevel
     647              :       END IF
     648              : 
     649        47804 :       IF (PRESENT(iter_nr)) iter_nr = iteration_info%iteration(ilevel)
     650        47804 :       IF (PRESENT(last_iter)) last_iter = iteration_info%last_iter(ilevel)
     651        47804 :    END SUBROUTINE cp_get_iter_nr
     652              : 
     653              : ! **************************************************************************************************
     654              : !> \brief Adds an iteration level
     655              : !> \param logger the logger with 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        47861 :    SUBROUTINE cp_add_iter_level(logger, level_name, n_rlevel_new)
     662              :       TYPE(cp_logger_type), POINTER                      :: logger
     663              :       CHARACTER(LEN=*), INTENT(IN)                       :: level_name
     664              :       INTEGER, INTENT(OUT), OPTIONAL                     :: n_rlevel_new
     665              : 
     666              :       INTEGER                                            :: i
     667              :       LOGICAL                                            :: found
     668              :       TYPE(cp_iteration_info_type), POINTER              :: iteration_info
     669              : 
     670            0 :       CPASSERT(ASSOCIATED(logger))
     671        47861 :       iteration_info => logger%iter_info
     672        47861 :       CPASSERT(ASSOCIATED(iteration_info))
     673        47861 :       CPASSERT(iteration_info%ref_count > 0)
     674        47861 :       found = .FALSE.
     675       257483 :       DO i = 1, SIZE(each_possible_labels)
     676       257483 :          IF (TRIM(level_name) == TRIM(each_possible_labels(i))) THEN
     677              :             found = .TRUE.
     678              :             EXIT
     679              :          END IF
     680              :       END DO
     681        47861 :       IF (found) THEN
     682        47861 :          CALL cp_iteration_info_retain(iteration_info)
     683        47861 :          iteration_info%n_rlevel = iteration_info%n_rlevel + 1
     684        47861 :          CALL reallocate(iteration_info%iteration, 1, iteration_info%n_rlevel)
     685        47861 :          CALL reallocate(iteration_info%level_name, 1, iteration_info%n_rlevel)
     686        47861 :          CALL reallocate(iteration_info%last_iter, 1, iteration_info%n_rlevel)
     687        47861 :          iteration_info%iteration(iteration_info%n_rlevel) = 0
     688        47861 :          iteration_info%level_name(iteration_info%n_rlevel) = level_name
     689        47861 :          iteration_info%last_iter(iteration_info%n_rlevel) = .FALSE.
     690        47861 :          IF (PRESENT(n_rlevel_new)) n_rlevel_new = iteration_info%n_rlevel
     691        47861 :          CALL cp_iter_level_print(logger, "A")
     692              :       ELSE
     693              :          CALL cp_abort(__LOCATION__, &
     694              :                        "Trying to create an iteration level ("//TRIM(level_name)//") not defined. "// &
     695            0 :                        "Please update the module: cp_iter_types.")
     696              :       END IF
     697              : 
     698        47861 :    END SUBROUTINE cp_add_iter_level
     699              : 
     700              : ! **************************************************************************************************
     701              : !> \brief Removes an iteration level
     702              : !> \param logger the logger with the iteration info to which an iteration level has
     703              : !>        to be removed
     704              : !> \param level_name level_name to be destroyed (if does not match gives an error)
     705              : !> \param n_rlevel_att iteration level before the call (to do some checks)
     706              : !> \author fawzi
     707              : ! **************************************************************************************************
     708        47861 :    SUBROUTINE cp_rm_iter_level(logger, level_name, n_rlevel_att)
     709              :       TYPE(cp_logger_type), POINTER                      :: logger
     710              :       CHARACTER(LEN=*), INTENT(IN)                       :: level_name
     711              :       INTEGER, INTENT(IN), OPTIONAL                      :: n_rlevel_att
     712              : 
     713              :       LOGICAL                                            :: check
     714              :       TYPE(cp_iteration_info_type), POINTER              :: iteration_info
     715              : 
     716        47861 :       CPASSERT(ASSOCIATED(logger))
     717        47861 :       iteration_info => logger%iter_info
     718        47861 :       CPASSERT(ASSOCIATED(iteration_info))
     719        47861 :       CPASSERT(iteration_info%ref_count > 0)
     720        47861 :       IF (PRESENT(n_rlevel_att)) THEN
     721         6434 :          CPASSERT(n_rlevel_att == iteration_info%n_rlevel)
     722              :       END IF
     723        47861 :       CALL cp_iter_level_print(logger, "R")
     724        47861 :       CALL cp_iteration_info_release(iteration_info)
     725              :       ! This check that the iteration levels are consistently created and destroyed..
     726              :       ! Never remove this check..
     727        47861 :       check = iteration_info%level_name(iteration_info%n_rlevel) == level_name
     728        47861 :       CPASSERT(check)
     729        47861 :       iteration_info%n_rlevel = iteration_info%n_rlevel - 1
     730        47861 :       CALL reallocate(iteration_info%iteration, 1, iteration_info%n_rlevel)
     731        47861 :       CALL reallocate(iteration_info%level_name, 1, iteration_info%n_rlevel)
     732        47861 :       CALL reallocate(iteration_info%last_iter, 1, iteration_info%n_rlevel)
     733        47861 :    END SUBROUTINE cp_rm_iter_level
     734              : 
     735              : ! **************************************************************************************************
     736              : !> \brief Print information entering or exiting an iteration level
     737              : !> \param logger the logger with iteration info and para_env
     738              : !> \param direction entering (A) or exiting (R) the iteration level
     739              : !> \param local if the unit should be local to this task
     740              : !> \author Zilong HE
     741              : ! **************************************************************************************************
     742        95722 :    SUBROUTINE cp_iter_level_print(logger, direction, local)
     743              :       TYPE(cp_logger_type), POINTER                      :: logger
     744              :       CHARACTER(LEN=1), INTENT(IN)                       :: direction
     745              :       LOGICAL, INTENT(IN), OPTIONAL                      :: local
     746              : 
     747              :       INTEGER, PARAMETER                                 :: min_iter_level = 2
     748              : 
     749        95722 :       CHARACTER(LEN=:), ALLOCATABLE                      :: level_name
     750              :       INTEGER                                            :: iter_nr, rlevel, unit_nr
     751              :       LOGICAL                                            :: my_local
     752              :       TYPE(cp_iteration_info_type), POINTER              :: iteration_info
     753              : 
     754              :       ! min_iter_level = 2 is to skip iteration_info%level_name(1)
     755              :       ! which corresponds to a fictitious __ROOT__ level added in
     756              :       ! the init_cp2k subroutine. The level_name should be one of
     757              :       ! the list each_possible_labels; the following WRITE format
     758              :       ! assumes implicitly a maximum length of 27 characters.
     759              : 
     760        95722 :       iteration_info => logger%iter_info
     761        95722 :       my_local = .FALSE.
     762        95722 :       IF (PRESENT(local)) my_local = local
     763        95722 :       IF (my_local .OR. logger%para_env%is_source()) THEN
     764        48508 :          IF (iteration_info%iter_print >= iter_silent) THEN
     765        47770 :             rlevel = iteration_info%n_rlevel
     766        47770 :             CPASSERT(rlevel > 0)
     767        47770 :             level_name = TRIM(ADJUSTL(iteration_info%level_name(rlevel)))
     768        47770 :             CALL cp_get_iter_nr(iteration_info, rlevel, iter_nr)
     769        47770 :             IF (iteration_info%iter_print > iter_silent) THEN
     770          190 :                unit_nr = cp_logger_get_unit_nr(logger, local=my_local)
     771          190 :                IF (unit_nr > 0) THEN
     772          190 :                   WRITE (UNIT=unit_nr, FMT="()")
     773              :                   ! The current iteration level
     774           95 :                   SELECT CASE (direction)
     775              :                   CASE ("A") ! After adding level in cp_add_iter_level
     776              :                      WRITE (UNIT=unit_nr, FMT="(T2,A,T37,I3,T41,A,T73,I8)") &
     777           95 :                         "ITER_LV| >>>>>>>> Entering level +", rlevel, "[ "//level_name//" ]", iter_nr
     778              :                   CASE ("R") ! Before removing level in cp_rm_iter_level
     779              :                      WRITE (UNIT=unit_nr, FMT="(T2,A,T37,I3,T41,A,T73,I8)") &
     780           95 :                         "ITER_LV| <<<<<<<<  Exiting level -", rlevel, "[ "//level_name//" ]", iter_nr
     781              :                   CASE DEFAULT
     782              :                      CALL cp_abort(__LOCATION__, &
     783              :                                    "Only entering (A) or exiting (R) an iteration level "// &
     784          190 :                                    "can have a message printed.")
     785              :                   END SELECT
     786              :                   ! The rest of stack of iteration levels
     787          190 :                   IF (iteration_info%iter_print > iter_notice) THEN
     788          114 :                      DO WHILE (rlevel > min_iter_level)
     789           34 :                         rlevel = rlevel - 1
     790           34 :                         level_name = TRIM(ADJUSTL(iteration_info%level_name(rlevel)))
     791           34 :                         CALL cp_get_iter_nr(iteration_info, rlevel, iter_nr)
     792              :                         WRITE (UNIT=unit_nr, FMT="(T2,A,T37,I3,T41,A,T73,I8)") &
     793          114 :                            "ITER_LV|                         *", rlevel, "[ "//level_name//" ]", iter_nr
     794              :                      END DO
     795              :                   END IF
     796          190 :                   WRITE (UNIT=unit_nr, FMT="()")
     797              :                END IF
     798              :             END IF
     799              :          ELSE
     800              :             CALL cp_warn(__LOCATION__, &
     801              :                          "An iteration level has been added to or removed from a logger "// &
     802          738 :                          "that does not receive the GLOBAL%ITER_LEVEL_VERBOSITY setting.")
     803              :          END IF
     804              :       END IF
     805              : 
     806        47770 :    END SUBROUTINE cp_iter_level_print
     807              : 
     808              : ! **************************************************************************************************
     809              : !> \brief Utility function that returns a unit number to write the print key.
     810              : !>     Might open a file with a unique filename, generated from
     811              : !>     the print_key name and iteration info.
     812              : !>
     813              : !>     Normally a valid unit (>0) is returned only if cp_print_key_should_output
     814              : !>     says that the print_key should be printed, and if the unit is global
     815              : !>     only the io node has a valid unit.
     816              : !>     So in many cases you can decide if you should print just checking if
     817              : !>     the returned units is bigger than 0.
     818              : !>
     819              : !>     IMPORTANT you should call cp_finished_output when an iteration output is
     820              : !>     finished (to immediately close the file that might have been opened)
     821              : !> \param logger the logger for the parallel environment, iteration info
     822              : !>        and filename generation
     823              : !> \param print_key ...
     824              : !> \param middle_name name to be added to the generated filename, useful when
     825              : !>        print_key activates different distinct outputs, to be able to
     826              : !>        distinguish them
     827              : !> \param extension extension to be applied to the filename (including the ".")
     828              : !> \param my_local if the unit should be local to this task, or global to the
     829              : !>        program (defaults to false).
     830              : !> \return ...
     831              : !> \author Fawzi Mohamed
     832              : ! **************************************************************************************************
     833       106155 :    FUNCTION cp_print_key_generate_filename(logger, print_key, middle_name, extension, &
     834              :                                            my_local) RESULT(filename)
     835              :       TYPE(cp_logger_type), POINTER                      :: logger
     836              :       TYPE(section_vals_type), POINTER                   :: print_key
     837              :       CHARACTER(len=*), INTENT(IN), OPTIONAL             :: middle_name
     838              :       CHARACTER(len=*), INTENT(IN)                       :: extension
     839              :       LOGICAL, INTENT(IN)                                :: my_local
     840              :       CHARACTER(len=default_path_length)                 :: filename
     841              : 
     842              :       CHARACTER(len=default_path_length)                 :: outName, outPath, postfix, root
     843              :       CHARACTER(len=default_string_length)               :: my_middle_name
     844              :       INTEGER                                            :: my_ind1, my_ind2
     845              :       LOGICAL                                            :: has_root
     846              : 
     847       106155 :       CALL section_vals_val_get(print_key, "FILENAME", c_val=outPath)
     848       106155 :       IF (outPath(1:1) == '=') THEN
     849              :          CPASSERT(LEN(outPath) - 1 <= LEN(filename))
     850          593 :          filename = outPath(2:)
     851          593 :          RETURN
     852              :       END IF
     853       105562 :       IF (outPath == "__STD_OUT__") outPath = ""
     854       105562 :       outName = outPath
     855       105562 :       has_root = .FALSE.
     856       105562 :       my_ind1 = INDEX(outPath, "/")
     857       105562 :       my_ind2 = LEN_TRIM(outPath)
     858       105562 :       IF (my_ind1 /= 0) THEN
     859         3937 :          has_root = .TRUE.
     860         3937 :          DO WHILE (INDEX(outPath(my_ind1 + 1:my_ind2), "/") /= 0)
     861         3937 :             my_ind1 = INDEX(outPath(my_ind1 + 1:my_ind2), "/") + my_ind1
     862              :          END DO
     863         3937 :          IF (my_ind1 == my_ind2) THEN
     864            0 :             outName = ""
     865              :          ELSE
     866         3937 :             outName = outPath(my_ind1 + 1:my_ind2)
     867              :          END IF
     868              :       END IF
     869              : 
     870       105562 :       IF (PRESENT(middle_name)) THEN
     871        40304 :          IF (outName /= "") THEN
     872          648 :             my_middle_name = "-"//TRIM(outName)//"-"//middle_name
     873              :          ELSE
     874        39656 :             my_middle_name = "-"//middle_name
     875              :          END IF
     876              :       ELSE
     877        65258 :          IF (outName /= "") THEN
     878        30556 :             my_middle_name = "-"//TRIM(outName)
     879              :          ELSE
     880        34702 :             my_middle_name = ""
     881              :          END IF
     882              :       END IF
     883              : 
     884       105562 :       IF (.NOT. has_root) THEN
     885       101625 :          root = TRIM(logger%iter_info%project_name)//TRIM(my_middle_name)
     886         3937 :       ELSE IF (outName == "") THEN
     887            0 :          root = outPath(1:my_ind1)//TRIM(logger%iter_info%project_name)//TRIM(my_middle_name)
     888              :       ELSE
     889         3937 :          root = outPath(1:my_ind1)//my_middle_name(2:LEN_TRIM(my_middle_name))
     890              :       END IF
     891              : 
     892              :       ! use the cp_iter_string as a postfix
     893       105562 :       postfix = "-"//TRIM(cp_iter_string(logger%iter_info, print_key=print_key, for_file=.TRUE.))
     894       105562 :       IF (TRIM(postfix) == "-") postfix = ""
     895              : 
     896              :       ! and add the extension
     897       105562 :       postfix = TRIM(postfix)//extension
     898              :       ! and let the logger generate the filename
     899              :       CALL cp_logger_generate_filename(logger, res=filename, &
     900       105562 :                                        root=root, postfix=postfix, local=my_local)
     901              : 
     902              :    END FUNCTION cp_print_key_generate_filename
     903              : 
     904              : ! **************************************************************************************************
     905              : !> \brief ...
     906              : !> \param logger ...
     907              : !> \param basis_section ...
     908              : !> \param print_key_path ...
     909              : !> \param extension ...
     910              : !> \param middle_name ...
     911              : !> \param local ...
     912              : !> \param log_filename ...
     913              : !> \param ignore_should_output ...
     914              : !> \param file_form ...
     915              : !> \param file_position ...
     916              : !> \param file_action ...
     917              : !> \param file_status ...
     918              : !> \param do_backup ...
     919              : !> \param on_file ...
     920              : !> \param is_new_file true if this rank created a new (or rewound) file, false otherwise
     921              : !> \param mpi_io True if the file should be opened in parallel on all processors belonging to
     922              : !>               the communicator group. Automatically disabled if the file form or access mode
     923              : !>               is unsuitable for MPI IO. Return value indicates whether MPI was actually used
     924              : !>               and therefore the flag must also be passed to the file closing directive.
     925              : !> \param fout   Name of the actual file where the output will be written. Needed mainly for MPI IO
     926              : !>               because inquiring the filename from the MPI filehandle does not work across
     927              : !>               all MPI libraries.
     928              : !> \param file_access Fortran access mode (SEQUENTIAL by default, or STREAM); unused with MPI I/O
     929              : !> \return ...
     930              : ! **************************************************************************************************
     931      3152109 :    FUNCTION cp_print_key_unit_nr(logger, basis_section, print_key_path, extension, &
     932              :                                  middle_name, local, log_filename, ignore_should_output, file_form, file_position, &
     933              :                                  file_action, file_status, do_backup, on_file, is_new_file, mpi_io, &
     934              :                                  fout, file_access) RESULT(res)
     935              :       TYPE(cp_logger_type), POINTER                      :: logger
     936              :       TYPE(section_vals_type), INTENT(IN)                :: basis_section
     937              :       CHARACTER(len=*), INTENT(IN), OPTIONAL             :: print_key_path
     938              :       CHARACTER(len=*), INTENT(IN)                       :: extension
     939              :       CHARACTER(len=*), INTENT(IN), OPTIONAL             :: middle_name
     940              :       LOGICAL, INTENT(IN), OPTIONAL                      :: local, log_filename, ignore_should_output
     941              :       CHARACTER(len=*), INTENT(IN), OPTIONAL             :: file_form, file_position, file_action, &
     942              :                                                             file_status
     943              :       LOGICAL, INTENT(IN), OPTIONAL                      :: do_backup, on_file
     944              :       LOGICAL, INTENT(OUT), OPTIONAL                     :: is_new_file
     945              :       LOGICAL, INTENT(INOUT), OPTIONAL                   :: mpi_io
     946              :       CHARACTER(len=default_path_length), INTENT(OUT), &
     947              :          OPTIONAL                                        :: fout
     948              :       CHARACTER(len=*), INTENT(IN), OPTIONAL             :: file_access
     949              :       INTEGER                                            :: res
     950              : 
     951              :       CHARACTER(len=default_path_length)                 :: filename, filename_bak, filename_bak_1, &
     952              :                                                             filename_bak_2
     953              :       CHARACTER(len=default_string_length)               :: my_file_action, my_file_form, &
     954              :                                                             my_file_position, my_file_status, &
     955              :                                                             outPath
     956              :       INTEGER                                            :: c_i_level, f_backup_level, i, mpi_amode, &
     957              :                                                             my_backup_level, my_nbak, nbak, &
     958              :                                                             s_backup_level, unit_nr
     959              :       LOGICAL                                            :: do_log, found, my_do_backup, my_local, &
     960              :                                                             my_mpi_io, my_on_file, &
     961              :                                                             my_should_output, replace
     962              :       TYPE(cp_iteration_info_type), POINTER              :: iteration_info
     963              :       TYPE(mp_file_type)                                 :: mp_unit
     964              :       TYPE(section_vals_type), POINTER                   :: print_key
     965              : 
     966      3152109 :       my_local = .FALSE.
     967      3152109 :       my_do_backup = .FALSE.
     968      3152109 :       my_mpi_io = .FALSE.
     969      3152109 :       replace = .FALSE.
     970      3152109 :       found = .FALSE.
     971      3152109 :       res = -1
     972      3152109 :       my_file_form = "FORMATTED"
     973      3152109 :       my_file_position = "APPEND"
     974      3152109 :       my_file_action = "WRITE"
     975      3152109 :       my_file_status = "UNKNOWN"
     976      3152109 :       my_on_file = .FALSE.
     977      3152109 :       mpi_amode = 0
     978       337120 :       IF (PRESENT(file_form)) my_file_form = file_form
     979      3152109 :       IF (PRESENT(file_position)) my_file_position = file_position
     980      3152109 :       IF (PRESENT(file_action)) my_file_action = file_action
     981      3152109 :       IF (PRESENT(file_status)) my_file_status = file_status
     982      3152109 :       IF (PRESENT(do_backup)) my_do_backup = do_backup
     983      3152109 :       IF (PRESENT(on_file)) my_on_file = on_file
     984      3152109 :       IF (PRESENT(local)) my_local = local
     985      3152109 :       IF (PRESENT(is_new_file)) is_new_file = .FALSE.
     986      3152109 :       IF (PRESENT(mpi_io)) THEN
     987              : #if defined(__parallel)
     988         2032 :          IF (cp_mpi_io_get() .AND. logger%para_env%num_pe > 1 .AND. mpi_io) THEN
     989              :             my_mpi_io = .TRUE.
     990              :          ELSE
     991              :             my_mpi_io = .FALSE.
     992              :          END IF
     993              :          IF (my_mpi_io) THEN
     994              :             CALL mp_file_get_amode(mpi_io, replace, mpi_amode, TRIM(my_file_form), &
     995         2032 :                                    TRIM(my_file_action), TRIM(my_file_status), TRIM(my_file_position))
     996         3902 :             replace = replace .AND. logger%para_env%is_source()
     997              :          END IF
     998              : #else
     999              :          my_mpi_io = .FALSE.
    1000              : #endif
    1001              :          ! Set return value
    1002         2032 :          mpi_io = my_mpi_io
    1003              :       END IF
    1004      3152109 :       NULLIFY (print_key)
    1005      3152109 :       CPASSERT(ASSOCIATED(logger))
    1006      3152109 :       CPASSERT(basis_section%ref_count > 0)
    1007      3152109 :       CPASSERT(logger%ref_count > 0)
    1008              :       my_should_output = BTEST(cp_print_key_should_output(logger%iter_info, &
    1009      3170239 :                                                           basis_section, print_key_path, used_print_key=print_key), cp_p_file)
    1010      3152109 :       IF (PRESENT(ignore_should_output)) my_should_output = my_should_output .OR. ignore_should_output
    1011      3144549 :       IF (.NOT. my_should_output) RETURN
    1012              :       IF (my_local .OR. &
    1013       955331 :           logger%para_env%is_source() .OR. &
    1014              :           my_mpi_io) THEN
    1015              : 
    1016       497415 :          CALL section_vals_val_get(print_key, "FILENAME", c_val=outPath)
    1017       497415 :          IF (outPath == '__STD_OUT__' .AND. .NOT. my_on_file) THEN
    1018       402561 :             res = cp_logger_get_default_unit_nr(logger, local=my_local)
    1019              :          ELSE
    1020              :             !
    1021              :             ! complex logic to build filename:
    1022              :             !   1)  Try to avoid '--' and '-.'
    1023              :             !   2)  If outPath contains '/' (as in ./filename) do not prepend the project_name
    1024              :             !
    1025              :             ! if it is actually a full path, use it as the root
    1026              :             filename = cp_print_key_generate_filename(logger, print_key, middle_name, extension, &
    1027       154979 :                                                       my_local)
    1028              :             ! Give back info about a possible existence of the file if required
    1029        94854 :             IF (PRESENT(is_new_file)) THEN
    1030        49993 :                INQUIRE (FILE=filename, EXIST=found)
    1031        49993 :                is_new_file = .NOT. found
    1032        49993 :                IF (my_file_position == "REWIND") is_new_file = .TRUE.
    1033              :             END IF
    1034              :             ! Check is we have to log any operation performed on the file..
    1035              :             do_log = .FALSE.
    1036        94854 :             IF (PRESENT(log_filename)) THEN
    1037         2336 :                do_log = log_filename
    1038              :             ELSE
    1039        92518 :                CALL section_vals_val_get(print_key, "LOG_PRINT_KEY", l_val=do_log)
    1040              :             END IF
    1041              :             ! If required do a backup
    1042        94854 :             IF (my_do_backup) THEN
    1043        18938 :                INQUIRE (FILE=filename, EXIST=found)
    1044        18938 :                CALL section_vals_val_get(print_key, "BACKUP_COPIES", i_val=nbak)
    1045        18938 :                IF (nbak /= 0) THEN
    1046        16215 :                   iteration_info => logger%iter_info
    1047        16215 :                   s_backup_level = 0
    1048        16215 :                   IF (ASSOCIATED(print_key%ibackup)) s_backup_level = SIZE(print_key%ibackup)
    1049        16215 :                   CALL section_vals_val_get(print_key, "COMMON_ITERATION_LEVELS", i_val=c_i_level)
    1050        16215 :                   my_backup_level = MAX(1, iteration_info%n_rlevel - c_i_level + 1)
    1051        16215 :                   f_backup_level = MAX(s_backup_level, my_backup_level)
    1052        16215 :                   IF (f_backup_level > s_backup_level) THEN
    1053         4533 :                      CALL reallocate(print_key%ibackup, 1, f_backup_level)
    1054        10407 :                      DO i = s_backup_level + 1, f_backup_level
    1055        10407 :                         print_key%ibackup(i) = 0
    1056              :                      END DO
    1057              :                   END IF
    1058        16215 :                   IF (found) THEN
    1059        13107 :                      print_key%ibackup(my_backup_level) = print_key%ibackup(my_backup_level) + 1
    1060        13107 :                      my_nbak = print_key%ibackup(my_backup_level)
    1061              :                      ! Recent backup copies correspond to lower backup indexes
    1062        13119 :                      DO i = MIN(nbak, my_nbak), 2, -1
    1063           12 :                         filename_bak_1 = TRIM(filename)//".bak-"//ADJUSTL(cp_to_string(i))
    1064           12 :                         filename_bak_2 = TRIM(filename)//".bak-"//ADJUSTL(cp_to_string(i - 1))
    1065           12 :                         IF (do_log) THEN
    1066           12 :                            unit_nr = cp_logger_get_unit_nr(logger, local=my_local)
    1067           12 :                            IF (unit_nr > 0) THEN
    1068              :                               WRITE (unit_nr, *) "Moving file "//TRIM(filename_bak_2)// &
    1069           12 :                                  " into file "//TRIM(filename_bak_1)//"."
    1070              :                            END IF
    1071              :                         END IF
    1072           12 :                         INQUIRE (FILE=filename_bak_2, EXIST=found)
    1073        13119 :                         IF (.NOT. found) THEN
    1074            0 :                            IF (do_log) THEN
    1075            0 :                               unit_nr = cp_logger_get_unit_nr(logger, local=my_local)
    1076            0 :                               IF (unit_nr > 0) THEN
    1077            0 :                                  WRITE (unit_nr, *) "File "//TRIM(filename_bak_2)//" not existing.."
    1078              :                               END IF
    1079              :                            END IF
    1080              :                         ELSE
    1081              :                            ! Shared file: rotate on the source rank only; per-task
    1082              :                            ! (my_local) files are per-rank, rotated by their owner.
    1083           12 :                            IF (my_local .OR. logger%para_env%is_source()) THEN
    1084           12 :                               CALL m_mov(TRIM(filename_bak_2), TRIM(filename_bak_1))
    1085              :                            END IF
    1086              :                         END IF
    1087              :                      END DO
    1088              :                      ! The last backup is always the one with index 1
    1089        13107 :                      filename_bak = TRIM(filename)//".bak-"//ADJUSTL(cp_to_string(1))
    1090        13107 :                      IF (do_log) THEN
    1091           68 :                         unit_nr = cp_logger_get_unit_nr(logger, local=my_local)
    1092           68 :                         IF (unit_nr > 0) THEN
    1093           68 :                            WRITE (unit_nr, *) "Moving file "//TRIM(filename)//" into file "//TRIM(filename_bak)//"."
    1094              :                         END IF
    1095              :                      END IF
    1096        13107 :                      IF (my_local .OR. logger%para_env%is_source()) THEN
    1097        13107 :                         CALL m_mov(TRIM(filename), TRIM(filename_bak))
    1098              :                      END IF
    1099              :                   ELSE
    1100              :                      ! Zero the backup history for this new iteration level..
    1101         3108 :                      print_key%ibackup(my_backup_level) = 0
    1102              :                   END IF
    1103              :                END IF
    1104              :             END IF
    1105              : 
    1106        94854 :             IF (.NOT. my_mpi_io) THEN
    1107              :                CALL open_file(file_name=filename, file_status=my_file_status, &
    1108              :                               file_form=my_file_form, file_action=my_file_action, &
    1109       185641 :                               file_position=my_file_position, file_access=file_access, unit_number=res)
    1110              :             ELSE
    1111         2032 :                IF (replace) CALL mp_file_delete(filename)
    1112              :                CALL mp_unit%open(groupid=logger%para_env, &
    1113         2032 :                                  filepath=filename, amode_status=mpi_amode)
    1114         2032 :                IF (PRESENT(fout)) fout = filename
    1115         2032 :                res = mp_unit%get_handle()
    1116              :             END IF
    1117        94854 :             IF (do_log) THEN
    1118           79 :                unit_nr = cp_logger_get_unit_nr(logger, local=my_local)
    1119           79 :                IF (unit_nr > 0) THEN
    1120              :                   WRITE (unit_nr, *) "Writing "//TRIM(print_key%section%name)//" "// &
    1121              :                      TRIM(cp_iter_string(logger%iter_info))//" to "// &
    1122           79 :                      TRIM(filename)
    1123              :                END IF
    1124              :             END IF
    1125              :          END IF
    1126              :       ELSE
    1127       457916 :          res = -1
    1128              :       END IF
    1129      4107440 :    END FUNCTION cp_print_key_unit_nr
    1130              : 
    1131              : ! **************************************************************************************************
    1132              : !> \brief should be called after you finish working with a unit obtained with
    1133              : !>      cp_print_key_unit_nr, so that the file that might have been opened
    1134              : !>      can be closed.
    1135              : !>
    1136              : !>      the inputs should be exactly the same of the corresponding
    1137              : !>      cp_print_key_unit_nr
    1138              : !> \param unit_nr ...
    1139              : !> \param logger ...
    1140              : !> \param basis_section ...
    1141              : !> \param print_key_path ...
    1142              : !> \param local ...
    1143              : !> \param ignore_should_output ...
    1144              : !> \param on_file ...
    1145              : !> \param mpi_io True if file was opened in parallel with MPI
    1146              : !> \par History
    1147              : !>      08.2002 created [fawzi]
    1148              : !> \author Fawzi Mohamed
    1149              : !> \note
    1150              : !>      closes if the corresponding filename of the printkey is
    1151              : !>      not __STD_OUT__
    1152              : ! **************************************************************************************************
    1153      2998982 :    SUBROUTINE cp_print_key_finished_output(unit_nr, logger, basis_section, &
    1154              :                                            print_key_path, local, ignore_should_output, on_file, &
    1155              :                                            mpi_io)
    1156              :       INTEGER, INTENT(INOUT)                             :: unit_nr
    1157              :       TYPE(cp_logger_type), POINTER                      :: logger
    1158              :       TYPE(section_vals_type), INTENT(IN)                :: basis_section
    1159              :       CHARACTER(len=*), INTENT(IN), OPTIONAL             :: print_key_path
    1160              :       LOGICAL, INTENT(IN), OPTIONAL                      :: local, ignore_should_output, on_file, &
    1161              :                                                             mpi_io
    1162              : 
    1163              :       CHARACTER(len=default_string_length)               :: outPath
    1164              :       LOGICAL                                            :: my_local, my_mpi_io, my_on_file, &
    1165              :                                                             my_should_output
    1166              :       TYPE(mp_file_type)                                 :: mp_unit
    1167              :       TYPE(section_vals_type), POINTER                   :: print_key
    1168              : 
    1169      2998982 :       my_local = .FALSE.
    1170      2998982 :       my_on_file = .FALSE.
    1171      2998982 :       my_mpi_io = .FALSE.
    1172      2998982 :       NULLIFY (print_key)
    1173         3030 :       IF (PRESENT(local)) my_local = local
    1174      2998982 :       IF (PRESENT(on_file)) my_on_file = on_file
    1175      2998982 :       IF (PRESENT(mpi_io)) my_mpi_io = mpi_io
    1176      2998982 :       CPASSERT(ASSOCIATED(logger))
    1177      2998982 :       CPASSERT(basis_section%ref_count > 0)
    1178      2998982 :       CPASSERT(logger%ref_count > 0)
    1179              :       my_should_output = BTEST(cp_print_key_should_output(logger%iter_info, basis_section, &
    1180      3043617 :                                                           print_key_path, used_print_key=print_key), cp_p_file)
    1181      2998982 :       IF (PRESENT(ignore_should_output)) my_should_output = my_should_output .OR. ignore_should_output
    1182      2998982 :       IF (my_should_output .AND. (my_local .OR. &
    1183              :                                   logger%para_env%is_source() .OR. &
    1184              :                                   my_mpi_io)) THEN
    1185       425040 :          CALL section_vals_val_get(print_key, "FILENAME", c_val=outPath)
    1186       425040 :          IF (my_on_file .OR. outPath /= '__STD_OUT__') THEN
    1187        92045 :             CPASSERT(unit_nr > 0)
    1188        92045 :             IF (.NOT. my_mpi_io) THEN
    1189        90013 :                CALL close_file(unit_nr, "KEEP")
    1190              :             ELSE
    1191         2032 :                CALL mp_unit%set_handle(unit_nr)
    1192         2032 :                CALL mp_unit%close()
    1193              :             END IF
    1194        92045 :             unit_nr = -1
    1195              :          ELSE
    1196       332995 :             unit_nr = -1
    1197              :          END IF
    1198              :       END IF
    1199      2998982 :       CPASSERT(unit_nr == -1)
    1200      2998982 :       unit_nr = -1
    1201      2998982 :    END SUBROUTINE cp_print_key_finished_output
    1202              : 
    1203              : ! **************************************************************************************************
    1204              : !> \brief Sets flag which determines whether or not to use MPI I/O for I/O routines that
    1205              : !>        have been parallized with MPI
    1206              : !> \param flag ...
    1207              : !> \par History
    1208              : !>      09.2018 created [Nico Holmberg]
    1209              : ! **************************************************************************************************
    1210        11793 :    SUBROUTINE cp_mpi_io_set(flag)
    1211              :       LOGICAL, INTENT(IN)                                :: flag
    1212              : 
    1213        11793 :       enable_mpi_io = flag
    1214        11793 :    END SUBROUTINE cp_mpi_io_set
    1215              : 
    1216              : ! **************************************************************************************************
    1217              : !> \brief Gets flag which determines whether or not to use MPI I/O for I/O routines that
    1218              : !>        have been parallized with MPI
    1219              : !> \return ...
    1220              : !> \par History
    1221              : !>      09.2018 created [Nico Holmberg]
    1222              : ! **************************************************************************************************
    1223         2078 :    FUNCTION cp_mpi_io_get() RESULT(flag)
    1224              :       LOGICAL                                            :: flag
    1225              : 
    1226         2078 :       flag = enable_mpi_io
    1227         2078 :    END FUNCTION cp_mpi_io_get
    1228              : 
    1229              : END MODULE cp_output_handling
        

Generated by: LCOV version 2.0-1