(git:9ccafda)
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 IF (local_logger%ref_count < 1) THEN
536 ! edge case: the default logger is just being released (e.g. a warning issued during
537 ! cp_rm_default_logger). Do not abort, because the error handlers call this function
538 ! themselves, which would result in an infinite recursion.
539 res = -1
540 RETURN
541 END IF
542 END IF
543
544 res = cp_logger_get_default_unit_nr(local_logger, local=.false., skip_not_ionode=.true.)
546
547! *************************** cp_logger_type settings ***************************
548
549! **************************************************************************************************
550!> \brief changes the logging level. Log messages with a level less than the one
551!> given wo not be printed.
552!> \param logger the logger to change
553!> \param level the new logging level for the logger
554!> \par History
555!> 4.2002 revised [fawzi]
556!> \author Fawzi Mohamed
557! **************************************************************************************************
558 SUBROUTINE cp_logger_set_log_level(logger, level)
559 TYPE(cp_logger_type), INTENT(INOUT) :: logger
560 INTEGER, INTENT(in) :: level
561
562 CHARACTER(len=*), PARAMETER :: routinen = 'cp_logger_set_log_level', &
563 routinep = modulen//':'//routinen
564
565 IF (logger%ref_count < 1) THEN
566 cpabort(routinep//" logger%ref_count<1")
567 END IF
568 logger%print_level = level
569 END SUBROUTINE cp_logger_set_log_level
570
571! **************************************************************************************************
572!> \brief asks the default unit number of the given logger.
573!> try to use cp_logger_get_unit_nr
574!> \param logger the logger you want info from
575!> \param local if you want the local unit nr (defaults to false)
576!> \param skip_not_ionode ...
577!> \return ...
578!> \par History
579!> 4.2002 revised [fawzi]
580!> \author Fawzi Mohamed
581! **************************************************************************************************
582 RECURSIVE FUNCTION cp_logger_get_default_unit_nr(logger, local, skip_not_ionode) RESULT(res)
583 TYPE(cp_logger_type), OPTIONAL, POINTER :: logger
584 LOGICAL, INTENT(in), OPTIONAL :: local, skip_not_ionode
585 INTEGER :: res
586
587 CHARACTER(len=*), PARAMETER :: routinen = 'cp_logger_get_default_unit_nr', &
588 routinep = modulen//':'//routinen
589
590 CHARACTER(len=default_path_length) :: filename, host_name
591 INTEGER :: iostat, pid
592 LOGICAL :: loc, skip
593 TYPE(cp_logger_type), POINTER :: lggr
594
595 loc = .true.
596 skip = .false.
597 IF (PRESENT(logger)) THEN
598 lggr => logger
599 ELSE
600 NULLIFY (lggr)
601 END IF
602 IF (.NOT. ASSOCIATED(lggr)) lggr => cp_get_default_logger()
603 IF (lggr%ref_count < 1) THEN
604 cpabort(routinep//" logger%ref_count<1")
605 END IF
606
607 IF (PRESENT(local)) loc = local
608 IF (PRESENT(skip_not_ionode)) skip = skip_not_ionode
609 IF (.NOT. loc) THEN
610 IF (lggr%default_global_unit_nr <= 0) THEN
611 IF (lggr%para_env%is_source()) THEN
612 CALL cp_logger_generate_filename(lggr, filename, lggr%global_filename, &
613 ".out", local=.false.)
614 CALL open_file(trim(filename), file_status="unknown", &
615 file_action="WRITE", file_position="APPEND", &
616 unit_number=lggr%default_global_unit_nr)
617 ELSE IF (.NOT. skip) THEN
618 lggr%default_global_unit_nr = cp_logger_get_default_unit_nr(lggr, .true.)
619 lggr%close_global_unit_on_dealloc = .false.
620 ELSE
621 lggr%default_global_unit_nr = -1
622 lggr%close_global_unit_on_dealloc = .false.
623 END IF
624 END IF
625 IF (.NOT. (lggr%para_env%is_source() .OR. skip)) THEN
626 WRITE (unit=lggr%default_global_unit_nr, fmt='(/,T2,A)', iostat=iostat) &
627 ' *** WARNING non ionode asked for global logger ***'
628 IF (iostat /= 0) THEN
629 CALL m_getpid(pid)
630 CALL m_hostnm(host_name)
631 print *, " *** Error trying to WRITE to the local logger ***"
632 print *, " *** MPI_id = ", lggr%para_env%mepos
633 print *, " *** MPI_Communicator = ", lggr%para_env%get_handle()
634 print *, " *** PID = ", pid
635 print *, " *** Hostname = "//trim(host_name)
636 CALL print_stack(default_output_unit)
637 ELSE
638 CALL print_stack(lggr%default_global_unit_nr)
639 END IF
640 END IF
641 res = lggr%default_global_unit_nr
642 ELSE
643 IF (lggr%default_local_unit_nr <= 0) THEN
644 CALL cp_logger_generate_filename(lggr, filename, lggr%local_filename, &
645 ".out", local=.true.)
646 CALL open_file(trim(filename), file_status="unknown", &
647 file_action="WRITE", &
648 file_position="APPEND", &
649 unit_number=lggr%default_local_unit_nr)
650 WRITE (unit=lggr%default_local_unit_nr, fmt='(/,T2,A,I0,A,I0,A)', iostat=iostat) &
651 '*** Local logger file of MPI task ', lggr%para_env%mepos, &
652 ' in communicator ', lggr%para_env%get_handle(), ' ***'
653 IF (iostat == 0) THEN
654 CALL m_getpid(pid)
655 CALL m_hostnm(host_name)
656 WRITE (unit=lggr%default_local_unit_nr, fmt='(T2,A,I0)', iostat=iostat) &
657 '*** PID = ', pid, &
658 '*** Hostname = '//host_name
659 CALL print_stack(lggr%default_local_unit_nr)
660 END IF
661 IF (iostat /= 0) THEN
662 CALL m_getpid(pid)
663 CALL m_hostnm(host_name)
664 print *, " *** Error trying to WRITE to the local logger ***"
665 print *, " *** MPI_id = ", lggr%para_env%mepos
666 print *, " *** MPI_Communicator = ", lggr%para_env%get_handle()
667 print *, " *** PID = ", pid
668 print *, " *** Hostname = "//trim(host_name)
669 CALL print_stack(default_output_unit)
670 END IF
671
672 END IF
673 res = lggr%default_local_unit_nr
674 END IF
676
677! **************************************************************************************************
678!> \brief generates a unique filename (ie adding eventual suffixes and
679!> process ids)
680!> \param logger ...
681!> \param res the resulting string
682!> \param root the start of filename
683!> \param postfix the end of the name
684!> \param local if the name should be local to this task (defaults to false)
685!> \par History
686!> 08.2002 created [fawzi]
687!> \author Fawzi Mohamed
688!> \note
689!> this should be a function returning a variable length string.
690!> All spaces are moved to the end of the string.
691!> Not fully optimized: result must be a little longer than the
692!> resulting compressed filename
693! **************************************************************************************************
694 SUBROUTINE cp_logger_generate_filename(logger, res, root, postfix, &
695 local)
696 TYPE(cp_logger_type), POINTER :: logger
697 CHARACTER(len=*), INTENT(inout) :: res
698 CHARACTER(len=*), INTENT(in) :: root, postfix
699 LOGICAL, INTENT(in), OPTIONAL :: local
700
701 CHARACTER(len=*), PARAMETER :: routinen = 'cp_logger_generate_filename', &
702 routinep = modulen//':'//routinen
703
704 LOGICAL :: loc
705 TYPE(cp_logger_type), POINTER :: lggr
706
707 loc = .false.
708 res = ' '
709 lggr => logger
710
711 IF (.NOT. ASSOCIATED(lggr)) lggr => cp_get_default_logger()
712 IF (lggr%ref_count < 1) THEN
713 cpabort(routinep//" logger%ref_count<1")
714 END IF
715 IF (PRESENT(local)) loc = local
716 IF (loc) THEN
717 res = trim(root)//trim(lggr%suffix)//'_p'// &
718 cp_to_string(lggr%para_env%mepos)//postfix
719 ELSE
720 res = trim(root)//trim(lggr%suffix)//postfix
721 END IF
722 CALL compress(res, full=.true.)
723 END SUBROUTINE cp_logger_generate_filename
724
725! **************************************************************************************************
726!> \brief sets various attributes of the given logger
727!> \param logger the logger you want to change
728!> \param local_filename the root of the name of the file used for local
729!> logging
730!> \param global_filename the root of the name of the file used for
731!> global logging
732!> \author Fawzi Mohamed
733! **************************************************************************************************
734 SUBROUTINE cp_logger_set(logger, local_filename, global_filename)
735 TYPE(cp_logger_type), INTENT(INOUT) :: logger
736 CHARACTER(len=*), INTENT(in), OPTIONAL :: local_filename, global_filename
737
738 IF (PRESENT(local_filename)) logger%local_filename = local_filename
739 IF (PRESENT(global_filename)) logger%global_filename = global_filename
740 END SUBROUTINE cp_logger_set
741
742! **************************************************************************************************
743!> \brief converts an int to a string
744!> (should be a variable length string, but that does not work with
745!> all the compilers)
746!> \param i the integer to convert
747!> \param fmt Optional format string
748!> \return ...
749!> \par History
750!> 4.2002 revised [fawzi]
751!> \author Fawzi Mohamed, MK
752! **************************************************************************************************
753 FUNCTION cp_int_to_string(i, fmt) RESULT(res)
754 INTEGER, INTENT(in) :: i
755 CHARACTER(len=*), OPTIONAL :: fmt
756 CHARACTER(len=25) :: res
757
758 CHARACTER(len=25) :: t_res
759 INTEGER :: iostat
760 REAL(kind=dp) :: tmp_r
761
762 iostat = 0
763 IF (PRESENT(fmt)) THEN
764 WRITE (t_res, fmt=fmt, iostat=iostat) i
765 ELSE IF (i > 999999 .OR. i < -99999) THEN
766 tmp_r = i
767 WRITE (t_res, fmt='(ES8.1)', iostat=iostat) tmp_r
768 ELSE
769 WRITE (t_res, fmt='(I6)', iostat=iostat) i
770 END IF
771 res = t_res
772 IF (iostat /= 0) THEN
773 print *, "cp_int_to_string I/O error", iostat
774 CALL print_stack(cp_logger_get_default_unit_nr())
775 END IF
776
777 END FUNCTION cp_int_to_string
778
779! **************************************************************************************************
780!> \brief Convert a double precision real in a string
781!> (should be a variable length string, but that does not work with
782!> all the compilers)
783!> \param val the number to convert
784!> \param fmt Optional format string
785!> \return ...
786!> \par History
787!> 4.2002 revised [fawzi]
788!> \author Fawzi Mohamed, MK
789! **************************************************************************************************
790 FUNCTION cp_real_dp_to_string(val, fmt) RESULT(res)
791 REAL(kind=dp), INTENT(in) :: val
792 CHARACTER(len=*), OPTIONAL :: fmt
793 CHARACTER(len=25) :: res
794
795 INTEGER :: iostat
796
797 IF (PRESENT(fmt)) THEN
798 WRITE (res, fmt=fmt, iostat=iostat) val
799 ELSE
800 WRITE (res, fmt='(ES11.4)', iostat=iostat) val
801 END IF
802 IF (iostat /= 0) THEN
803 print *, "cp_real_dp_to_string I/O error", iostat
804 CALL print_stack(cp_logger_get_default_unit_nr())
805 END IF
806
807 END FUNCTION cp_real_dp_to_string
808
809! **************************************************************************************************
810!> \brief convert a logical in a string ('T' or 'F')
811!> \param val the number to convert
812!> \return ...
813!> \author fawzi
814! **************************************************************************************************
815 ELEMENTAL FUNCTION cp_logical_to_string(val) RESULT(res)
816 LOGICAL, INTENT(in) :: val
817 CHARACTER(len=1) :: res
818
819 IF (val) THEN
820 res = 'T'
821 ELSE
822 res = 'F'
823 END IF
824 END FUNCTION cp_logical_to_string
825
826END MODULE cp_log_handling
827
Utility routines to open and close files.
Definition cp_files.F:22
subroutine, public open_file(file_name, unit_number, file_status, file_form, file_action, file_position, file_pad, file_access, debug)
Opens a file and returns its logical unit number.
Definition cp_files.F:196
subroutine, public close_file(unit_number, file_status)
Closes an open file given by its logical unit number.
Definition cp_files.F:63
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:657
integer, parameter, public default_output_unit
Definition machine.F:47
subroutine, public m_hostnm(hname)
...
Definition machine.F:582
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