(git:d2a9ebd)
Loading...
Searching...
No Matches
cp_log_handling.F
Go to the documentation of this file.
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! **************************************************************************************************
42 USE cp_files, ONLY: close_file,&
48 USE kinds, ONLY: default_path_length,&
50 dp
51 USE machine, ONLY: default_output_unit,&
52 m_getpid,&
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
65 !API parameter vars
67 !API default loggers
70 !API logger routines
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! **************************************************************************************************
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
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
165CONTAINS
166
167! **************************************************************************************************
168!> \brief ...
169!> \return ...
170!> \author fawzi
171! **************************************************************************************************
172 FUNCTION cp_default_logger_stack_size() RESULT(res)
173 INTEGER :: res
174
175 res = stack_pointer
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 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 IF (stack_pointer + 1 > max_stack_pointer) THEN
194 CALL cp_abort(__location__, routinep// &
195 "too many default loggers, increase max_stack_pointer in "//modulen)
196 END IF
197
198 stack_pointer = stack_pointer + 1
199 NULLIFY (default_logger_stack(stack_pointer)%cp_default_logger)
200
201 default_logger_stack(stack_pointer)%cp_default_logger => logger
202 CALL cp_logger_retain(logger)
203
204 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! **************************************************************************************************
213 IF (stack_pointer - 1 < 0) THEN
214 CALL cp_abort(__location__, modulen//":cp_rm_default_logger "// &
215 "can not destroy default logger "//modulen)
216 END IF
217
218 CALL cp_logger_release(default_logger_stack(stack_pointer)%cp_default_logger)
219 NULLIFY (default_logger_stack(stack_pointer)%cp_default_logger)
220 stack_pointer = stack_pointer - 1
221
222 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 FUNCTION cp_get_default_logger() RESULT(res)
234 TYPE(cp_logger_type), POINTER :: res
235
236 IF (.NOT. stack_pointer > 0) THEN
237 CALL cp_abort(__location__, "cp_log_handling:cp_get_default_logger "// &
238 "default logger not yet initialized (CALL cp_init_default_logger)")
239 END IF
240 res => default_logger_stack(stack_pointer)%cp_default_logger
241 IF (.NOT. ASSOCIATED(res)) THEN
242 CALL cp_abort(__location__, "cp_log_handling:cp_get_default_logger "// &
243 "default logger is null (released too much ?)")
244 END IF
245 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 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 ALLOCATE (logger)
300
301 NULLIFY (logger%para_env)
302 NULLIFY (logger%iter_info)
303 logger%ref_count = 1
304
305 IF (PRESENT(template_logger)) THEN
306 IF (template_logger%ref_count < 1) THEN
307 cpabort(routinep//" template_logger%ref_count<1")
308 END IF
309 logger%print_level = template_logger%print_level
310 logger%default_global_unit_nr = template_logger%default_global_unit_nr
311 logger%close_local_unit_on_dealloc = template_logger%close_local_unit_on_dealloc
312 IF (logger%close_local_unit_on_dealloc) THEN
313 logger%default_local_unit_nr = -1
314 ELSE
315 logger%default_local_unit_nr = template_logger%default_local_unit_nr
316 END IF
317 logger%close_global_unit_on_dealloc = template_logger%close_global_unit_on_dealloc
318 IF (logger%close_global_unit_on_dealloc) THEN
319 logger%default_global_unit_nr = -1
320 ELSE
321 logger%default_global_unit_nr = template_logger%default_global_unit_nr
322 END IF
323 logger%local_filename = template_logger%local_filename
324 logger%global_filename = template_logger%global_filename
325 logger%para_env => template_logger%para_env
326 logger%suffix = template_logger%suffix
327 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 logger%default_global_unit_nr = -1
332 logger%close_global_unit_on_dealloc = .true.
333 logger%local_filename = "localLog"
334 logger%global_filename = "mainLog"
335 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 logger%default_local_unit_nr = -1
339 logger%close_local_unit_on_dealloc = .true.
340 logger%suffix = ""
341 END IF
342 IF (PRESENT(para_env)) logger%para_env => para_env
343 IF (.NOT. ASSOCIATED(logger%para_env)) THEN
344 cpabort(routinep//" para env not associated")
345 END IF
346 IF (.NOT. logger%para_env%is_valid()) THEN
347 cpabort(routinep//" para_env%ref_count<1")
348 END IF
349 CALL logger%para_env%retain()
350
351 IF (PRESENT(print_level)) logger%print_level = print_level
352
353 IF (PRESENT(default_global_unit_nr)) THEN
354 logger%default_global_unit_nr = default_global_unit_nr
355 END IF
356 IF (PRESENT(global_filename)) THEN
357 logger%global_filename = global_filename
358 logger%close_global_unit_on_dealloc = .true.
359 logger%default_global_unit_nr = -1
360 END IF
361 IF (PRESENT(close_global_unit_on_dealloc)) THEN
362 logger%close_global_unit_on_dealloc = close_global_unit_on_dealloc
363 IF (PRESENT(default_global_unit_nr) .AND. PRESENT(global_filename) .AND. &
364 (.NOT. close_global_unit_on_dealloc)) THEN
365 logger%default_global_unit_nr = default_global_unit_nr
366 END IF
367 END IF
368
369 IF (PRESENT(default_local_unit_nr)) THEN
370 logger%default_local_unit_nr = default_local_unit_nr
371 END IF
372 IF (PRESENT(local_filename)) THEN
373 logger%local_filename = local_filename
374 logger%close_local_unit_on_dealloc = .true.
375 logger%default_local_unit_nr = -1
376 END IF
377 IF (PRESENT(suffix)) logger%suffix = suffix
378
379 IF (PRESENT(close_local_unit_on_dealloc)) THEN
380 logger%close_local_unit_on_dealloc = close_local_unit_on_dealloc
381 IF (PRESENT(default_local_unit_nr) .AND. PRESENT(local_filename) .AND. &
382 (.NOT. close_local_unit_on_dealloc)) THEN
383 logger%default_local_unit_nr = default_local_unit_nr
384 END IF
385 END IF
386
387 IF (logger%default_local_unit_nr == -1) THEN
388 IF (logger%para_env%is_source()) THEN
389 logger%default_local_unit_nr = logger%default_global_unit_nr
390 logger%close_local_unit_on_dealloc = .false.
391 END IF
392 END IF
393 IF (PRESENT(iter_info)) logger%iter_info => iter_info
394 IF (ASSOCIATED(logger%iter_info)) THEN
395 CALL cp_iteration_info_retain(logger%iter_info)
396 ELSE
397 CALL cp_iteration_info_create(logger%iter_info, "")
398 END IF
399 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 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 IF (logger%ref_count < 1) THEN
416 cpabort(routinep//" logger%ref_count<1")
417 END IF
418 logger%ref_count = logger%ref_count + 1
419 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 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 IF (ASSOCIATED(logger)) THEN
435 IF (logger%ref_count < 1) THEN
436 cpabort(routinep//" logger%ref_count<1")
437 END IF
438 logger%ref_count = logger%ref_count - 1
439 IF (logger%ref_count == 0) THEN
440 IF (logger%close_global_unit_on_dealloc .AND. &
441 logger%default_global_unit_nr >= 0) THEN
442 CALL close_file(logger%default_global_unit_nr)
443 logger%close_global_unit_on_dealloc = .false.
444 logger%default_global_unit_nr = -1
445 END IF
446 IF (logger%close_local_unit_on_dealloc .AND. &
447 logger%default_local_unit_nr >= 0) THEN
448 CALL close_file(logger%default_local_unit_nr)
449 logger%close_local_unit_on_dealloc = .false.
450 logger%default_local_unit_nr = -1
451 END IF
452 CALL mp_para_env_release(logger%para_env)
453 CALL cp_iteration_info_release(logger%iter_info)
454 DEALLOCATE (logger)
455 END IF
456 END IF
457 NULLIFY (logger)
458 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 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 lggr => logger
485 IF (.NOT. ASSOCIATED(lggr)) lggr => cp_get_default_logger()
486 IF (lggr%ref_count < 1) THEN
487 cpabort(routinep//" logger%ref_count<1")
488 END IF
489
490 res = level >= lggr%print_level
491 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 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 res = cp_logger_get_default_unit_nr(logger, local=local)
511 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 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 IF (PRESENT(logger)) THEN
529 local_logger => logger
530 ELSE IF (stack_pointer == 0) THEN
531 res = -1 ! edge case: default logger not yet/anymore available
532 RETURN
533 ELSE
534 local_logger => cp_get_default_logger()
535 END IF
536
537 res = cp_logger_get_default_unit_nr(local_logger, local=.false., skip_not_ionode=.true.)
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 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 IF (logger%ref_count < 1) THEN
559 cpabort(routinep//" logger%ref_count<1")
560 END IF
561 logger%print_level = level
562 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 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 loc = .true.
589 skip = .false.
590 IF (PRESENT(logger)) THEN
591 lggr => logger
592 ELSE
593 NULLIFY (lggr)
594 END IF
595 IF (.NOT. ASSOCIATED(lggr)) lggr => cp_get_default_logger()
596 IF (lggr%ref_count < 1) THEN
597 cpabort(routinep//" logger%ref_count<1")
598 END IF
599
600 IF (PRESENT(local)) loc = local
601 IF (PRESENT(skip_not_ionode)) skip = skip_not_ionode
602 IF (.NOT. loc) THEN
603 IF (lggr%default_global_unit_nr <= 0) THEN
604 IF (lggr%para_env%is_source()) THEN
605 CALL cp_logger_generate_filename(lggr, filename, lggr%global_filename, &
606 ".out", local=.false.)
607 CALL open_file(trim(filename), file_status="unknown", &
608 file_action="WRITE", file_position="APPEND", &
609 unit_number=lggr%default_global_unit_nr)
610 ELSE IF (.NOT. skip) THEN
611 lggr%default_global_unit_nr = cp_logger_get_default_unit_nr(lggr, .true.)
612 lggr%close_global_unit_on_dealloc = .false.
613 ELSE
614 lggr%default_global_unit_nr = -1
615 lggr%close_global_unit_on_dealloc = .false.
616 END IF
617 END IF
618 IF (.NOT. (lggr%para_env%is_source() .OR. skip)) THEN
619 WRITE (unit=lggr%default_global_unit_nr, fmt='(/,T2,A)', iostat=iostat) &
620 ' *** WARNING non ionode asked for global logger ***'
621 IF (iostat /= 0) THEN
622 CALL m_getpid(pid)
623 CALL m_hostnm(host_name)
624 print *, " *** Error trying to WRITE to the local logger ***"
625 print *, " *** MPI_id = ", lggr%para_env%mepos
626 print *, " *** MPI_Communicator = ", lggr%para_env%get_handle()
627 print *, " *** PID = ", pid
628 print *, " *** Hostname = "//trim(host_name)
629 CALL print_stack(default_output_unit)
630 ELSE
631 CALL print_stack(lggr%default_global_unit_nr)
632 END IF
633 END IF
634 res = lggr%default_global_unit_nr
635 ELSE
636 IF (lggr%default_local_unit_nr <= 0) THEN
637 CALL cp_logger_generate_filename(lggr, filename, lggr%local_filename, &
638 ".out", local=.true.)
639 CALL open_file(trim(filename), file_status="unknown", &
640 file_action="WRITE", &
641 file_position="APPEND", &
642 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 '*** Local logger file of MPI task ', lggr%para_env%mepos, &
645 ' in communicator ', lggr%para_env%get_handle(), ' ***'
646 IF (iostat == 0) THEN
647 CALL m_getpid(pid)
648 CALL m_hostnm(host_name)
649 WRITE (unit=lggr%default_local_unit_nr, fmt='(T2,A,I0)', iostat=iostat) &
650 '*** PID = ', pid, &
651 '*** Hostname = '//host_name
652 CALL print_stack(lggr%default_local_unit_nr)
653 END IF
654 IF (iostat /= 0) THEN
655 CALL m_getpid(pid)
656 CALL m_hostnm(host_name)
657 print *, " *** Error trying to WRITE to the local logger ***"
658 print *, " *** MPI_id = ", lggr%para_env%mepos
659 print *, " *** MPI_Communicator = ", lggr%para_env%get_handle()
660 print *, " *** PID = ", pid
661 print *, " *** Hostname = "//trim(host_name)
662 CALL print_stack(default_output_unit)
663 END IF
664
665 END IF
666 res = lggr%default_local_unit_nr
667 END IF
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 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 loc = .false.
701 res = ' '
702 lggr => logger
703
704 IF (.NOT. ASSOCIATED(lggr)) lggr => cp_get_default_logger()
705 IF (lggr%ref_count < 1) THEN
706 cpabort(routinep//" logger%ref_count<1")
707 END IF
708 IF (PRESENT(local)) loc = local
709 IF (loc) THEN
710 res = trim(root)//trim(lggr%suffix)//'_p'// &
711 cp_to_string(lggr%para_env%mepos)//postfix
712 ELSE
713 res = trim(root)//trim(lggr%suffix)//postfix
714 END IF
715 CALL compress(res, full=.true.)
716 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 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 IF (PRESENT(local_filename)) logger%local_filename = local_filename
732 IF (PRESENT(global_filename)) logger%global_filename = global_filename
733 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 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 iostat = 0
756 IF (PRESENT(fmt)) THEN
757 WRITE (t_res, fmt=fmt, iostat=iostat) i
758 ELSE IF (i > 999999 .OR. i < -99999) THEN
759 tmp_r = i
760 WRITE (t_res, fmt='(ES8.1)', iostat=iostat) tmp_r
761 ELSE
762 WRITE (t_res, fmt='(I6)', iostat=iostat) i
763 END IF
764 res = t_res
765 IF (iostat /= 0) THEN
766 print *, "cp_int_to_string I/O error", iostat
767 CALL print_stack(cp_logger_get_default_unit_nr())
768 END IF
769
770 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 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 IF (PRESENT(fmt)) THEN
791 WRITE (res, fmt=fmt, iostat=iostat) val
792 ELSE
793 WRITE (res, fmt='(ES11.4)', iostat=iostat) val
794 END IF
795 IF (iostat /= 0) THEN
796 print *, "cp_real_dp_to_string I/O error", iostat
797 CALL print_stack(cp_logger_get_default_unit_nr())
798 END IF
799
800 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 ELEMENTAL FUNCTION cp_logical_to_string(val) RESULT(res)
809 LOGICAL, INTENT(in) :: val
810 CHARACTER(len=1) :: res
811
812 IF (val) THEN
813 res = 'T'
814 ELSE
815 res = 'F'
816 END IF
817 END FUNCTION cp_logical_to_string
818
819END MODULE cp_log_handling
820
Utility routines to open and close files. Tracking of preconnections.
Definition cp_files.F:16
subroutine, public open_file(file_name, file_status, file_form, file_action, file_position, file_pad, unit_number, debug, skip_get_unit_number, file_access)
Opens the requested file using a free unit number.
Definition cp_files.F:311
subroutine, public close_file(unit_number, file_status, keep_preconnection)
Close an open file given by its logical unit number. Optionally, keep the file and unit preconnected.
Definition cp_files.F:122
Collection of routines to handle the iteration info.
pure subroutine, public cp_iteration_info_create(iteration_info, project_name)
creates an output info object
subroutine, public cp_iteration_info_retain(iteration_info)
retains the iteration_info (see doc/ReferenceCounting.html)
subroutine, public cp_iteration_info_release(iteration_info)
releases the iteration_info (see doc/ReferenceCounting.html)
various routines to log and control the output. The idea is that decisions about where to log should ...
logical function, public cp_logger_would_log(logger, level)
this function can be called to check if the logger would log a message with the given level from the ...
recursive integer function, public cp_logger_get_default_unit_nr(logger, local, skip_not_ionode)
asks the default unit number of the given logger. try to use cp_logger_get_unit_nr
subroutine, public cp_logger_set(logger, local_filename, global_filename)
sets various attributes of the given logger
subroutine, public cp_rm_default_logger()
the cousin of cp_add_default_logger, decrements the stack, so that the default logger is what it has ...
subroutine, public cp_logger_release(logger)
releases this logger
integer, parameter, public cp_note_level
integer function, public cp_logger_get_unit_nr(logger, local)
returns the unit nr for the requested kind of log.
integer function, public cp_logger_get_default_io_unit(logger)
returns the unit nr for the ionode (-1 on all other processors) skips as well checks if the procs cal...
subroutine, public cp_logger_set_log_level(logger, level)
changes the logging level. Log messages with a level less than the one given wo not be printed.
subroutine, public cp_logger_create(logger, para_env, print_level, default_global_unit_nr, default_local_unit_nr, global_filename, local_filename, close_global_unit_on_dealloc, iter_info, close_local_unit_on_dealloc, suffix, template_logger)
initializes a logger
subroutine, public cp_logger_generate_filename(logger, res, root, postfix, local)
generates a unique filename (ie adding eventual suffixes and process ids)
integer function, public cp_default_logger_stack_size()
...
integer, parameter, public cp_failure_level
integer, parameter, public cp_fatal_level
subroutine, public cp_logger_retain(logger)
retains the given logger (to be called to keep a shared copy of the logger)
integer, parameter, public cp_warning_level
subroutine, public cp_add_default_logger(logger)
adds a default logger. MUST be called before logging occours
type(cp_logger_type) function, pointer, public cp_get_default_logger()
returns the default logger
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
integer, parameter, public default_string_length
Definition kinds.F:57
integer, parameter, public default_path_length
Definition kinds.F:58
Machine interface based on Fortran 2003 and POSIX.
Definition machine.F:17
subroutine, public m_getpid(pid)
...
Definition machine.F:655
integer, parameter, public default_output_unit
Definition machine.F:46
subroutine, public m_hostnm(hname)
...
Definition machine.F:580
Interface to the message passing library MPI.
subroutine, public mp_para_env_release(para_env)
releases the para object (to be called when you don't want anymore the shared copy of this object)
Utilities for string manipulations.
subroutine, public compress(string, full)
Eliminate multiple space characters in a string. If full is .TRUE., then all spaces are eliminated.
Timing routines for accounting.
Definition timings.F:17
subroutine, public print_stack(unit_nr)
Print current routine stack.
Definition timings.F:437
contains the information about the current state of the program to be able to decide if output is nec...
type of a logger, at the moment it contains just a print level starting at which level it should be l...
stores all the informations relevant to an mpi environment