Neko 1.99.3
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
log.f90
Go to the documentation of this file.
1! Copyright (c) 2021-2024, The Neko Authors
2! All rights reserved.
3!
4! Redistribution and use in source and binary forms, with or without
5! modification, are permitted provided that the following conditions
6! are met:
7!
8! * Redistributions of source code must retain the above copyright
9! notice, this list of conditions and the following disclaimer.
10!
11! * Redistributions in binary form must reproduce the above
12! copyright notice, this list of conditions and the following
13! disclaimer in the documentation and/or other materials provided
14! with the distribution.
15!
16! * Neither the name of the authors nor the names of its
17! contributors may be used to endorse or promote products derived
18! from this software without specific prior written permission.
19!
20! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21! "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22! LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23! FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24! COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25! INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26! BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27! LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28! CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29! LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30! ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31! POSSIBILITY OF SUCH DAMAGE.
32!
34module logger
35 use comm, only : pe_rank
36 use utils, only : neko_error
37 use, intrinsic :: iso_fortran_env, only : stdout => output_unit, &
38 stderr => error_unit
39 implicit none
40 private
41
42 ! > Size of the log message buffer
43 !! @note This adjust for the leading space applied by `write`. 80 character
44 !! output log leaves 79 characters for the message.
45 integer, public, parameter :: log_size = 79
46
48 integer, public, parameter :: sec_head_size = 30
49
50 type, public :: log_t
51 integer, private :: indent_
52 integer, private :: section_id_
53 integer, private :: tab_size_
54 integer, private :: level_
55 integer, private :: unit_
56
57 character(len=LOG_SIZE), private :: section_header = ""
58
59 contains
60 procedure, pass(this) :: init => log_init
61 procedure, pass(this) :: free => log_free
62 procedure, pass(this) :: begin => log_begin
63 procedure, pass(this) :: end => log_end
64 procedure, pass(this) :: indent => log_indent
65 procedure, pass(this) :: newline => log_newline
66 procedure, pass(this) :: message => log_message
67 procedure, pass(this) :: section => log_section
68 procedure, pass(this) :: header => log_header
69 procedure, pass(this) :: error => log_error
70 procedure, pass(this) :: warning => log_warning
71 procedure, pass(this) :: deprecated => log_deprecated
72 procedure, pass(this) :: end_section => log_end_section
73
74 procedure, private, pass(this) :: print_section_header => &
76 end type log_t
77
79 type(log_t), public :: neko_log
81 integer, public, parameter :: neko_log_quiet = 0
83 integer, public, parameter :: neko_log_info = 1
85 integer, public, parameter :: neko_log_verbose = 2
87 integer, public, parameter :: neko_log_deprecation_error = 5
89 integer, public, parameter :: neko_log_debug = 10
90
92 character(len=50), dimension(:), allocatable :: deprecated_list
93
94contains
95
97 subroutine log_init(this)
98 class(log_t), intent(inout) :: this
99 character(len=255) :: log_level
100 character(len=255) :: log_tab_size
101 character(len=255) :: log_file
102 integer :: envvar_len
103
104 this%indent_ = 0
105 this%section_id_ = 0
106
107 call get_environment_variable("NEKO_LOG_TAB_SIZE", log_tab_size, envvar_len)
108 if (envvar_len .gt. 0) then
109 read(log_tab_size(1:envvar_len), *) this%tab_size_
110 else
111 this%tab_size_ = 1
112 end if
113
114 call get_environment_variable("NEKO_LOG_LEVEL", log_level, envvar_len)
115 if (envvar_len .gt. 0) then
116 read(log_level(1:envvar_len), *) this%level_
117 else
118 this%level_ = neko_log_info
119 end if
120
121 call get_environment_variable("NEKO_LOG_FILE", log_file, envvar_len)
122 if (envvar_len .gt. 0) then
123 open(newunit = this%unit_, file = trim(log_file), status = 'replace', &
124 action = 'write')
125 else
126 this%unit_ = stdout
127 end if
128
129 end subroutine log_init
130
132 subroutine log_free(this)
133 class(log_t), intent(inout) :: this
134
135 if (this%section_id_ .ne. 0) then
136 call neko_error("Log is unbalanced")
137 end if
138
139 if (this%unit_ .ne. stdout) then
140 close(this%unit_)
141 end if
142
143 this%indent_ = 0
144 this%level_ = neko_log_info
145 this%unit_ = -1
146
147 if (allocated(deprecated_list)) then
148 deallocate(deprecated_list)
149 end if
150
151 end subroutine log_free
152
154 subroutine log_begin(this)
155 class(log_t), intent(inout) :: this
156
157 if (pe_rank .eq. 0) then
158 this%section_id_ = this%section_id_ + 1
159 this%indent_ = this%indent_ + this%tab_size_
160 end if
161
162 end subroutine log_begin
163
165 subroutine log_end(this)
166 class(log_t), intent(inout) :: this
167
168 if (pe_rank .eq. 0) then
169 if (this%section_id_ .eq. 0) then
170 call neko_error("Log is unbalanced")
171 end if
172 this%section_id_ = this%section_id_ - 1
173 this%indent_ = this%indent_ - this%tab_size_
174 end if
175
176 this%section_header = ""
177
178 end subroutine log_end
179
181 subroutine log_indent(this)
182 class(log_t), intent(in) :: this
183
184 if (pe_rank .eq. 0) then
185 write(this%unit_, '(A)', advance = 'no') repeat(' ', this%indent_)
186 end if
187
188 end subroutine log_indent
189
191 subroutine log_newline(this, lvl)
192 class(log_t), intent(in) :: this
193 integer, optional :: lvl
194
195 integer :: lvl_
196
197 if (present(lvl)) then
198 lvl_ = lvl
199 else
200 lvl_ = neko_log_info
201 end if
202
203 if (lvl_ .gt. this%level_) then
204 return
205 end if
206
207 if (pe_rank .eq. 0) then
208 write(this%unit_, '(A)') ''
209 end if
210
211 end subroutine log_newline
212
214 subroutine log_message(this, msg, lvl)
215 class(log_t), intent(inout) :: this
216 character(len=*), intent(in) :: msg
217 integer, optional :: lvl
218 integer :: lvl_
219
220 if (present(lvl)) then
221 lvl_ = lvl
222 else
223 lvl_ = neko_log_info
224 end if
225
226 if (lvl_ .gt. this%level_) then
227 return
228 end if
229
230 if (len_trim(this%section_header) .gt. 0) then
231 call this%print_section_header(lvl)
232 end if
233
234 if (pe_rank .eq. 0) then
235 call this%indent()
236 write(this%unit_, '(A)') trim(msg)
237 end if
238
239 end subroutine log_message
240
242 subroutine log_header(this, version, build_info)
243 class(log_t), intent(in) :: this
244 character(len=*), intent(in) :: version
245 character(len=*), intent(in) :: build_info
246
247 if (pe_rank .eq. 0) then
248 write(this%unit_, '(A)') ''
249 write(this%unit_, '(1X,A)') ' _ __ ____ __ __ ____ '
250 write(this%unit_, '(1X,A)') ' / |/ / / __/ / //_/ / __ \ '
251 write(this%unit_, '(1X,A)') ' / / / _/ / ,< / /_/ / '
252 write(this%unit_, '(1X,A)') '/_/|_/ /___/ /_/|_| \____/ '
253 write(this%unit_, '(A)') ''
254 write(this%unit_, '(1X,A,A,A)') '(version: ', trim(version), ')'
255 write(this%unit_, '(1X,A)') trim(build_info)
256 write(this%unit_, '(A)') ''
257 end if
258
259 end subroutine log_header
260
262 subroutine log_error(this, msg)
263 class(log_t), intent(in) :: this
264 character(len=*), intent(in) :: msg
265
266 if (pe_rank .eq. 0) then
267 call this%indent()
268 write(stderr, '(A,A,A)') '*** ERROR: ', trim(msg), ' ***'
269 end if
270
271 end subroutine log_error
272
274 subroutine log_warning(this, msg)
275 class(log_t), intent(in) :: this
276 character(len=*), intent(in) :: msg
277
278 if (pe_rank .eq. 0) then
279 call this%indent()
280 write(this%unit_, '(A,A,A)') '*** WARNING: ', trim(msg), ' ***'
281 end if
282
283 end subroutine log_warning
284
289 subroutine log_deprecated(this, feature, removal_version, extra_info)
290 class(log_t), intent(inout) :: this
291 character(len=*), intent(in) :: feature
292 character(len=*), intent(in), optional :: removal_version
293 character(len=*), intent(in), optional :: extra_info
294 character(len=LOG_SIZE) :: msg
295 character(len=50), dimension(:), allocatable :: deprecated_list_local
296 integer :: i
297
298 if (this%level_ .lt. neko_log_quiet) return
299
300 if (.not. allocated(deprecated_list)) then
301 allocate(character(len=50) :: deprecated_list(1))
302 deprecated_list = trim(feature)
303 else
304 ! Check that the feature have not already been logged
305 do i = 1, size(deprecated_list)
306 if (trim(deprecated_list(i)) .eq. trim(feature)) return
307 end do
308
309 ! Save the feature to the list of deprecated features
310 call move_alloc(deprecated_list, deprecated_list_local)
311 allocate(character(len=50)::deprecated_list(size(deprecated_list_local)+1))
312 deprecated_list(1:size(deprecated_list_local)) = deprecated_list_local
313 deprecated_list(size(deprecated_list_local) + 1) = trim(feature)
314 deallocate(deprecated_list_local)
315 end if
316
317 ! Construct deprecation message
318 write(msg, '(A,A)') '*** DEPRECATION: ', trim(feature)
319 call this%message(msg)
320 write(msg, '(A,A,A)') 'The feature "', trim(feature), &
321 '" is deprecated.'
322 call this%message(msg)
323
324 if (present(removal_version)) then
325 write(msg, '(A,A,A)') 'It will be removed in version ', &
326 trim(removal_version), '.'
327 call this%message(msg)
328 end if
329
330 if (present(extra_info)) then
331 call this%message(extra_info)
332 end if
333
334 call this%message('***')
335
336 if (this%level_ .ge. neko_log_deprecation_error) then
337 call neko_error('Deprecated feature used: ' // trim(feature))
338 end if
339
340 end subroutine log_deprecated
341
343 subroutine log_section(this, msg, lvl)
344 class(log_t), intent(inout) :: this
345 character(len=*), intent(in) :: msg
346 integer, optional :: lvl
347
348 integer :: pre, pos
349
350 if (len_trim(this%section_header) .gt. 0) then
351 call this%print_section_header(lvl)
352 end if
353
354 call this%begin()
355
356 if (pe_rank .eq. 0) then
357 pre = (30 - len_trim(msg)) / 2
358 pos = 30 - (len_trim(msg) + pre)
359
360 if (pre .lt. 0 .or. pos .lt. 0) then
361 pre = 1
362 pos = 1
363 write(this%section_header, '(A,A,A)') &
364 repeat('-', pre), trim(msg(1: sec_head_size - 2)), &
365 repeat('-', pos)
366 else
367 write(this%section_header, '(A,A,A)') &
368 repeat('-', pre), trim(msg), repeat('-', pos)
369 end if
370 end if
371
372 end subroutine log_section
373
375 subroutine log_print_section_header(this, lvl)
376 class(log_t), intent(inout) :: this
377 integer, optional :: lvl
378 integer :: lvl_
379
380 if (present(lvl)) then
381 lvl_ = lvl
382 else
383 lvl_ = neko_log_info
384 end if
385
386 if (lvl_ .gt. this%level_) then
387 return
388 end if
389
390 if (pe_rank .eq. 0) then
391 call this%newline(lvl)
392 call this%indent()
393 write(this%unit_, '(A)') trim(this%section_header)
394 this%section_header = ""
395 end if
396
397 end subroutine log_print_section_header
398
400 subroutine log_end_section(this, msg, lvl)
401 class(log_t), intent(inout) :: this
402 character(len=*), intent(in), optional :: msg
403 integer, optional :: lvl
404
405 if (present(msg)) then
406 call this%message(msg, lvl)
407 end if
408
409 call this%end()
410
411 end subroutine log_end_section
412
413 !
414 ! Rudimentary C interface
415 !
416
419 subroutine log_message_c(c_msg) bind(c, name = 'log_message')
420 use, intrinsic :: iso_c_binding
421 character(kind=c_char), dimension(*), intent(in) :: c_msg
422 character(len=LOG_SIZE) :: msg
423 integer :: len
424
425 if (pe_rank .eq. 0) then
426 len = 0
427 do
428 if (c_msg(len+1) .eq. c_null_char) exit
429 len = len + 1
430 msg(len:len) = c_msg(len)
431 end do
432
433 call neko_log%message(trim(msg(1:len)))
434 end if
435
436 end subroutine log_message_c
437
440 subroutine log_error_c(c_msg) bind(c, name = "log_error")
441 use, intrinsic :: iso_c_binding
442 character(kind=c_char), dimension(*), intent(in) :: c_msg
443 character(len=LOG_SIZE) :: msg
444 integer :: len
445
446 if (pe_rank .eq. 0) then
447 len = 0
448 do
449 if (c_msg(len+1) .eq. c_null_char) exit
450 len = len + 1
451 msg(len:len) = c_msg(len)
452 end do
453
454 call neko_log%indent()
455 write(stderr, '(A,A,A)') '*** ERROR: ', trim(msg(1:len)), ' ***'
456 end if
457
458 end subroutine log_error_c
459
462 subroutine log_warning_c(c_msg) bind(c, name = "log_warning")
463 use, intrinsic :: iso_c_binding
464 character(kind=c_char), dimension(*), intent(in) :: c_msg
465 character(len=LOG_SIZE) :: msg
466 integer :: len
467
468 if (pe_rank .eq. 0) then
469 len = 0
470 do
471 if (c_msg(len+1) .eq. c_null_char) exit
472 len = len + 1
473 msg(len:len) = c_msg(len)
474 end do
475
476 call neko_log%indent()
477 write(neko_log%unit_, '(A,A,A)') &
478 '*** WARNING: ', trim(msg(1:len)), ' ***'
479 end if
480
481 end subroutine log_warning_c
482
485 subroutine log_section_c(c_msg) bind(c, name = "log_section")
486 use, intrinsic :: iso_c_binding
487 character(kind=c_char), dimension(*), intent(in) :: c_msg
488 character(len=LOG_SIZE) :: msg
489 integer :: len
490
491 if (pe_rank .eq. 0) then
492 len = 0
493 do
494 if (c_msg(len+1) .eq. c_null_char) exit
495 len = len + 1
496 msg(len:len) = c_msg(len)
497 end do
498
499 call neko_log%section(trim(msg(1:len)))
500 end if
501
502 end subroutine log_section_c
503
506 subroutine log_end_section_c() bind(c, name = "log_end_section")
507
508 call neko_log%end_section()
509
510 end subroutine log_end_section_c
511
512end module logger
Definition comm.F90:1
integer, public pe_rank
MPI rank.
Definition comm.F90:56
Module for file I/O operations.
Definition file.f90:34
Logging routines.
Definition log.f90:34
subroutine log_end_section_c()
End a log section (from C)
Definition log.f90:507
subroutine log_end(this)
Decrease indention level.
Definition log.f90:166
subroutine log_print_section_header(this, lvl)
Print a section header.
Definition log.f90:376
subroutine log_deprecated(this, feature, removal_version, extra_info)
Write a deprecation warning to a log.
Definition log.f90:290
subroutine log_header(this, version, build_info)
Write the Neko header to a log.
Definition log.f90:243
integer, parameter, public neko_log_verbose
Verbose log level.
Definition log.f90:85
subroutine log_message(this, msg, lvl)
Write a message to a log.
Definition log.f90:215
integer, parameter, public neko_log_quiet
Always logged.
Definition log.f90:81
subroutine log_begin(this)
Increase indention level.
Definition log.f90:155
subroutine log_message_c(c_msg)
Write a message to a log (from C)
Definition log.f90:420
subroutine log_end_section(this, msg, lvl)
End a log section.
Definition log.f90:401
subroutine log_init(this)
Initialize a log.
Definition log.f90:98
subroutine log_warning(this, msg)
Write a warning message to a log.
Definition log.f90:275
character(len=50), dimension(:), allocatable deprecated_list
List of already logged deprecated features.
Definition log.f90:92
subroutine log_error_c(c_msg)
Write an error message to a log (from C)
Definition log.f90:441
subroutine log_indent(this)
Indent a log.
Definition log.f90:182
subroutine log_warning_c(c_msg)
Write a warning message to a log (from C)
Definition log.f90:463
subroutine log_newline(this, lvl)
Write a new line to a log.
Definition log.f90:192
integer, parameter, public sec_head_size
Length of the section header.
Definition log.f90:48
integer, parameter, public neko_log_deprecation_error
Deprecation error level.
Definition log.f90:87
subroutine log_section_c(c_msg)
Begin a new log section (from C)
Definition log.f90:486
integer, parameter, public neko_log_debug
Debug log level.
Definition log.f90:89
type(log_t), public neko_log
Global log stream.
Definition log.f90:79
integer, parameter, public log_size
Definition log.f90:45
integer, parameter, public neko_log_info
Default log level.
Definition log.f90:83
subroutine log_free(this)
Free a log.
Definition log.f90:133
subroutine log_section(this, msg, lvl)
Begin a new log section.
Definition log.f90:344
subroutine log_error(this, msg)
Write an error message to a log.
Definition log.f90:263
Utilities.
Definition utils.f90:35