Loading [MathJax]/extensions/tex2jax.js
Neko 0.9.1
A portable framework for high-order spectral element flow simulations
All Classes Namespaces Files Functions Variables Typedefs Enumerator Macros Pages
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, intrinsic :: iso_fortran_env, only: stdout => output_unit, &
38 stderr => error_unit
39 implicit none
40 private
41
42 integer, public, parameter :: log_size = 80
43
44 type, public :: log_t
45 integer :: indent_
46 integer :: section_id_
47 integer :: level_
48 integer :: unit_
49 contains
50 procedure, pass(this) :: init => log_init
51 procedure, pass(this) :: begin => log_begin
52 procedure, pass(this) :: end => log_end
53 procedure, pass(this) :: indent => log_indent
54 procedure, pass(this) :: newline => log_newline
55 procedure, pass(this) :: message => log_message
56 procedure, pass(this) :: section => log_section
57 procedure, pass(this) :: status => log_status
58 procedure, pass(this) :: header => log_header
59 procedure, pass(this) :: error => log_error
60 procedure, pass(this) :: warning => log_warning
61 procedure, pass(this) :: end_section => log_end_section
62 end type log_t
63
65 type(log_t), public :: neko_log
67 integer, public, parameter :: neko_log_quiet = 0
69 integer, public, parameter :: neko_log_info = 1
71 integer, public, parameter :: neko_log_verbose = 2
73 integer, public, parameter :: neko_log_debug = 10
74
75contains
76
78 subroutine log_init(this)
79 class(log_t), intent(inout) :: this
80 character(len=255) :: log_level
81 character(len=255) :: log_file
82 integer :: envvar_len
83
84 this%indent_ = 1
85 this%section_id_ = 0
86
87 call get_environment_variable("NEKO_LOG_LEVEL", log_level, envvar_len)
88 if (envvar_len .gt. 0) then
89 read(log_level(1:envvar_len), *) this%level_
90 else
91 this%level_ = neko_log_info
92 end if
93
94 call get_environment_variable("NEKO_LOG_FILE", log_file, envvar_len)
95 if (envvar_len .gt. 0) then
96 this%unit_ = 69
97 open(unit = this%unit_, file = trim(log_file), status = 'replace', &
98 action = 'write')
99 else
100 this%unit_ = stdout
101 end if
102
103 end subroutine log_init
104
106 subroutine log_begin(this)
107 class(log_t), intent(inout) :: this
108
109 if (pe_rank .eq. 0) then
110 this%indent_ = this%indent_ + 1
111 end if
112
113 end subroutine log_begin
114
116 subroutine log_end(this)
117 class(log_t), intent(inout) :: this
118
119 if (pe_rank .eq. 0) then
120 this%indent_ = this%indent_ - 1
121 end if
122
123 end subroutine log_end
124
126 subroutine log_indent(this)
127 class(log_t), intent(in) :: this
128 integer :: i
129
130 if (pe_rank .eq. 0) then
131 write(this%unit_, '(A)', advance = 'no') repeat(' ', this%indent_)
132 end if
133
134 end subroutine log_indent
135
137 subroutine log_newline(this, lvl)
138 class(log_t), intent(in) :: this
139 integer, optional :: lvl
140
141 integer :: lvl_
142
143 if (present(lvl)) then
144 lvl_ = lvl
145 else
146 lvl_ = neko_log_info
147 end if
148
149 if (lvl_ .gt. this%level_) then
150 return
151 end if
152
153 if (pe_rank .eq. 0) then
154 write(this%unit_, '(A)') ''
155 end if
156
157 end subroutine log_newline
158
160 subroutine log_message(this, msg, lvl)
161 class(log_t), intent(in) :: this
162 character(len=*), intent(in) :: msg
163 integer, optional :: lvl
164 integer :: lvl_
165
166 if (present(lvl)) then
167 lvl_ = lvl
168 else
169 lvl_ = neko_log_info
170 end if
171
172 if (lvl_ .gt. this%level_) then
173 return
174 end if
175
176 if (pe_rank .eq. 0) then
177 call this%indent()
178 write(this%unit_, '(A)') trim(msg)
179 end if
180
181 end subroutine log_message
182
184 subroutine log_header(this, version, build_info)
185 class(log_t), intent(in) :: this
186 character(len=*), intent(in) :: version
187 character(len=*), intent(in) :: build_info
188
189 if (pe_rank .eq. 0) then
190 write(this%unit_, '(A)') ''
191 write(this%unit_, '(1X,A)') ' _ __ ____ __ __ ____ '
192 write(this%unit_, '(1X,A)') ' / |/ / / __/ / //_/ / __ \ '
193 write(this%unit_, '(1X,A)') ' / / / _/ / ,< / /_/ / '
194 write(this%unit_, '(1X,A)') '/_/|_/ /___/ /_/|_| \____/ '
195 write(this%unit_, '(A)') ''
196 write(this%unit_, '(1X,A,A,A)') '(version: ', trim(version), ')'
197 write(this%unit_, '(1X,A)') trim(build_info)
198 write(this%unit_, '(A)') ''
199 end if
200
201 end subroutine log_header
202
204 subroutine log_error(this, msg)
205 class(log_t), intent(in) :: this
206 character(len=*), intent(in) :: msg
207
208 if (pe_rank .eq. 0) then
209 call this%indent()
210 write(stderr, '(A,A,A)') '*** ERROR: ', trim(msg), ' ***'
211 end if
212
213 end subroutine log_error
214
216 subroutine log_warning(this, msg)
217 class(log_t), intent(in) :: this
218 character(len=*), intent(in) :: msg
219
220 if (pe_rank .eq. 0) then
221 call this%indent()
222 write(this%unit_, '(A,A,A)') '*** WARNING: ', trim(msg), ' ***'
223 end if
224
225 end subroutine log_warning
226
228 subroutine log_section(this, msg, lvl)
229 class(log_t), intent(inout) :: this
230 character(len=*), intent(in) :: msg
231 integer, optional :: lvl
232
233 integer :: i, pre, pos
234 integer :: lvl_
235
236 if (present(lvl)) then
237 lvl_ = lvl
238 else
239 lvl_ = neko_log_info
240 end if
241
242 if (lvl_ .gt. this%level_) then
243 return
244 end if
245
246 if (pe_rank .eq. 0) then
247
248 this%indent_ = this%indent_ + this%section_id_
249 this%section_id_ = this%section_id_ + 1
250
251 pre = (30 - len_trim(msg)) / 2
252 pos = 30 - (len_trim(msg) + pre)
253
254 write(this%unit_, '(A)') ''
255 call this%indent()
256 write(this%unit_, '(A,A,A)') &
257 repeat('-', pre), trim(msg), repeat('-', pos)
258
259 end if
260
261 end subroutine log_section
262
264 subroutine log_end_section(this, msg, lvl)
265 class(log_t), intent(inout) :: this
266 character(len=*), intent(in), optional :: msg
267 integer, optional :: lvl
268 integer :: lvl_
269
270 if (present(lvl)) then
271 lvl_ = lvl
272 else
273 lvl_ = neko_log_info
274 end if
275
276 if (lvl_ .gt. this%level_) then
277 return
278 end if
279
280 if (present(msg)) then
281 call this%message(msg, neko_log_quiet)
282 end if
283
284 if (pe_rank .eq. 0) then
285 this%section_id_ = this%section_id_ - 1
286 this%indent_ = this%indent_ - this%section_id_
287 end if
288
289 end subroutine log_end_section
290
293 subroutine log_status(this, t, T_end)
294 class(log_t), intent(in) :: this
295 real(kind=rp), intent(in) :: t
296 real(kind=rp), intent(in) :: t_end
297 character(len=LOG_SIZE) :: log_buf
298 real(kind=rp) :: t_prog
299
300 t_prog = 100d0 * t / t_end
301 write(log_buf, '(A4,E15.7,34X,A2,F6.2,A3)') 't = ', t, '[ ', t_prog, '% ]'
302
303 call this%message(repeat('-', 64), neko_log_quiet)
304 call this%message(log_buf, neko_log_quiet)
305 call this%message(repeat('-', 64), neko_log_quiet)
306
307 end subroutine log_status
308
309 !
310 ! Rudimentary C interface
311 !
312
315 subroutine log_message_c(c_msg) bind(c, name = 'log_message')
316 use, intrinsic :: iso_c_binding
317 character(kind=c_char), dimension(*), intent(in) :: c_msg
318 character(len=LOG_SIZE) :: msg
319 integer :: len
320
321 if (pe_rank .eq. 0) then
322 len = 0
323 do
324 if (c_msg(len+1) .eq. c_null_char) exit
325 len = len + 1
326 msg(len:len) = c_msg(len)
327 end do
328
329 call neko_log%indent()
330 write(neko_log%unit_, '(A)') trim(msg(1:len))
331 end if
332
333 end subroutine log_message_c
334
337 subroutine log_error_c(c_msg) bind(c, name = "log_error")
338 use, intrinsic :: iso_c_binding
339 character(kind=c_char), dimension(*), intent(in) :: c_msg
340 character(len=LOG_SIZE) :: msg
341 integer :: len
342
343 if (pe_rank .eq. 0) then
344 len = 0
345 do
346 if (c_msg(len+1) .eq. c_null_char) exit
347 len = len + 1
348 msg(len:len) = c_msg(len)
349 end do
350
351 call neko_log%indent()
352 write(stderr, '(A,A,A)') '*** ERROR: ', trim(msg(1:len)), ' ***'
353 end if
354
355 end subroutine log_error_c
356
359 subroutine log_warning_c(c_msg) bind(c, name = "log_warning")
360 use, intrinsic :: iso_c_binding
361 character(kind=c_char), dimension(*), intent(in) :: c_msg
362 character(len=LOG_SIZE) :: msg
363 integer :: len
364
365 if (pe_rank .eq. 0) then
366 len = 0
367 do
368 if (c_msg(len+1) .eq. c_null_char) exit
369 len = len + 1
370 msg(len:len) = c_msg(len)
371 end do
372
373 call neko_log%indent()
374 write(neko_log%unit_, '(A,A,A)') &
375 '*** WARNING: ', trim(msg(1:len)), ' ***'
376 end if
377
378 end subroutine log_warning_c
379
382 subroutine log_section_c(c_msg) bind(c, name = "log_section")
383 use, intrinsic :: iso_c_binding
384 character(kind=c_char), dimension(*), intent(in) :: c_msg
385 character(len=LOG_SIZE) :: msg
386 integer :: len
387
388 if (pe_rank .eq. 0) then
389 len = 0
390 do
391 if (c_msg(len+1) .eq. c_null_char) exit
392 len = len + 1
393 msg(len:len) = c_msg(len)
394 end do
395
396 call neko_log%section(trim(msg(1:len)))
397 end if
398
399 end subroutine log_section_c
400
403 subroutine log_end_section_c() bind(c, name = "log_end_section")
404
405 call neko_log%end_section()
406
407 end subroutine log_end_section_c
408
409end module logger
Definition comm.F90:1
integer pe_rank
MPI rank.
Definition comm.F90:28
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:404
subroutine log_end(this)
Decrease indention level.
Definition log.f90:117
subroutine log_header(this, version, build_info)
Write the Neko header to a log.
Definition log.f90:185
integer, parameter, public neko_log_verbose
Verbose log level.
Definition log.f90:71
subroutine log_message(this, msg, lvl)
Write a message to a log.
Definition log.f90:161
integer, parameter, public neko_log_quiet
Always logged.
Definition log.f90:67
subroutine log_begin(this)
Increase indention level.
Definition log.f90:107
subroutine log_message_c(c_msg)
Write a message to a log (from C)
Definition log.f90:316
subroutine log_end_section(this, msg, lvl)
End a log section.
Definition log.f90:265
subroutine log_init(this)
Initialize a log.
Definition log.f90:79
subroutine log_warning(this, msg)
Write a warning message to a log.
Definition log.f90:217
subroutine log_error_c(c_msg)
Write an error message to a log (from C)
Definition log.f90:338
subroutine log_indent(this)
Indent a log.
Definition log.f90:127
subroutine log_warning_c(c_msg)
Write a warning message to a log (from C)
Definition log.f90:360
subroutine log_newline(this, lvl)
Write a new line to a log.
Definition log.f90:138
subroutine log_section_c(c_msg)
Begin a new log section (from C)
Definition log.f90:383
integer, parameter, public neko_log_debug
Debug log level.
Definition log.f90:73
subroutine log_status(this, t, t_end)
Write status banner.
Definition log.f90:294
type(log_t), public neko_log
Global log stream.
Definition log.f90:65
integer, parameter, public log_size
Definition log.f90:42
integer, parameter, public neko_log_info
Default log level.
Definition log.f90:69
subroutine log_section(this, msg, lvl)
Begin a new log section.
Definition log.f90:229
subroutine log_error(this, msg)
Write an error message to a log.
Definition log.f90:205
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:12