Neko 1.99.2
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 num_types, only : rp
37 use utils, only: neko_error
38 use, intrinsic :: iso_fortran_env, only: stdout => output_unit, &
39 stderr => error_unit
40 implicit none
41 private
42
43 ! > Size of the log message buffer
44 !! @note This adjust for the leading space applied by `write`. 80 character
45 !! output log leaves 79 characters for the message.
46 integer, public, parameter :: log_size = 79
47
48 type, public :: log_t
49 integer, private :: indent_
50 integer, private :: section_id_
51 integer, private :: tab_size_
52 integer, private :: level_
53 integer, private :: unit_
54
55 character(len=LOG_SIZE), private :: section_header = ""
56
57 contains
58 procedure, pass(this) :: init => log_init
59 procedure, pass(this) :: free => log_free
60 procedure, pass(this) :: begin => log_begin
61 procedure, pass(this) :: end => log_end
62 procedure, pass(this) :: indent => log_indent
63 procedure, pass(this) :: newline => log_newline
64 procedure, pass(this) :: message => log_message
65 procedure, pass(this) :: section => log_section
66 procedure, pass(this) :: header => log_header
67 procedure, pass(this) :: error => log_error
68 procedure, pass(this) :: warning => log_warning
69 procedure, pass(this) :: end_section => log_end_section
70
71 procedure, private, pass(this) :: print_section_header => &
73 end type log_t
74
76 type(log_t), public :: neko_log
78 integer, public, parameter :: neko_log_quiet = 0
80 integer, public, parameter :: neko_log_info = 1
82 integer, public, parameter :: neko_log_verbose = 2
84 integer, public, parameter :: neko_log_debug = 10
85
86contains
87
89 subroutine log_init(this)
90 class(log_t), intent(inout) :: this
91 character(len=255) :: log_level
92 character(len=255) :: log_tab_size
93 character(len=255) :: log_file
94 integer :: envvar_len
95
96 this%indent_ = 0
97 this%section_id_ = 0
98
99 call get_environment_variable("NEKO_LOG_TAB_SIZE", log_tab_size, envvar_len)
100 if (envvar_len .gt. 0) then
101 read(log_tab_size(1:envvar_len), *) this%tab_size_
102 else
103 this%tab_size_ = 1
104 end if
105
106 call get_environment_variable("NEKO_LOG_LEVEL", log_level, envvar_len)
107 if (envvar_len .gt. 0) then
108 read(log_level(1:envvar_len), *) this%level_
109 else
110 this%level_ = neko_log_info
111 end if
112
113 call get_environment_variable("NEKO_LOG_FILE", log_file, envvar_len)
114 if (envvar_len .gt. 0) then
115 open(newunit = this%unit_, file = trim(log_file), status = 'replace', &
116 action = 'write')
117 else
118 this%unit_ = stdout
119 end if
120
121 end subroutine log_init
122
124 subroutine log_free(this)
125 class(log_t), intent(inout) :: this
126
127 if (this%section_id_ .ne. 0) then
128 call neko_error("Log is unbalanced")
129 end if
130
131 if (this%unit_ .ne. stdout) then
132 close(this%unit_)
133 end if
134
135 this%indent_ = 0
136 this%level_ = neko_log_info
137 this%unit_ = -1
138
139 end subroutine log_free
140
142 subroutine log_begin(this)
143 class(log_t), intent(inout) :: this
144
145 if (pe_rank .eq. 0) then
146 this%section_id_ = this%section_id_ + 1
147 this%indent_ = this%indent_ + this%tab_size_
148 end if
149
150 end subroutine log_begin
151
153 subroutine log_end(this)
154 class(log_t), intent(inout) :: this
155
156 if (pe_rank .eq. 0) then
157 if (this%section_id_ .eq. 0) then
158 call neko_error("Log is unbalanced")
159 end if
160 this%section_id_ = this%section_id_ - 1
161 this%indent_ = this%indent_ - this%tab_size_
162 end if
163
164 this%section_header = ""
165
166 end subroutine log_end
167
169 subroutine log_indent(this)
170 class(log_t), intent(in) :: this
171
172 if (pe_rank .eq. 0) then
173 write(this%unit_, '(A)', advance = 'no') repeat(' ', this%indent_)
174 end if
175
176 end subroutine log_indent
177
179 subroutine log_newline(this, lvl)
180 class(log_t), intent(in) :: this
181 integer, optional :: lvl
182
183 integer :: lvl_
184
185 if (present(lvl)) then
186 lvl_ = lvl
187 else
188 lvl_ = neko_log_info
189 end if
190
191 if (lvl_ .gt. this%level_) then
192 return
193 end if
194
195 if (pe_rank .eq. 0) then
196 write(this%unit_, '(A)') ''
197 end if
198
199 end subroutine log_newline
200
202 subroutine log_message(this, msg, lvl)
203 class(log_t), intent(inout) :: this
204 character(len=*), intent(in) :: msg
205 integer, optional :: lvl
206 integer :: lvl_
207
208 if (present(lvl)) then
209 lvl_ = lvl
210 else
211 lvl_ = neko_log_info
212 end if
213
214 if (lvl_ .gt. this%level_) then
215 return
216 end if
217
218 if (len_trim(this%section_header) .gt. 0) then
219 call this%print_section_header(lvl)
220 end if
221
222 if (pe_rank .eq. 0) then
223 call this%indent()
224 write(this%unit_, '(A)') trim(msg)
225 end if
226
227 end subroutine log_message
228
230 subroutine log_header(this, version, build_info)
231 class(log_t), intent(in) :: this
232 character(len=*), intent(in) :: version
233 character(len=*), intent(in) :: build_info
234
235 if (pe_rank .eq. 0) then
236 write(this%unit_, '(A)') ''
237 write(this%unit_, '(1X,A)') ' _ __ ____ __ __ ____ '
238 write(this%unit_, '(1X,A)') ' / |/ / / __/ / //_/ / __ \ '
239 write(this%unit_, '(1X,A)') ' / / / _/ / ,< / /_/ / '
240 write(this%unit_, '(1X,A)') '/_/|_/ /___/ /_/|_| \____/ '
241 write(this%unit_, '(A)') ''
242 write(this%unit_, '(1X,A,A,A)') '(version: ', trim(version), ')'
243 write(this%unit_, '(1X,A)') trim(build_info)
244 write(this%unit_, '(A)') ''
245 end if
246
247 end subroutine log_header
248
250 subroutine log_error(this, msg)
251 class(log_t), intent(in) :: this
252 character(len=*), intent(in) :: msg
253
254 if (pe_rank .eq. 0) then
255 call this%indent()
256 write(stderr, '(A,A,A)') '*** ERROR: ', trim(msg), ' ***'
257 end if
258
259 end subroutine log_error
260
262 subroutine log_warning(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(this%unit_, '(A,A,A)') '*** WARNING: ', trim(msg), ' ***'
269 end if
270
271 end subroutine log_warning
272
274 subroutine log_section(this, msg, lvl)
275 class(log_t), intent(inout) :: this
276 character(len=*), intent(in) :: msg
277 integer, optional :: lvl
278
279 integer :: pre, pos
280
281 if (len_trim(this%section_header) .gt. 0) then
282 call this%print_section_header(lvl)
283 end if
284
285 call this%begin()
286
287 if (pe_rank .eq. 0) then
288 pre = (30 - len_trim(msg)) / 2
289 pos = 30 - (len_trim(msg) + pre)
290
291 write(this%section_header, '(A,A,A)') &
292 repeat('-', pre), trim(msg), repeat('-', pos)
293 end if
294
295 end subroutine log_section
296
298 subroutine log_print_section_header(this, lvl)
299 class(log_t), intent(inout) :: this
300 integer, optional :: lvl
301 integer :: lvl_
302
303 if (present(lvl)) then
304 lvl_ = lvl
305 else
306 lvl_ = neko_log_info
307 end if
308
309 if (lvl_ .gt. this%level_) then
310 return
311 end if
312
313 if (pe_rank .eq. 0) then
314 call this%newline(lvl)
315 call this%indent()
316 write(this%unit_, '(A)') trim(this%section_header)
317 this%section_header = ""
318 end if
319
320 end subroutine log_print_section_header
321
323 subroutine log_end_section(this, msg, lvl)
324 class(log_t), intent(inout) :: this
325 character(len=*), intent(in), optional :: msg
326 integer, optional :: lvl
327 integer :: lvl_
328
329 if (present(msg)) then
330 call this%message(msg, lvl)
331 end if
332
333 call this%end()
334
335 end subroutine log_end_section
336
337 !
338 ! Rudimentary C interface
339 !
340
343 subroutine log_message_c(c_msg) bind(c, name = 'log_message')
344 use, intrinsic :: iso_c_binding
345 character(kind=c_char), dimension(*), intent(in) :: c_msg
346 character(len=LOG_SIZE) :: msg
347 integer :: len
348
349 if (pe_rank .eq. 0) then
350 len = 0
351 do
352 if (c_msg(len+1) .eq. c_null_char) exit
353 len = len + 1
354 msg(len:len) = c_msg(len)
355 end do
356
357 call neko_log%message(trim(msg(1:len)))
358 end if
359
360 end subroutine log_message_c
361
364 subroutine log_error_c(c_msg) bind(c, name = "log_error")
365 use, intrinsic :: iso_c_binding
366 character(kind=c_char), dimension(*), intent(in) :: c_msg
367 character(len=LOG_SIZE) :: msg
368 integer :: len
369
370 if (pe_rank .eq. 0) then
371 len = 0
372 do
373 if (c_msg(len+1) .eq. c_null_char) exit
374 len = len + 1
375 msg(len:len) = c_msg(len)
376 end do
377
378 call neko_log%indent()
379 write(stderr, '(A,A,A)') '*** ERROR: ', trim(msg(1:len)), ' ***'
380 end if
381
382 end subroutine log_error_c
383
386 subroutine log_warning_c(c_msg) bind(c, name = "log_warning")
387 use, intrinsic :: iso_c_binding
388 character(kind=c_char), dimension(*), intent(in) :: c_msg
389 character(len=LOG_SIZE) :: msg
390 integer :: len
391
392 if (pe_rank .eq. 0) then
393 len = 0
394 do
395 if (c_msg(len+1) .eq. c_null_char) exit
396 len = len + 1
397 msg(len:len) = c_msg(len)
398 end do
399
400 call neko_log%indent()
401 write(neko_log%unit_, '(A,A,A)') &
402 '*** WARNING: ', trim(msg(1:len)), ' ***'
403 end if
404
405 end subroutine log_warning_c
406
409 subroutine log_section_c(c_msg) bind(c, name = "log_section")
410 use, intrinsic :: iso_c_binding
411 character(kind=c_char), dimension(*), intent(in) :: c_msg
412 character(len=LOG_SIZE) :: msg
413 integer :: len
414
415 if (pe_rank .eq. 0) then
416 len = 0
417 do
418 if (c_msg(len+1) .eq. c_null_char) exit
419 len = len + 1
420 msg(len:len) = c_msg(len)
421 end do
422
423 call neko_log%section(trim(msg(1:len)))
424 end if
425
426 end subroutine log_section_c
427
430 subroutine log_end_section_c() bind(c, name = "log_end_section")
431
432 call neko_log%end_section()
433
434 end subroutine log_end_section_c
435
436end 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:431
subroutine log_end(this)
Decrease indention level.
Definition log.f90:154
subroutine log_print_section_header(this, lvl)
Print a section header.
Definition log.f90:299
subroutine log_header(this, version, build_info)
Write the Neko header to a log.
Definition log.f90:231
integer, parameter, public neko_log_verbose
Verbose log level.
Definition log.f90:82
subroutine log_message(this, msg, lvl)
Write a message to a log.
Definition log.f90:203
integer, parameter, public neko_log_quiet
Always logged.
Definition log.f90:78
subroutine log_begin(this)
Increase indention level.
Definition log.f90:143
subroutine log_message_c(c_msg)
Write a message to a log (from C)
Definition log.f90:344
subroutine log_end_section(this, msg, lvl)
End a log section.
Definition log.f90:324
subroutine log_init(this)
Initialize a log.
Definition log.f90:90
subroutine log_warning(this, msg)
Write a warning message to a log.
Definition log.f90:263
subroutine log_error_c(c_msg)
Write an error message to a log (from C)
Definition log.f90:365
subroutine log_indent(this)
Indent a log.
Definition log.f90:170
subroutine log_warning_c(c_msg)
Write a warning message to a log (from C)
Definition log.f90:387
subroutine log_newline(this, lvl)
Write a new line to a log.
Definition log.f90:180
subroutine log_section_c(c_msg)
Begin a new log section (from C)
Definition log.f90:410
integer, parameter, public neko_log_debug
Debug log level.
Definition log.f90:84
type(log_t), public neko_log
Global log stream.
Definition log.f90:76
integer, parameter, public log_size
Definition log.f90:46
integer, parameter, public neko_log_info
Default log level.
Definition log.f90:80
subroutine log_free(this)
Free a log.
Definition log.f90:125
subroutine log_section(this, msg, lvl)
Begin a new log section.
Definition log.f90:275
subroutine log_error(this, msg)
Write an error message to a log.
Definition log.f90:251
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:12
Utilities.
Definition utils.f90:35