LCOV - code coverage report
Current view: top level - src/common - cp_log_handling.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:71c3ab0) Lines: 75.8 % 240 182
Test Date: 2026-07-25 06:35:44 Functions: 75.0 % 20 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 various routines to log and control the output.
      10              : !>      The idea is that decisions about where to log should not be done in
      11              : !>      the code that generates the log, but should be globally changeable
      12              : !>      a central place.
      13              : !>      So some care has been taken to have enough information about the
      14              : !>      place from where the log comes so that in the future intelligent and
      15              : !>      flexible decisions can be taken by the logger, without having to change
      16              : !>      other code.
      17              : !> \note
      18              : !>      contains also routines to convert to a string.
      19              : !>      in my idea they should have been with variable length,
      20              : !>      (i.e. they should have returned a trim(adjustl(actual_result)))
      21              : !>      As a logger should be robust, at the moment I have given up.
      22              : !>
      23              : !>      At the moment logging and output refer to the same object
      24              : !>      (cp_logger_type)
      25              : !>      as these are actually different it might be better to separate them
      26              : !>      (they have already separate routines in a separate module
      27              : !>      @see cp_output_handling).
      28              : !>
      29              : !>      some practices (use of print *, no cp_error_type,
      30              : !>      manual retain release of some objects) are dictated by the need to
      31              : !>      have minimal dependency
      32              : !> \par History
      33              : !>      08.2002 major update: retain, release, printkeys, para_env,
      34              : !>              local logging [fawzi]
      35              : !>      02.2004 made a stack of default loggers [Joost VandeVondele]
      36              : !> \par
      37              : !>      @see cp_error_handling
      38              : !> \author Fawzi Mohamed
      39              : !>      @version 12.2001
      40              : ! **************************************************************************************************
      41              : MODULE cp_log_handling
      42              :    USE cp_files,                        ONLY: close_file,&
      43              :                                               open_file
      44              :    USE cp_iter_types,                   ONLY: cp_iteration_info_create,&
      45              :                                               cp_iteration_info_release,&
      46              :                                               cp_iteration_info_retain,&
      47              :                                               cp_iteration_info_type
      48              :    USE kinds,                           ONLY: default_path_length,&
      49              :                                               default_string_length,&
      50              :                                               dp
      51              :    USE machine,                         ONLY: default_output_unit,&
      52              :                                               m_getpid,&
      53              :                                               m_hostnm
      54              :    USE message_passing,                 ONLY: mp_para_env_release,&
      55              :                                               mp_para_env_type
      56              :    USE string_utilities,                ONLY: compress
      57              :    USE timings,                         ONLY: print_stack
      58              : #include "../base/base_uses.f90"
      59              : 
      60              :    IMPLICIT NONE
      61              :    PRIVATE
      62              : 
      63              :    !API types
      64              :    PUBLIC :: cp_logger_type, cp_logger_p_type
      65              :    !API parameter vars
      66              :    PUBLIC :: cp_note_level, cp_warning_level, cp_failure_level, cp_fatal_level
      67              :    !API default loggers
      68              :    PUBLIC :: cp_get_default_logger, cp_add_default_logger, cp_rm_default_logger, &
      69              :              cp_default_logger_stack_size
      70              :    !API logger routines
      71              :    PUBLIC :: cp_logger_create, cp_logger_retain, cp_logger_release, &
      72              :              cp_logger_would_log, cp_logger_set, cp_logger_get_default_unit_nr, &
      73              :              cp_logger_get_default_io_unit, cp_logger_get_unit_nr, &
      74              :              cp_logger_set_log_level, cp_logger_generate_filename, &
      75              :              cp_to_string
      76              : 
      77              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'cp_log_handling'
      78              :    LOGICAL, PRIVATE, PARAMETER :: debug_this_module = .FALSE.
      79              : 
      80              :    !! level of an error
      81              :    INTEGER, PARAMETER          :: cp_fatal_level = 3
      82              :    !! level of a failure
      83              :    INTEGER, PARAMETER          :: cp_failure_level = 2
      84              :    !! level of a warning
      85              :    INTEGER, PARAMETER          :: cp_warning_level = 1
      86              :    !! level of a note
      87              :    INTEGER, PARAMETER          :: cp_note_level = 0
      88              : 
      89              :    !! a generic function to transform different types to strings
      90              :    INTERFACE cp_to_string
      91              :       MODULE PROCEDURE cp_int_to_string, cp_real_dp_to_string, cp_logical_to_string
      92              :    END INTERFACE
      93              : 
      94              : ! **************************************************************************************************
      95              : !> \brief type of a logger, at the moment it contains just a print level
      96              : !>      starting at which level it should be logged
      97              : !>      (0 note, 1 warning, 2 failure, 3 fatal)
      98              : !>      it could be expanded with the ability to focus on one or more
      99              : !>      module/object/thread/processor
     100              : !> \param ref_count reference count (see cp2k/doc/ReferenceCounting.html)
     101              : !> \param print_level the level starting at which something gets printed
     102              : !> \param default_local_unit_nr default unit for local logging (-1 if not
     103              : !>        yet initialized). Local logging guarantee to each task its own
     104              : !>        file.
     105              : !> \param default_global_unit_nr default unit for global logging
     106              : !>        (-1 if not yet initialized). This unit is valid only on the
     107              : !>        processor with %para_env%mepos==%para_env%source.
     108              : !> \param para_env the parallel environment for the output.
     109              : !>        this might be a super environment of your computation environment
     110              : !>        i.e. be very careful not to do global operations like broadcast
     111              : !>        with a subset of its processors (use your computation environment
     112              : !>        instead).
     113              : !> \param close_local_unit_on_dealloc if the local unit should be closed
     114              : !>        when this logger is deallocated
     115              : !> \param close_global_unit_on_dealloc whether the global unit should be
     116              : !>        closed when this logger is deallocated
     117              : !> \param suffix a short string that is used as suffix in all the filenames
     118              : !>        created by this logger. Can be used to guarantee the unicity of
     119              : !>        generated filename
     120              : !> \param local_filename the root of the name of the file used for local
     121              : !>        logging (can be different from the name of the file corresponding
     122              : !>        to default_local_unit_nr, only the one used if the unit needs to
     123              : !>        be opened)
     124              : !> \param global_filename the root of the name of the file used for
     125              : !>        global logging (can be different from the name of the file
     126              : !>        corresponding to default_global_unit_nr, only the one used if
     127              : !>        the unit needs to be opened)
     128              : !> \param print_keys print keys that tell what should be logged/outputted
     129              : !> \note
     130              : !>      This should be private, but as the output functions have been
     131              : !>      moved to another module and there is no "friend" keyword, they
     132              : !>      are public.
     133              : !>      DO NOT USE THE INTERNAL COMPONENTS DIRECTLY!!!
     134              : !> \par History
     135              : !>      04.2002 revised [fawzi]
     136              : !>      08.2002 major update: retain, release, printkeys, para_env,
     137              : !>              local logging [fawzi]
     138              : !> \author Fawzi Mohamed
     139              : ! **************************************************************************************************
     140              :    TYPE cp_logger_type
     141              :       INTEGER :: ref_count = -1
     142              :       INTEGER :: print_level = -1
     143              :       INTEGER :: default_local_unit_nr = -1
     144              :       INTEGER :: default_global_unit_nr = -1
     145              :       LOGICAL :: close_local_unit_on_dealloc = .FALSE., close_global_unit_on_dealloc = .FALSE.
     146              :       CHARACTER(len=default_string_length)  :: suffix = ""
     147              :       CHARACTER(len=default_path_length)    :: local_filename = "", global_filename = ""
     148              :       TYPE(mp_para_env_type), POINTER       :: para_env => NULL()
     149              :       TYPE(cp_iteration_info_type), POINTER :: iter_info => NULL()
     150              :    END TYPE cp_logger_type
     151              : 
     152              :    TYPE cp_logger_p_type
     153              :       TYPE(cp_logger_type), POINTER :: p => Null()
     154              :    END TYPE cp_logger_p_type
     155              : 
     156              : ! **************************************************************************************************
     157              :    TYPE default_logger_stack_type
     158              :       TYPE(cp_logger_type), POINTER :: cp_default_logger => Null()
     159              :    END TYPE default_logger_stack_type
     160              : 
     161              :    INTEGER, PRIVATE            :: stack_pointer = 0
     162              :    INTEGER, PARAMETER, PRIVATE :: max_stack_pointer = 10
     163              :    TYPE(default_logger_stack_type), SAVE, DIMENSION(max_stack_pointer) ::  default_logger_stack
     164              : 
     165              : CONTAINS
     166              : 
     167              : ! **************************************************************************************************
     168              : !> \brief ...
     169              : !> \return ...
     170              : !> \author fawzi
     171              : ! **************************************************************************************************
     172        32916 :    FUNCTION cp_default_logger_stack_size() RESULT(res)
     173              :       INTEGER                                            :: res
     174              : 
     175        32916 :       res = stack_pointer
     176        32916 :    END FUNCTION cp_default_logger_stack_size
     177              : 
     178              : ! **************************************************************************************************
     179              : !> \brief adds a default logger.
     180              : !>      MUST be called before logging occours
     181              : !> \param logger ...
     182              : !> \author Fawzi Mohamed
     183              : !> \note
     184              : !>      increments a stack of default loggers the latest one will be
     185              : !>      available within the program
     186              : ! **************************************************************************************************
     187       121929 :    SUBROUTINE cp_add_default_logger(logger)
     188              :       TYPE(cp_logger_type), INTENT(INOUT), TARGET        :: logger
     189              : 
     190              :       CHARACTER(len=*), PARAMETER :: routineN = 'cp_add_default_logger', &
     191              :          routineP = moduleN//':'//routineN
     192              : 
     193       121929 :       IF (stack_pointer + 1 > max_stack_pointer) THEN
     194              :          CALL cp_abort(__LOCATION__, routineP// &
     195            0 :                        "too many default loggers, increase max_stack_pointer in "//moduleN)
     196              :       END IF
     197              : 
     198       121929 :       stack_pointer = stack_pointer + 1
     199       121929 :       NULLIFY (default_logger_stack(stack_pointer)%cp_default_logger)
     200              : 
     201       121929 :       default_logger_stack(stack_pointer)%cp_default_logger => logger
     202       121929 :       CALL cp_logger_retain(logger)
     203              : 
     204       121929 :    END SUBROUTINE cp_add_default_logger
     205              : 
     206              : ! **************************************************************************************************
     207              : !> \brief the cousin of cp_add_default_logger, decrements the stack, so that
     208              : !>      the default logger is what it has
     209              : !>      been
     210              : !> \author Joost VandeVondele
     211              : ! **************************************************************************************************
     212       121929 :    SUBROUTINE cp_rm_default_logger()
     213       121929 :       IF (stack_pointer - 1 < 0) THEN
     214              :          CALL cp_abort(__LOCATION__, moduleN//":cp_rm_default_logger "// &
     215            0 :                        "can not destroy default logger "//moduleN)
     216              :       END IF
     217              : 
     218       121929 :       CALL cp_logger_release(default_logger_stack(stack_pointer)%cp_default_logger)
     219       121929 :       NULLIFY (default_logger_stack(stack_pointer)%cp_default_logger)
     220       121929 :       stack_pointer = stack_pointer - 1
     221              : 
     222       121929 :    END SUBROUTINE cp_rm_default_logger
     223              : 
     224              : ! **************************************************************************************************
     225              : !> \brief returns the default logger
     226              : !> \return ...
     227              : !> \par History
     228              : !>      4.2002 created [fawzi]
     229              : !> \author Fawzi Mohamed
     230              : !> \note
     231              : !>      initializes the default loggers if necessary
     232              : ! **************************************************************************************************
     233     14292005 :    FUNCTION cp_get_default_logger() RESULT(res)
     234              :       TYPE(cp_logger_type), POINTER                      :: res
     235              : 
     236     14292005 :       IF (.NOT. stack_pointer > 0) THEN
     237              :          CALL cp_abort(__LOCATION__, "cp_log_handling:cp_get_default_logger "// &
     238            0 :                        "default logger not yet initialized (CALL cp_init_default_logger)")
     239              :       END IF
     240     14292005 :       res => default_logger_stack(stack_pointer)%cp_default_logger
     241     14292005 :       IF (.NOT. ASSOCIATED(res)) THEN
     242              :          CALL cp_abort(__LOCATION__, "cp_log_handling:cp_get_default_logger "// &
     243            0 :                        "default logger is null (released too much ?)")
     244              :       END IF
     245     14292005 :    END FUNCTION cp_get_default_logger
     246              : 
     247              : ! ================== log ==================
     248              : 
     249              : ! **************************************************************************************************
     250              : !> \brief initializes a logger
     251              : !> \param logger the logger to initialize
     252              : !> \param para_env the parallel environment (this is most likely the global
     253              : !>        parallel environment
     254              : !> \param print_level the level starting with which something is written
     255              : !>        (defaults to cp_note_level)
     256              : !> \param default_global_unit_nr the default unit_nr for output
     257              : !>        (if not given, and no file is given defaults to the standard output)
     258              : !> \param default_local_unit_nr the default unit number for local (i.e. task)
     259              : !>        output. If not given defaults to a out.taskid file created upon
     260              : !> \param global_filename a new file to open (can be given instread of the
     261              : !>        global_unit_nr)
     262              : !> \param local_filename a new file to open (with suffix and para_env%mepos
     263              : !>        appended). Can be given instread of the default_local_unit_nr).
     264              : !>        the file is created only upon the first local logging request
     265              : !> \param close_global_unit_on_dealloc if the unit should be closed when the
     266              : !>        logger is deallocated (defaults to true if a local_filename is given,
     267              : !>        to false otherwise)
     268              : !> \param iter_info ...
     269              : !> \param close_local_unit_on_dealloc if the unit should be closed when the
     270              : !>        logger is deallocated (defaults to true)
     271              : !> \param suffix the suffix that should be added to all the generated filenames
     272              : !> \param template_logger a logger from where to take the unspecified things
     273              : !> \par History
     274              : !>      4.2002 created [fawzi]
     275              : !> \author Fawzi Mohamed
     276              : !> \note
     277              : !>      the handling of *_filename, default_*_unit_nr, close_*_unit_on_dealloc
     278              : !>      tries to take the right decision with different inputs, and thus is a
     279              : !>      little complex.
     280              : ! **************************************************************************************************
     281        22705 :    SUBROUTINE cp_logger_create(logger, para_env, print_level, &
     282              :                                default_global_unit_nr, default_local_unit_nr, global_filename, &
     283              :                                local_filename, close_global_unit_on_dealloc, iter_info, &
     284              :                                close_local_unit_on_dealloc, suffix, template_logger)
     285              :       TYPE(cp_logger_type), POINTER                      :: logger
     286              :       TYPE(mp_para_env_type), OPTIONAL, POINTER          :: para_env
     287              :       INTEGER, INTENT(in), OPTIONAL                      :: print_level, default_global_unit_nr, &
     288              :                                                             default_local_unit_nr
     289              :       CHARACTER(len=*), INTENT(in), OPTIONAL             :: global_filename, local_filename
     290              :       LOGICAL, INTENT(in), OPTIONAL                      :: close_global_unit_on_dealloc
     291              :       TYPE(cp_iteration_info_type), OPTIONAL, POINTER    :: iter_info
     292              :       LOGICAL, INTENT(in), OPTIONAL                      :: close_local_unit_on_dealloc
     293              :       CHARACTER(len=*), INTENT(in), OPTIONAL             :: suffix
     294              :       TYPE(cp_logger_type), OPTIONAL, POINTER            :: template_logger
     295              : 
     296              :       CHARACTER(len=*), PARAMETER :: routineN = 'cp_logger_create', &
     297              :          routineP = moduleN//':'//routineN
     298              : 
     299            0 :       ALLOCATE (logger)
     300              : 
     301        22705 :       NULLIFY (logger%para_env)
     302        22705 :       NULLIFY (logger%iter_info)
     303        22705 :       logger%ref_count = 1
     304              : 
     305        22705 :       IF (PRESENT(template_logger)) THEN
     306          124 :          IF (template_logger%ref_count < 1) THEN
     307            0 :             CPABORT(routineP//" template_logger%ref_count<1")
     308              :          END IF
     309          124 :          logger%print_level = template_logger%print_level
     310          124 :          logger%default_global_unit_nr = template_logger%default_global_unit_nr
     311          124 :          logger%close_local_unit_on_dealloc = template_logger%close_local_unit_on_dealloc
     312          124 :          IF (logger%close_local_unit_on_dealloc) THEN
     313           59 :             logger%default_local_unit_nr = -1
     314              :          ELSE
     315           65 :             logger%default_local_unit_nr = template_logger%default_local_unit_nr
     316              :          END IF
     317          124 :          logger%close_global_unit_on_dealloc = template_logger%close_global_unit_on_dealloc
     318          124 :          IF (logger%close_global_unit_on_dealloc) THEN
     319            0 :             logger%default_global_unit_nr = -1
     320              :          ELSE
     321          124 :             logger%default_global_unit_nr = template_logger%default_global_unit_nr
     322              :          END IF
     323          124 :          logger%local_filename = template_logger%local_filename
     324          124 :          logger%global_filename = template_logger%global_filename
     325          124 :          logger%para_env => template_logger%para_env
     326          124 :          logger%suffix = template_logger%suffix
     327          124 :          logger%iter_info => template_logger%iter_info
     328              :       ELSE
     329              :          ! create a file if nothing is specified, one can also get the unit from the default logger
     330              :          ! which should have something reasonable as the argument is required in that case
     331        22581 :          logger%default_global_unit_nr = -1
     332        22581 :          logger%close_global_unit_on_dealloc = .TRUE.
     333        22581 :          logger%local_filename = "localLog"
     334        22581 :          logger%global_filename = "mainLog"
     335        22581 :          logger%print_level = cp_note_level
     336              :          ! generate a file for default local logger
     337              :          ! except the ionode that should write to the default global logger
     338        22581 :          logger%default_local_unit_nr = -1
     339        22581 :          logger%close_local_unit_on_dealloc = .TRUE.
     340        22581 :          logger%suffix = ""
     341              :       END IF
     342        22705 :       IF (PRESENT(para_env)) logger%para_env => para_env
     343        22705 :       IF (.NOT. ASSOCIATED(logger%para_env)) THEN
     344            0 :          CPABORT(routineP//" para env not associated")
     345              :       END IF
     346        22705 :       IF (.NOT. logger%para_env%is_valid()) THEN
     347            0 :          CPABORT(routineP//" para_env%ref_count<1")
     348              :       END IF
     349        22705 :       CALL logger%para_env%retain()
     350              : 
     351        22705 :       IF (PRESENT(print_level)) logger%print_level = print_level
     352              : 
     353        22705 :       IF (PRESENT(default_global_unit_nr)) THEN
     354        22587 :          logger%default_global_unit_nr = default_global_unit_nr
     355              :       END IF
     356        22705 :       IF (PRESENT(global_filename)) THEN
     357            0 :          logger%global_filename = global_filename
     358            0 :          logger%close_global_unit_on_dealloc = .TRUE.
     359            0 :          logger%default_global_unit_nr = -1
     360              :       END IF
     361        22705 :       IF (PRESENT(close_global_unit_on_dealloc)) THEN
     362        22587 :          logger%close_global_unit_on_dealloc = close_global_unit_on_dealloc
     363        22587 :          IF (PRESENT(default_global_unit_nr) .AND. PRESENT(global_filename) .AND. &
     364              :              (.NOT. close_global_unit_on_dealloc)) THEN
     365            0 :             logger%default_global_unit_nr = default_global_unit_nr
     366              :          END IF
     367              :       END IF
     368              : 
     369        22705 :       IF (PRESENT(default_local_unit_nr)) THEN
     370            0 :          logger%default_local_unit_nr = default_local_unit_nr
     371              :       END IF
     372        22705 :       IF (PRESENT(local_filename)) THEN
     373            0 :          logger%local_filename = local_filename
     374            0 :          logger%close_local_unit_on_dealloc = .TRUE.
     375            0 :          logger%default_local_unit_nr = -1
     376              :       END IF
     377        22705 :       IF (PRESENT(suffix)) logger%suffix = suffix
     378              : 
     379        22705 :       IF (PRESENT(close_local_unit_on_dealloc)) THEN
     380            0 :          logger%close_local_unit_on_dealloc = close_local_unit_on_dealloc
     381            0 :          IF (PRESENT(default_local_unit_nr) .AND. PRESENT(local_filename) .AND. &
     382              :              (.NOT. close_local_unit_on_dealloc)) THEN
     383            0 :             logger%default_local_unit_nr = default_local_unit_nr
     384              :          END IF
     385              :       END IF
     386              : 
     387        22705 :       IF (logger%default_local_unit_nr == -1) THEN
     388        22640 :          IF (logger%para_env%is_source()) THEN
     389        11773 :             logger%default_local_unit_nr = logger%default_global_unit_nr
     390        11773 :             logger%close_local_unit_on_dealloc = .FALSE.
     391              :          END IF
     392              :       END IF
     393        22705 :       IF (PRESENT(iter_info)) logger%iter_info => iter_info
     394        22705 :       IF (ASSOCIATED(logger%iter_info)) THEN
     395          124 :          CALL cp_iteration_info_retain(logger%iter_info)
     396              :       ELSE
     397        22581 :          CALL cp_iteration_info_create(logger%iter_info, "")
     398              :       END IF
     399        22705 :    END SUBROUTINE cp_logger_create
     400              : 
     401              : ! **************************************************************************************************
     402              : !> \brief retains the given logger (to be called to keep a shared copy of
     403              : !>      the logger)
     404              : !> \param logger the logger to retain
     405              : !> \par History
     406              : !>      08.2002 created [fawzi]
     407              : !> \author Fawzi Mohamed
     408              : ! **************************************************************************************************
     409       132492 :    SUBROUTINE cp_logger_retain(logger)
     410              :       TYPE(cp_logger_type), INTENT(INOUT)                :: logger
     411              : 
     412              :       CHARACTER(len=*), PARAMETER :: routineN = 'cp_logger_retain', &
     413              :          routineP = moduleN//':'//routineN
     414              : 
     415       132492 :       IF (logger%ref_count < 1) THEN
     416            0 :          CPABORT(routineP//" logger%ref_count<1")
     417              :       END IF
     418       132492 :       logger%ref_count = logger%ref_count + 1
     419       132492 :    END SUBROUTINE cp_logger_retain
     420              : 
     421              : ! **************************************************************************************************
     422              : !> \brief releases this logger
     423              : !> \param logger the logger to release
     424              : !> \par History
     425              : !>      4.2002 created [fawzi]
     426              : !> \author Fawzi Mohamed
     427              : ! **************************************************************************************************
     428       155197 :    SUBROUTINE cp_logger_release(logger)
     429              :       TYPE(cp_logger_type), POINTER                      :: logger
     430              : 
     431              :       CHARACTER(len=*), PARAMETER :: routineN = 'cp_logger_release', &
     432              :          routineP = moduleN//':'//routineN
     433              : 
     434       155197 :       IF (ASSOCIATED(logger)) THEN
     435       155197 :          IF (logger%ref_count < 1) THEN
     436            0 :             CPABORT(routineP//" logger%ref_count<1")
     437              :          END IF
     438       155197 :          logger%ref_count = logger%ref_count - 1
     439       155197 :          IF (logger%ref_count == 0) THEN
     440        22705 :             IF (logger%close_global_unit_on_dealloc .AND. &
     441              :                 logger%default_global_unit_nr >= 0) THEN
     442            1 :                CALL close_file(logger%default_global_unit_nr)
     443            1 :                logger%close_global_unit_on_dealloc = .FALSE.
     444            1 :                logger%default_global_unit_nr = -1
     445              :             END IF
     446        22705 :             IF (logger%close_local_unit_on_dealloc .AND. &
     447              :                 logger%default_local_unit_nr >= 0) THEN
     448          596 :                CALL close_file(logger%default_local_unit_nr)
     449          596 :                logger%close_local_unit_on_dealloc = .FALSE.
     450          596 :                logger%default_local_unit_nr = -1
     451              :             END IF
     452        22705 :             CALL mp_para_env_release(logger%para_env)
     453        22705 :             CALL cp_iteration_info_release(logger%iter_info)
     454        22705 :             DEALLOCATE (logger)
     455              :          END IF
     456              :       END IF
     457       155197 :       NULLIFY (logger)
     458       155197 :    END SUBROUTINE cp_logger_release
     459              : 
     460              : ! **************************************************************************************************
     461              : !> \brief this function can be called to check if the logger would log
     462              : !>      a message with the given level from the given source
     463              : !>      you should use this function if you do direct logging
     464              : !>      (without using cp_logger_log), or if you want to know if the generation
     465              : !>      of some costly log info is necessary
     466              : !> \param logger the logger you want to log in
     467              : !> \param level describes the of the message: cp_fatal_level(3),
     468              : !>     cp_failure_level(2), cp_warning_level(1), cp_note_level(0).
     469              : !> \return ...
     470              : !> \par History
     471              : !>      4.2002 revised [fawzi]
     472              : !> \author Fawzi Mohamed
     473              : ! **************************************************************************************************
     474         5330 :    FUNCTION cp_logger_would_log(logger, level) RESULT(res)
     475              :       TYPE(cp_logger_type), POINTER                      :: logger
     476              :       INTEGER, INTENT(in)                                :: level
     477              :       LOGICAL                                            :: res
     478              : 
     479              :       CHARACTER(len=*), PARAMETER :: routineN = 'cp_logger_would_log', &
     480              :          routineP = moduleN//':'//routineN
     481              : 
     482              :       TYPE(cp_logger_type), POINTER                      :: lggr
     483              : 
     484         5330 :       lggr => logger
     485         5330 :       IF (.NOT. ASSOCIATED(lggr)) lggr => cp_get_default_logger()
     486         5330 :       IF (lggr%ref_count < 1) THEN
     487            0 :          CPABORT(routineP//" logger%ref_count<1")
     488              :       END IF
     489              : 
     490         5330 :       res = level >= lggr%print_level
     491         5330 :    END FUNCTION cp_logger_would_log
     492              : 
     493              : ! **************************************************************************************************
     494              : !> \brief returns the unit nr for the requested kind of log.
     495              : !> \param logger the logger you want to log in
     496              : !> \param local if true returns a local logger (one per task), otherwise
     497              : !>     returns a global logger (only the process with para_env%mepos==
     498              : !>     para_env%source should write to the global logger). Defaults to
     499              : !>     false
     500              : !> \return ...
     501              : !> \par History
     502              : !>      4.2002 revised [fawzi]
     503              : !> \author Fawzi Mohamed
     504              : ! **************************************************************************************************
     505          212 :    FUNCTION cp_logger_get_unit_nr(logger, local) RESULT(res)
     506              :       TYPE(cp_logger_type), POINTER                      :: logger
     507              :       LOGICAL, INTENT(in), OPTIONAL                      :: local
     508              :       INTEGER                                            :: res
     509              : 
     510          212 :       res = cp_logger_get_default_unit_nr(logger, local=local)
     511          212 :    END FUNCTION cp_logger_get_unit_nr
     512              : 
     513              : ! **************************************************************************************************
     514              : !> \brief returns the unit nr for the ionode (-1 on all other processors)
     515              : !>        skips as well checks if the procs calling this function is not the ionode
     516              : !> \param logger the logger you want to log in
     517              : !> \return ...
     518              : !> \par History
     519              : !>      12.2009 created [tlaino]
     520              : !> \author Teodoro Laino
     521              : ! **************************************************************************************************
     522      9186260 :    FUNCTION cp_logger_get_default_io_unit(logger) RESULT(res)
     523              :       TYPE(cp_logger_type), OPTIONAL, POINTER            :: logger
     524              :       INTEGER                                            :: res
     525              : 
     526              :       TYPE(cp_logger_type), POINTER                      :: local_logger
     527              : 
     528      9186260 :       IF (PRESENT(logger)) THEN
     529       715220 :          local_logger => logger
     530      8471040 :       ELSE IF (stack_pointer == 0) THEN
     531      9186260 :          res = -1 ! edge case: default logger not yet/anymore available
     532              :          RETURN
     533              :       ELSE
     534      8471040 :          local_logger => cp_get_default_logger()
     535              :       END IF
     536              : 
     537      9186260 :       res = cp_logger_get_default_unit_nr(local_logger, local=.FALSE., skip_not_ionode=.TRUE.)
     538      9186260 :    END FUNCTION cp_logger_get_default_io_unit
     539              : 
     540              : ! *************************** cp_logger_type settings ***************************
     541              : 
     542              : ! **************************************************************************************************
     543              : !> \brief changes the logging level. Log messages with a level less than the one
     544              : !>      given wo not be printed.
     545              : !> \param logger the logger to change
     546              : !> \param level the new logging level for the logger
     547              : !> \par History
     548              : !>      4.2002 revised [fawzi]
     549              : !> \author Fawzi Mohamed
     550              : ! **************************************************************************************************
     551            0 :    SUBROUTINE cp_logger_set_log_level(logger, level)
     552              :       TYPE(cp_logger_type), INTENT(INOUT)                :: logger
     553              :       INTEGER, INTENT(in)                                :: level
     554              : 
     555              :       CHARACTER(len=*), PARAMETER :: routineN = 'cp_logger_set_log_level', &
     556              :          routineP = moduleN//':'//routineN
     557              : 
     558            0 :       IF (logger%ref_count < 1) THEN
     559            0 :          CPABORT(routineP//" logger%ref_count<1")
     560              :       END IF
     561            0 :       logger%print_level = level
     562            0 :    END SUBROUTINE cp_logger_set_log_level
     563              : 
     564              : ! **************************************************************************************************
     565              : !> \brief asks the default unit number of the given logger.
     566              : !>      try to use cp_logger_get_unit_nr
     567              : !> \param logger the logger you want info from
     568              : !> \param local if you want the local unit nr (defaults to false)
     569              : !> \param skip_not_ionode ...
     570              : !> \return ...
     571              : !> \par History
     572              : !>      4.2002 revised [fawzi]
     573              : !> \author Fawzi Mohamed
     574              : ! **************************************************************************************************
     575      9644209 :    RECURSIVE FUNCTION cp_logger_get_default_unit_nr(logger, local, skip_not_ionode) RESULT(res)
     576              :       TYPE(cp_logger_type), OPTIONAL, POINTER            :: logger
     577              :       LOGICAL, INTENT(in), OPTIONAL                      :: local, skip_not_ionode
     578              :       INTEGER                                            :: res
     579              : 
     580              :       CHARACTER(len=*), PARAMETER :: routineN = 'cp_logger_get_default_unit_nr', &
     581              :          routineP = moduleN//':'//routineN
     582              : 
     583              :       CHARACTER(len=default_path_length)                 :: filename, host_name
     584              :       INTEGER                                            :: iostat, pid
     585              :       LOGICAL                                            :: loc, skip
     586              :       TYPE(cp_logger_type), POINTER                      :: lggr
     587              : 
     588      9644209 :       loc = .TRUE.
     589      9644209 :       skip = .FALSE.
     590      9644209 :       IF (PRESENT(logger)) THEN
     591      9639892 :          lggr => logger
     592              :       ELSE
     593         4317 :          NULLIFY (lggr)
     594              :       END IF
     595      9644209 :       IF (.NOT. ASSOCIATED(lggr)) lggr => cp_get_default_logger()
     596      9644209 :       IF (lggr%ref_count < 1) THEN
     597            0 :          CPABORT(routineP//" logger%ref_count<1")
     598              :       END IF
     599              : 
     600      9644209 :       IF (PRESENT(local)) loc = local
     601      9644209 :       IF (PRESENT(skip_not_ionode)) skip = skip_not_ionode
     602      9644209 :       IF (.NOT. loc) THEN
     603      9577252 :          IF (lggr%default_global_unit_nr <= 0) THEN
     604      3853389 :             IF (lggr%para_env%is_source()) THEN
     605              :                CALL cp_logger_generate_filename(lggr, filename, lggr%global_filename, &
     606            0 :                                                 ".out", local=.FALSE.)
     607              :                CALL open_file(TRIM(filename), file_status="unknown", &
     608              :                               file_action="WRITE", file_position="APPEND", &
     609            0 :                               unit_number=lggr%default_global_unit_nr)
     610      3853389 :             ELSE IF (.NOT. skip) THEN
     611            2 :                lggr%default_global_unit_nr = cp_logger_get_default_unit_nr(lggr, .TRUE.)
     612            2 :                lggr%close_global_unit_on_dealloc = .FALSE.
     613              :             ELSE
     614      3853387 :                lggr%default_global_unit_nr = -1
     615      3853387 :                lggr%close_global_unit_on_dealloc = .FALSE.
     616              :             END IF
     617              :          END IF
     618      9577252 :          IF (.NOT. (lggr%para_env%is_source() .OR. skip)) THEN
     619              :             WRITE (UNIT=lggr%default_global_unit_nr, FMT='(/,T2,A)', IOSTAT=iostat) &
     620            2 :                ' *** WARNING non ionode asked for global logger ***'
     621            2 :             IF (iostat /= 0) THEN
     622            0 :                CALL m_getpid(pid)
     623            0 :                CALL m_hostnm(host_name)
     624            0 :                PRINT *, " *** Error trying to WRITE to the local logger ***"
     625            0 :                PRINT *, " *** MPI_id           = ", lggr%para_env%mepos
     626            0 :                PRINT *, " *** MPI_Communicator = ", lggr%para_env%get_handle()
     627            0 :                PRINT *, " *** PID              = ", pid
     628            0 :                PRINT *, " *** Hostname         = "//TRIM(host_name)
     629            0 :                CALL print_stack(default_output_unit)
     630              :             ELSE
     631            2 :                CALL print_stack(lggr%default_global_unit_nr)
     632              :             END IF
     633              :          END IF
     634      9577252 :          res = lggr%default_global_unit_nr
     635              :       ELSE
     636        66957 :          IF (lggr%default_local_unit_nr <= 0) THEN
     637              :             CALL cp_logger_generate_filename(lggr, filename, lggr%local_filename, &
     638          596 :                                              ".out", local=.TRUE.)
     639              :             CALL open_file(TRIM(filename), file_status="unknown", &
     640              :                            file_action="WRITE", &
     641              :                            file_position="APPEND", &
     642          596 :                            unit_number=lggr%default_local_unit_nr)
     643              :             WRITE (UNIT=lggr%default_local_unit_nr, FMT='(/,T2,A,I0,A,I0,A)', IOSTAT=iostat) &
     644          596 :                '*** Local logger file of MPI task ', lggr%para_env%mepos, &
     645         1192 :                ' in communicator ', lggr%para_env%get_handle(), ' ***'
     646          596 :             IF (iostat == 0) THEN
     647          596 :                CALL m_getpid(pid)
     648          596 :                CALL m_hostnm(host_name)
     649              :                WRITE (UNIT=lggr%default_local_unit_nr, FMT='(T2,A,I0)', IOSTAT=iostat) &
     650          596 :                   '*** PID      = ', pid, &
     651         1192 :                   '*** Hostname = '//host_name
     652          596 :                CALL print_stack(lggr%default_local_unit_nr)
     653              :             END IF
     654          596 :             IF (iostat /= 0) THEN
     655            0 :                CALL m_getpid(pid)
     656            0 :                CALL m_hostnm(host_name)
     657            0 :                PRINT *, " *** Error trying to WRITE to the local logger ***"
     658            0 :                PRINT *, " *** MPI_id           = ", lggr%para_env%mepos
     659            0 :                PRINT *, " *** MPI_Communicator = ", lggr%para_env%get_handle()
     660            0 :                PRINT *, " *** PID              = ", pid
     661            0 :                PRINT *, " *** Hostname         = "//TRIM(host_name)
     662            0 :                CALL print_stack(default_output_unit)
     663              :             END IF
     664              : 
     665              :          END IF
     666        66957 :          res = lggr%default_local_unit_nr
     667              :       END IF
     668      9644209 :    END FUNCTION cp_logger_get_default_unit_nr
     669              : 
     670              : ! **************************************************************************************************
     671              : !> \brief generates a unique filename (ie adding eventual suffixes and
     672              : !>      process ids)
     673              : !> \param logger ...
     674              : !> \param res the resulting string
     675              : !> \param root the start of filename
     676              : !> \param postfix the end of the name
     677              : !> \param local if the name should be local to this task (defaults to false)
     678              : !> \par History
     679              : !>      08.2002 created [fawzi]
     680              : !> \author Fawzi Mohamed
     681              : !> \note
     682              : !>      this should be a function returning a variable length string.
     683              : !>      All spaces are moved to the end of the string.
     684              : !>      Not fully optimized: result must be a little longer than the
     685              : !>      resulting compressed filename
     686              : ! **************************************************************************************************
     687       101845 :    SUBROUTINE cp_logger_generate_filename(logger, res, root, postfix, &
     688              :                                           local)
     689              :       TYPE(cp_logger_type), POINTER                      :: logger
     690              :       CHARACTER(len=*), INTENT(inout)                    :: res
     691              :       CHARACTER(len=*), INTENT(in)                       :: root, postfix
     692              :       LOGICAL, INTENT(in), OPTIONAL                      :: local
     693              : 
     694              :       CHARACTER(len=*), PARAMETER :: routineN = 'cp_logger_generate_filename', &
     695              :          routineP = moduleN//':'//routineN
     696              : 
     697              :       LOGICAL                                            :: loc
     698              :       TYPE(cp_logger_type), POINTER                      :: lggr
     699              : 
     700       101845 :       loc = .FALSE.
     701       101845 :       res = ' '
     702       101845 :       lggr => logger
     703              : 
     704       101845 :       IF (.NOT. ASSOCIATED(lggr)) lggr => cp_get_default_logger()
     705       101845 :       IF (lggr%ref_count < 1) THEN
     706            0 :          CPABORT(routineP//" logger%ref_count<1")
     707              :       END IF
     708       101845 :       IF (PRESENT(local)) loc = local
     709       101845 :       IF (loc) THEN
     710              :          res = TRIM(root)//TRIM(lggr%suffix)//'_p'// &
     711          819 :                cp_to_string(lggr%para_env%mepos)//postfix
     712              :       ELSE
     713       101026 :          res = TRIM(root)//TRIM(lggr%suffix)//postfix
     714              :       END IF
     715       101845 :       CALL compress(res, full=.TRUE.)
     716       101845 :    END SUBROUTINE cp_logger_generate_filename
     717              : 
     718              : ! **************************************************************************************************
     719              : !> \brief sets various attributes of the given logger
     720              : !> \param logger the logger you want to change
     721              : !> \param local_filename the root of the name of the file used for local
     722              : !>        logging
     723              : !> \param global_filename the root of the name of the file used for
     724              : !>        global logging
     725              : !> \author Fawzi Mohamed
     726              : ! **************************************************************************************************
     727        12179 :    SUBROUTINE cp_logger_set(logger, local_filename, global_filename)
     728              :       TYPE(cp_logger_type), INTENT(INOUT)                :: logger
     729              :       CHARACTER(len=*), INTENT(in), OPTIONAL             :: local_filename, global_filename
     730              : 
     731        12177 :       IF (PRESENT(local_filename)) logger%local_filename = local_filename
     732        12179 :       IF (PRESENT(global_filename)) logger%global_filename = global_filename
     733        12179 :    END SUBROUTINE cp_logger_set
     734              : 
     735              : ! **************************************************************************************************
     736              : !> \brief converts an int to a string
     737              : !>      (should be a variable length string, but that does not work with
     738              : !>      all the compilers)
     739              : !> \param i the integer to convert
     740              : !> \param fmt Optional format string
     741              : !> \return ...
     742              : !> \par History
     743              : !>      4.2002 revised [fawzi]
     744              : !> \author Fawzi Mohamed, MK
     745              : ! **************************************************************************************************
     746      9388048 :    FUNCTION cp_int_to_string(i, fmt) RESULT(res)
     747              :       INTEGER, INTENT(in)                                :: i
     748              :       CHARACTER(len=*), OPTIONAL                         :: fmt
     749              :       CHARACTER(len=25)                                  :: res
     750              : 
     751              :       CHARACTER(len=25)                                  :: t_res
     752              :       INTEGER                                            :: iostat
     753              :       REAL(KIND=dp)                                      :: tmp_r
     754              : 
     755      9388048 :       iostat = 0
     756      9388048 :       IF (PRESENT(fmt)) THEN
     757         1820 :          WRITE (t_res, FMT=fmt, IOSTAT=iostat) i
     758      9386228 :       ELSE IF (i > 999999 .OR. i < -99999) THEN
     759            1 :          tmp_r = i
     760            1 :          WRITE (t_res, FMT='(ES8.1)', IOSTAT=iostat) tmp_r
     761              :       ELSE
     762      9386227 :          WRITE (t_res, FMT='(I6)', IOSTAT=iostat) i
     763              :       END IF
     764      9388048 :       res = t_res
     765      9388048 :       IF (iostat /= 0) THEN
     766            0 :          PRINT *, "cp_int_to_string I/O error", iostat
     767            0 :          CALL print_stack(cp_logger_get_default_unit_nr())
     768              :       END IF
     769              : 
     770      9388048 :    END FUNCTION cp_int_to_string
     771              : 
     772              : ! **************************************************************************************************
     773              : !> \brief Convert a double precision real in a string
     774              : !>      (should be a variable length string, but that does not work with
     775              : !>      all the compilers)
     776              : !> \param val the number to convert
     777              : !> \param fmt Optional format string
     778              : !> \return ...
     779              : !> \par History
     780              : !>      4.2002 revised [fawzi]
     781              : !> \author Fawzi Mohamed, MK
     782              : ! **************************************************************************************************
     783       103411 :    FUNCTION cp_real_dp_to_string(val, fmt) RESULT(res)
     784              :       REAL(KIND=dp), INTENT(in)                          :: val
     785              :       CHARACTER(len=*), OPTIONAL                         :: fmt
     786              :       CHARACTER(len=25)                                  :: res
     787              : 
     788              :       INTEGER                                            :: iostat
     789              : 
     790       103411 :       IF (PRESENT(fmt)) THEN
     791         1820 :          WRITE (res, FMT=fmt, IOSTAT=iostat) val
     792              :       ELSE
     793       101591 :          WRITE (res, FMT='(ES11.4)', IOSTAT=iostat) val
     794              :       END IF
     795       103411 :       IF (iostat /= 0) THEN
     796            0 :          PRINT *, "cp_real_dp_to_string I/O error", iostat
     797            0 :          CALL print_stack(cp_logger_get_default_unit_nr())
     798              :       END IF
     799              : 
     800       103411 :    END FUNCTION cp_real_dp_to_string
     801              : 
     802              : ! **************************************************************************************************
     803              : !> \brief convert a logical in a string ('T' or 'F')
     804              : !> \param val the number to convert
     805              : !> \return ...
     806              : !> \author fawzi
     807              : ! **************************************************************************************************
     808            0 :    ELEMENTAL FUNCTION cp_logical_to_string(val) RESULT(res)
     809              :       LOGICAL, INTENT(in)                                :: val
     810              :       CHARACTER(len=1)                                   :: res
     811              : 
     812            0 :       IF (val) THEN
     813            0 :          res = 'T'
     814              :       ELSE
     815            0 :          res = 'F'
     816              :       END IF
     817            0 :    END FUNCTION cp_logical_to_string
     818              : 
     819            0 : END MODULE cp_log_handling
     820              : 
        

Generated by: LCOV version 2.0-1