(git:374b731)
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-2024 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) &
307 cpabort(routinep//" template_logger%ref_count<1")
308 logger%print_level = template_logger%print_level
309 logger%default_global_unit_nr = template_logger%default_global_unit_nr
310 logger%close_local_unit_on_dealloc = template_logger%close_local_unit_on_dealloc
311 IF (logger%close_local_unit_on_dealloc) THEN
312 logger%default_local_unit_nr = -1
313 ELSE
314 logger%default_local_unit_nr = template_logger%default_local_unit_nr
315 END IF
316 logger%close_global_unit_on_dealloc = template_logger%close_global_unit_on_dealloc
317 IF (logger%close_global_unit_on_dealloc) THEN
318 logger%default_global_unit_nr = -1
319 ELSE
320 logger%default_global_unit_nr = template_logger%default_global_unit_nr
321 END IF
322 logger%local_filename = template_logger%local_filename
323 logger%global_filename = template_logger%global_filename
324 logger%para_env => template_logger%para_env
325 logger%suffix = template_logger%suffix
326 logger%iter_info => template_logger%iter_info
327 ELSE
328 ! create a file if nothing is specified, one can also get the unit from the default logger
329 ! which should have something reasonable as the argument is required in that case
330 logger%default_global_unit_nr = -1
331 logger%close_global_unit_on_dealloc = .true.
332 logger%local_filename = "localLog"
333 logger%global_filename = "mainLog"
334 logger%print_level = cp_note_level
335 ! generate a file for default local logger
336 ! except the ionode that should write to the default global logger
337 logger%default_local_unit_nr = -1
338 logger%close_local_unit_on_dealloc = .true.
339 logger%suffix = ""
340 END IF
341 IF (PRESENT(para_env)) logger%para_env => para_env
342 IF (.NOT. ASSOCIATED(logger%para_env)) &
343 cpabort(routinep//" para env not associated")
344 IF (.NOT. logger%para_env%is_valid()) &
345 cpabort(routinep//" para_env%ref_count<1")
346 CALL logger%para_env%retain()
347
348 IF (PRESENT(print_level)) logger%print_level = print_level
349
350 IF (PRESENT(default_global_unit_nr)) &
351 logger%default_global_unit_nr = default_global_unit_nr
352 IF (PRESENT(global_filename)) THEN
353 logger%global_filename = global_filename
354 logger%close_global_unit_on_dealloc = .true.
355 logger%default_global_unit_nr = -1
356 END IF
357 IF (PRESENT(close_global_unit_on_dealloc)) THEN
358 logger%close_global_unit_on_dealloc = close_global_unit_on_dealloc
359 IF (PRESENT(default_global_unit_nr) .AND. PRESENT(global_filename) .AND. &
360 (.NOT. close_global_unit_on_dealloc)) THEN
361 logger%default_global_unit_nr = default_global_unit_nr
362 END IF
363 END IF
364
365 IF (PRESENT(default_local_unit_nr)) &
366 logger%default_local_unit_nr = default_local_unit_nr
367 IF (PRESENT(local_filename)) THEN
368 logger%local_filename = local_filename
369 logger%close_local_unit_on_dealloc = .true.
370 logger%default_local_unit_nr = -1
371 END IF
372 IF (PRESENT(suffix)) logger%suffix = suffix
373
374 IF (PRESENT(close_local_unit_on_dealloc)) THEN
375 logger%close_local_unit_on_dealloc = close_local_unit_on_dealloc
376 IF (PRESENT(default_local_unit_nr) .AND. PRESENT(local_filename) .AND. &
377 (.NOT. close_local_unit_on_dealloc)) THEN
378 logger%default_local_unit_nr = default_local_unit_nr
379 END IF
380 END IF
381
382 IF (logger%default_local_unit_nr == -1) THEN
383 IF (logger%para_env%is_source()) THEN
384 logger%default_local_unit_nr = logger%default_global_unit_nr
385 logger%close_local_unit_on_dealloc = .false.
386 END IF
387 END IF
388 IF (PRESENT(iter_info)) logger%iter_info => iter_info
389 IF (ASSOCIATED(logger%iter_info)) THEN
390 CALL cp_iteration_info_retain(logger%iter_info)
391 ELSE
392 CALL cp_iteration_info_create(logger%iter_info, "")
393 END IF
394 END SUBROUTINE cp_logger_create
395
396! **************************************************************************************************
397!> \brief retains the given logger (to be called to keep a shared copy of
398!> the logger)
399!> \param logger the logger to retain
400!> \par History
401!> 08.2002 created [fawzi]
402!> \author Fawzi Mohamed
403! **************************************************************************************************
404 SUBROUTINE cp_logger_retain(logger)
405 TYPE(cp_logger_type), INTENT(INOUT) :: logger
406
407 CHARACTER(len=*), PARAMETER :: routinen = 'cp_logger_retain', &
408 routinep = modulen//':'//routinen
409
410 IF (logger%ref_count < 1) &
411 cpabort(routinep//" logger%ref_count<1")
412 logger%ref_count = logger%ref_count + 1
413 END SUBROUTINE cp_logger_retain
414
415! **************************************************************************************************
416!> \brief releases this logger
417!> \param logger the logger to release
418!> \par History
419!> 4.2002 created [fawzi]
420!> \author Fawzi Mohamed
421! **************************************************************************************************
422 SUBROUTINE cp_logger_release(logger)
423 TYPE(cp_logger_type), POINTER :: logger
424
425 CHARACTER(len=*), PARAMETER :: routinen = 'cp_logger_release', &
426 routinep = modulen//':'//routinen
427
428 IF (ASSOCIATED(logger)) THEN
429 IF (logger%ref_count < 1) &
430 cpabort(routinep//" logger%ref_count<1")
431 logger%ref_count = logger%ref_count - 1
432 IF (logger%ref_count == 0) THEN
433 IF (logger%close_global_unit_on_dealloc .AND. &
434 logger%default_global_unit_nr >= 0) THEN
435 CALL close_file(logger%default_global_unit_nr)
436 logger%close_global_unit_on_dealloc = .false.
437 logger%default_global_unit_nr = -1
438 END IF
439 IF (logger%close_local_unit_on_dealloc .AND. &
440 logger%default_local_unit_nr >= 0) THEN
441 CALL close_file(logger%default_local_unit_nr)
442 logger%close_local_unit_on_dealloc = .false.
443 logger%default_local_unit_nr = -1
444 END IF
445 CALL mp_para_env_release(logger%para_env)
446 CALL cp_iteration_info_release(logger%iter_info)
447 DEALLOCATE (logger)
448 END IF
449 END IF
450 NULLIFY (logger)
451 END SUBROUTINE cp_logger_release
452
453! **************************************************************************************************
454!> \brief this function can be called to check if the logger would log
455!> a message with the given level from the given source
456!> you should use this function if you do direct logging
457!> (without using cp_logger_log), or if you want to know if the generation
458!> of some costly log info is necessary
459!> \param logger the logger you want to log in
460!> \param level describes the of the message: cp_fatal_level(3),
461!> cp_failure_level(2), cp_warning_level(1), cp_note_level(0).
462!> \return ...
463!> \par History
464!> 4.2002 revised [fawzi]
465!> \author Fawzi Mohamed
466! **************************************************************************************************
467 FUNCTION cp_logger_would_log(logger, level) RESULT(res)
468 TYPE(cp_logger_type), POINTER :: logger
469 INTEGER, INTENT(in) :: level
470 LOGICAL :: res
471
472 CHARACTER(len=*), PARAMETER :: routinen = 'cp_logger_would_log', &
473 routinep = modulen//':'//routinen
474
475 TYPE(cp_logger_type), POINTER :: lggr
476
477 lggr => logger
478 IF (.NOT. ASSOCIATED(lggr)) lggr => cp_get_default_logger()
479 IF (lggr%ref_count < 1) &
480 cpabort(routinep//" logger%ref_count<1")
481
482 res = level >= lggr%print_level
483 END FUNCTION cp_logger_would_log
484
485! **************************************************************************************************
486!> \brief returns the unit nr for the requested kind of log.
487!> \param logger the logger you want to log in
488!> \param local if true returns a local logger (one per task), otherwise
489!> returns a global logger (only the process with para_env%mepos==
490!> para_env%source should write to the global logger). Defaults to
491!> false
492!> \return ...
493!> \par History
494!> 4.2002 revised [fawzi]
495!> \author Fawzi Mohamed
496! **************************************************************************************************
497 FUNCTION cp_logger_get_unit_nr(logger, local) RESULT(res)
498 TYPE(cp_logger_type), POINTER :: logger
499 LOGICAL, INTENT(in), OPTIONAL :: local
500 INTEGER :: res
501
502 res = cp_logger_get_default_unit_nr(logger, local=local)
503 END FUNCTION cp_logger_get_unit_nr
504
505! **************************************************************************************************
506!> \brief returns the unit nr for the ionode (-1 on all other processors)
507!> skips as well checks if the procs calling this function is not the ionode
508!> \param logger the logger you want to log in
509!> \return ...
510!> \par History
511!> 12.2009 created [tlaino]
512!> \author Teodoro Laino
513! **************************************************************************************************
514 FUNCTION cp_logger_get_default_io_unit(logger) RESULT(res)
515 TYPE(cp_logger_type), OPTIONAL, POINTER :: logger
516 INTEGER :: res
517
518 TYPE(cp_logger_type), POINTER :: local_logger
519
520 IF (PRESENT(logger)) THEN
521 local_logger => logger
522 ELSE IF (stack_pointer == 0) THEN
523 res = -1 ! edge case: default logger not yet/anymore available
524 RETURN
525 ELSE
526 local_logger => cp_get_default_logger()
527 END IF
528
529 res = cp_logger_get_default_unit_nr(local_logger, local=.false., skip_not_ionode=.true.)
531
532! *************************** cp_logger_type settings ***************************
533
534! **************************************************************************************************
535!> \brief changes the logging level. Log messages with a level less than the one
536!> given wo not be printed.
537!> \param logger the logger to change
538!> \param level the new logging level for the logger
539!> \par History
540!> 4.2002 revised [fawzi]
541!> \author Fawzi Mohamed
542! **************************************************************************************************
543 SUBROUTINE cp_logger_set_log_level(logger, level)
544 TYPE(cp_logger_type), INTENT(INOUT) :: logger
545 INTEGER, INTENT(in) :: level
546
547 CHARACTER(len=*), PARAMETER :: routinen = 'cp_logger_set_log_level', &
548 routinep = modulen//':'//routinen
549
550 IF (logger%ref_count < 1) &
551 cpabort(routinep//" logger%ref_count<1")
552 logger%print_level = level
553 END SUBROUTINE cp_logger_set_log_level
554
555! **************************************************************************************************
556!> \brief asks the default unit number of the given logger.
557!> try to use cp_logger_get_unit_nr
558!> \param logger the logger you want info from
559!> \param local if you want the local unit nr (defaults to false)
560!> \param skip_not_ionode ...
561!> \return ...
562!> \par History
563!> 4.2002 revised [fawzi]
564!> \author Fawzi Mohamed
565! **************************************************************************************************
566 RECURSIVE FUNCTION cp_logger_get_default_unit_nr(logger, local, skip_not_ionode) RESULT(res)
567 TYPE(cp_logger_type), OPTIONAL, POINTER :: logger
568 LOGICAL, INTENT(in), OPTIONAL :: local, skip_not_ionode
569 INTEGER :: res
570
571 CHARACTER(len=*), PARAMETER :: routinen = 'cp_logger_get_default_unit_nr', &
572 routinep = modulen//':'//routinen
573
574 CHARACTER(len=default_path_length) :: filename, host_name
575 INTEGER :: iostat, pid
576 LOGICAL :: loc, skip
577 TYPE(cp_logger_type), POINTER :: lggr
578
579 loc = .true.
580 skip = .false.
581 IF (PRESENT(logger)) THEN
582 lggr => logger
583 ELSE
584 NULLIFY (lggr)
585 END IF
586 IF (.NOT. ASSOCIATED(lggr)) lggr => cp_get_default_logger()
587 IF (lggr%ref_count < 1) &
588 cpabort(routinep//" logger%ref_count<1")
589
590 IF (PRESENT(local)) loc = local
591 IF (PRESENT(skip_not_ionode)) skip = skip_not_ionode
592 IF (.NOT. loc) THEN
593 IF (lggr%default_global_unit_nr <= 0) THEN
594 IF (lggr%para_env%is_source()) THEN
595 CALL cp_logger_generate_filename(lggr, filename, lggr%global_filename, &
596 ".out", local=.false.)
597 CALL open_file(trim(filename), file_status="unknown", &
598 file_action="WRITE", file_position="APPEND", &
599 unit_number=lggr%default_global_unit_nr)
600 ELSE IF (.NOT. skip) THEN
601 lggr%default_global_unit_nr = cp_logger_get_default_unit_nr(lggr, .true.)
602 lggr%close_global_unit_on_dealloc = .false.
603 ELSE
604 lggr%default_global_unit_nr = -1
605 lggr%close_global_unit_on_dealloc = .false.
606 END IF
607 END IF
608 IF (.NOT. (lggr%para_env%is_source() .OR. skip)) THEN
609 WRITE (unit=lggr%default_global_unit_nr, fmt='(/,T2,A)', iostat=iostat) &
610 ' *** WARNING non ionode asked for global logger ***'
611 IF (iostat /= 0) THEN
612 CALL m_getpid(pid)
613 CALL m_hostnm(host_name)
614 print *, " *** Error trying to WRITE to the local logger ***"
615 print *, " *** MPI_id = ", lggr%para_env%mepos
616 print *, " *** MPI_Communicator = ", lggr%para_env%get_handle()
617 print *, " *** PID = ", pid
618 print *, " *** Hostname = "//trim(host_name)
619 CALL print_stack(default_output_unit)
620 ELSE
621 CALL print_stack(lggr%default_global_unit_nr)
622 END IF
623 END IF
624 res = lggr%default_global_unit_nr
625 ELSE
626 IF (lggr%default_local_unit_nr <= 0) THEN
627 CALL cp_logger_generate_filename(lggr, filename, lggr%local_filename, &
628 ".out", local=.true.)
629 CALL open_file(trim(filename), file_status="unknown", &
630 file_action="WRITE", &
631 file_position="APPEND", &
632 unit_number=lggr%default_local_unit_nr)
633 WRITE (unit=lggr%default_local_unit_nr, fmt='(/,T2,A,I0,A,I0,A)', iostat=iostat) &
634 '*** Local logger file of MPI task ', lggr%para_env%mepos, &
635 ' in communicator ', lggr%para_env%get_handle(), ' ***'
636 IF (iostat == 0) THEN
637 CALL m_getpid(pid)
638 CALL m_hostnm(host_name)
639 WRITE (unit=lggr%default_local_unit_nr, fmt='(T2,A,I0)', iostat=iostat) &
640 '*** PID = ', pid, &
641 '*** Hostname = '//host_name
642 CALL print_stack(lggr%default_local_unit_nr)
643 END IF
644 IF (iostat /= 0) THEN
645 CALL m_getpid(pid)
646 CALL m_hostnm(host_name)
647 print *, " *** Error trying to WRITE to the local logger ***"
648 print *, " *** MPI_id = ", lggr%para_env%mepos
649 print *, " *** MPI_Communicator = ", lggr%para_env%get_handle()
650 print *, " *** PID = ", pid
651 print *, " *** Hostname = "//trim(host_name)
652 CALL print_stack(default_output_unit)
653 END IF
654
655 END IF
656 res = lggr%default_local_unit_nr
657 END IF
659
660! **************************************************************************************************
661!> \brief generates a unique filename (ie adding eventual suffixes and
662!> process ids)
663!> \param logger ...
664!> \param res the resulting string
665!> \param root the start of filename
666!> \param postfix the end of the name
667!> \param local if the name should be local to this task (defaults to false)
668!> \par History
669!> 08.2002 created [fawzi]
670!> \author Fawzi Mohamed
671!> \note
672!> this should be a function returning a variable length string.
673!> All spaces are moved to the end of the string.
674!> Not fully optimized: result must be a little longer than the
675!> resulting compressed filename
676! **************************************************************************************************
677 SUBROUTINE cp_logger_generate_filename(logger, res, root, postfix, &
678 local)
679 TYPE(cp_logger_type), POINTER :: logger
680 CHARACTER(len=*), INTENT(inout) :: res
681 CHARACTER(len=*), INTENT(in) :: root, postfix
682 LOGICAL, INTENT(in), OPTIONAL :: local
683
684 CHARACTER(len=*), PARAMETER :: routinen = 'cp_logger_generate_filename', &
685 routinep = modulen//':'//routinen
686
687 LOGICAL :: loc
688 TYPE(cp_logger_type), POINTER :: lggr
689
690 loc = .false.
691 res = ' '
692 lggr => logger
693
694 IF (.NOT. ASSOCIATED(lggr)) lggr => cp_get_default_logger()
695 IF (lggr%ref_count < 1) &
696 cpabort(routinep//" logger%ref_count<1")
697 IF (PRESENT(local)) loc = local
698 IF (loc) THEN
699 res = trim(root)//trim(lggr%suffix)//'_p'// &
700 cp_to_string(lggr%para_env%mepos)//postfix
701 ELSE
702 res = trim(root)//trim(lggr%suffix)//postfix
703 END IF
704 CALL compress(res, full=.true.)
705 END SUBROUTINE cp_logger_generate_filename
706
707! **************************************************************************************************
708!> \brief sets various attributes of the given logger
709!> \param logger the logger you want to change
710!> \param local_filename the root of the name of the file used for local
711!> logging
712!> \param global_filename the root of the name of the file used for
713!> global logging
714!> \author Fawzi Mohamed
715! **************************************************************************************************
716 SUBROUTINE cp_logger_set(logger, local_filename, global_filename)
717 TYPE(cp_logger_type), INTENT(INOUT) :: logger
718 CHARACTER(len=*), INTENT(in), OPTIONAL :: local_filename, global_filename
719
720 IF (PRESENT(local_filename)) logger%local_filename = local_filename
721 IF (PRESENT(global_filename)) logger%global_filename = global_filename
722 END SUBROUTINE cp_logger_set
723
724! **************************************************************************************************
725!> \brief converts an int to a string
726!> (should be a variable length string, but that does not work with
727!> all the compilers)
728!> \param i the integer to convert
729!> \param fmt Optional format string
730!> \return ...
731!> \par History
732!> 4.2002 revised [fawzi]
733!> \author Fawzi Mohamed, MK
734! **************************************************************************************************
735 FUNCTION cp_int_to_string(i, fmt) RESULT(res)
736 INTEGER, INTENT(in) :: i
737 CHARACTER(len=*), OPTIONAL :: fmt
738 CHARACTER(len=25) :: res
739
740 CHARACTER(len=25) :: t_res
741 INTEGER :: iostat
742 REAL(kind=dp) :: tmp_r
743
744 iostat = 0
745 IF (PRESENT(fmt)) THEN
746 WRITE (t_res, fmt=fmt, iostat=iostat) i
747 ELSE IF (i > 999999 .OR. i < -99999) THEN
748 tmp_r = i
749 WRITE (t_res, fmt='(ES8.1)', iostat=iostat) tmp_r
750 ELSE
751 WRITE (t_res, fmt='(I6)', iostat=iostat) i
752 END IF
753 res = t_res
754 IF (iostat /= 0) THEN
755 print *, "cp_int_to_string I/O error", iostat
756 CALL print_stack(cp_logger_get_default_unit_nr())
757 END IF
758
759 END FUNCTION cp_int_to_string
760
761! **************************************************************************************************
762!> \brief Convert a double precision real in a string
763!> (should be a variable length string, but that does not work with
764!> all the compilers)
765!> \param val the number to convert
766!> \param fmt Optional format string
767!> \return ...
768!> \par History
769!> 4.2002 revised [fawzi]
770!> \author Fawzi Mohamed, MK
771! **************************************************************************************************
772 FUNCTION cp_real_dp_to_string(val, fmt) RESULT(res)
773 REAL(kind=dp), INTENT(in) :: val
774 CHARACTER(len=*), OPTIONAL :: fmt
775 CHARACTER(len=25) :: res
776
777 INTEGER :: iostat
778
779 IF (PRESENT(fmt)) THEN
780 WRITE (res, fmt=fmt, iostat=iostat) val
781 ELSE
782 WRITE (res, fmt='(ES11.4)', iostat=iostat) val
783 END IF
784 IF (iostat /= 0) THEN
785 print *, "cp_real_dp_to_string I/O error", iostat
786 CALL print_stack(cp_logger_get_default_unit_nr())
787 END IF
788
789 END FUNCTION cp_real_dp_to_string
790
791! **************************************************************************************************
792!> \brief convert a logical in a string ('T' or 'F')
793!> \param val the number to convert
794!> \return ...
795!> \author fawzi
796! **************************************************************************************************
797 ELEMENTAL FUNCTION cp_logical_to_string(val) RESULT(res)
798 LOGICAL, INTENT(in) :: val
799 CHARACTER(len=1) :: res
800
801 IF (val) THEN
802 res = 'T'
803 ELSE
804 res = 'F'
805 END IF
806 END FUNCTION cp_logical_to_string
807
808END MODULE cp_log_handling
809
Utility routines to open and close files. Tracking of preconnections.
Definition cp_files.F:16
subroutine, public open_file(file_name, file_status, file_form, file_action, file_position, file_pad, unit_number, debug, skip_get_unit_number, file_access)
Opens the requested file using a free unit number.
Definition cp_files.F:308
subroutine, public close_file(unit_number, file_status, keep_preconnection)
Close an open file given by its logical unit number. Optionally, keep the file and unit preconnected.
Definition cp_files.F:119
Collection of routines to handle the iteration info.
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:555
integer, parameter, public default_output_unit
Definition machine.F:45
subroutine, public m_hostnm(hname)
...
Definition machine.F:474
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:432
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