Neko 0.9.99
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, 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
129 if (pe_rank .eq. 0) then
130 write(this%unit_, '(A)', advance = 'no') repeat(' ', this%indent_)
131 end if
132
133 end subroutine log_indent
134
136 subroutine log_newline(this, lvl)
137 class(log_t), intent(in) :: this
138 integer, optional :: lvl
139
140 integer :: lvl_
141
142 if (present(lvl)) then
143 lvl_ = lvl
144 else
145 lvl_ = neko_log_info
146 end if
147
148 if (lvl_ .gt. this%level_) then
149 return
150 end if
151
152 if (pe_rank .eq. 0) then
153 write(this%unit_, '(A)') ''
154 end if
155
156 end subroutine log_newline
157
159 subroutine log_message(this, msg, lvl)
160 class(log_t), intent(in) :: this
161 character(len=*), intent(in) :: msg
162 integer, optional :: lvl
163 integer :: lvl_
164
165 if (present(lvl)) then
166 lvl_ = lvl
167 else
168 lvl_ = neko_log_info
169 end if
170
171 if (lvl_ .gt. this%level_) then
172 return
173 end if
174
175 if (pe_rank .eq. 0) then
176 call this%indent()
177 write(this%unit_, '(A)') trim(msg)
178 end if
179
180 end subroutine log_message
181
183 subroutine log_header(this, version, build_info)
184 class(log_t), intent(in) :: this
185 character(len=*), intent(in) :: version
186 character(len=*), intent(in) :: build_info
187
188 if (pe_rank .eq. 0) then
189 write(this%unit_, '(A)') ''
190 write(this%unit_, '(1X,A)') ' _ __ ____ __ __ ____ '
191 write(this%unit_, '(1X,A)') ' / |/ / / __/ / //_/ / __ \ '
192 write(this%unit_, '(1X,A)') ' / / / _/ / ,< / /_/ / '
193 write(this%unit_, '(1X,A)') '/_/|_/ /___/ /_/|_| \____/ '
194 write(this%unit_, '(A)') ''
195 write(this%unit_, '(1X,A,A,A)') '(version: ', trim(version), ')'
196 write(this%unit_, '(1X,A)') trim(build_info)
197 write(this%unit_, '(A)') ''
198 end if
199
200 end subroutine log_header
201
203 subroutine log_error(this, msg)
204 class(log_t), intent(in) :: this
205 character(len=*), intent(in) :: msg
206
207 if (pe_rank .eq. 0) then
208 call this%indent()
209 write(stderr, '(A,A,A)') '*** ERROR: ', trim(msg), ' ***'
210 end if
211
212 end subroutine log_error
213
215 subroutine log_warning(this, msg)
216 class(log_t), intent(in) :: this
217 character(len=*), intent(in) :: msg
218
219 if (pe_rank .eq. 0) then
220 call this%indent()
221 write(this%unit_, '(A,A,A)') '*** WARNING: ', trim(msg), ' ***'
222 end if
223
224 end subroutine log_warning
225
227 subroutine log_section(this, msg, lvl)
228 class(log_t), intent(inout) :: this
229 character(len=*), intent(in) :: msg
230 integer, optional :: lvl
231
232 integer :: pre, pos
233 integer :: lvl_
234
235 if (present(lvl)) then
236 lvl_ = lvl
237 else
238 lvl_ = neko_log_info
239 end if
240
241 if (lvl_ .gt. this%level_) then
242 return
243 end if
244
245 if (pe_rank .eq. 0) then
246
247 this%indent_ = this%indent_ + this%section_id_
248 this%section_id_ = this%section_id_ + 1
249
250 pre = (30 - len_trim(msg)) / 2
251 pos = 30 - (len_trim(msg) + pre)
252
253 write(this%unit_, '(A)') ''
254 call this%indent()
255 write(this%unit_, '(A,A,A)') &
256 repeat('-', pre), trim(msg), repeat('-', pos)
257
258 end if
259
260 end subroutine log_section
261
263 subroutine log_end_section(this, msg, lvl)
264 class(log_t), intent(inout) :: this
265 character(len=*), intent(in), optional :: msg
266 integer, optional :: lvl
267 integer :: lvl_
268
269 if (present(lvl)) then
270 lvl_ = lvl
271 else
272 lvl_ = neko_log_info
273 end if
274
275 if (lvl_ .gt. this%level_) then
276 return
277 end if
278
279 if (present(msg)) then
280 call this%message(msg, neko_log_quiet)
281 end if
282
283 if (pe_rank .eq. 0) then
284 this%section_id_ = this%section_id_ - 1
285 this%indent_ = this%indent_ - this%section_id_
286 end if
287
288 end subroutine log_end_section
289
292 subroutine log_status(this, t, T_end)
293 class(log_t), intent(in) :: this
294 real(kind=rp), intent(in) :: t
295 real(kind=rp), intent(in) :: t_end
296 character(len=LOG_SIZE) :: log_buf
297 real(kind=rp) :: t_prog
298
299 t_prog = 100d0 * t / t_end
300 write(log_buf, '(A4,E15.7,34X,A2,F6.2,A3)') 't = ', t, '[ ', t_prog, '% ]'
301
302 call this%message(repeat('-', 64), neko_log_quiet)
303 call this%message(log_buf, neko_log_quiet)
304 call this%message(repeat('-', 64), neko_log_quiet)
305
306 end subroutine log_status
307
308 !
309 ! Rudimentary C interface
310 !
311
314 subroutine log_message_c(c_msg) bind(c, name = 'log_message')
315 use, intrinsic :: iso_c_binding
316 character(kind=c_char), dimension(*), intent(in) :: c_msg
317 character(len=LOG_SIZE) :: msg
318 integer :: len
319
320 if (pe_rank .eq. 0) then
321 len = 0
322 do
323 if (c_msg(len+1) .eq. c_null_char) exit
324 len = len + 1
325 msg(len:len) = c_msg(len)
326 end do
327
328 call neko_log%indent()
329 write(neko_log%unit_, '(A)') trim(msg(1:len))
330 end if
331
332 end subroutine log_message_c
333
336 subroutine log_error_c(c_msg) bind(c, name = "log_error")
337 use, intrinsic :: iso_c_binding
338 character(kind=c_char), dimension(*), intent(in) :: c_msg
339 character(len=LOG_SIZE) :: msg
340 integer :: len
341
342 if (pe_rank .eq. 0) then
343 len = 0
344 do
345 if (c_msg(len+1) .eq. c_null_char) exit
346 len = len + 1
347 msg(len:len) = c_msg(len)
348 end do
349
350 call neko_log%indent()
351 write(stderr, '(A,A,A)') '*** ERROR: ', trim(msg(1:len)), ' ***'
352 end if
353
354 end subroutine log_error_c
355
358 subroutine log_warning_c(c_msg) bind(c, name = "log_warning")
359 use, intrinsic :: iso_c_binding
360 character(kind=c_char), dimension(*), intent(in) :: c_msg
361 character(len=LOG_SIZE) :: msg
362 integer :: len
363
364 if (pe_rank .eq. 0) then
365 len = 0
366 do
367 if (c_msg(len+1) .eq. c_null_char) exit
368 len = len + 1
369 msg(len:len) = c_msg(len)
370 end do
371
372 call neko_log%indent()
373 write(neko_log%unit_, '(A,A,A)') &
374 '*** WARNING: ', trim(msg(1:len)), ' ***'
375 end if
376
377 end subroutine log_warning_c
378
381 subroutine log_section_c(c_msg) bind(c, name = "log_section")
382 use, intrinsic :: iso_c_binding
383 character(kind=c_char), dimension(*), intent(in) :: c_msg
384 character(len=LOG_SIZE) :: msg
385 integer :: len
386
387 if (pe_rank .eq. 0) then
388 len = 0
389 do
390 if (c_msg(len+1) .eq. c_null_char) exit
391 len = len + 1
392 msg(len:len) = c_msg(len)
393 end do
394
395 call neko_log%section(trim(msg(1:len)))
396 end if
397
398 end subroutine log_section_c
399
402 subroutine log_end_section_c() bind(c, name = "log_end_section")
403
404 call neko_log%end_section()
405
406 end subroutine log_end_section_c
407
408end 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:403
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:184
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:160
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:315
subroutine log_end_section(this, msg, lvl)
End a log section.
Definition log.f90:264
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:216
subroutine log_error_c(c_msg)
Write an error message to a log (from C)
Definition log.f90:337
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:359
subroutine log_newline(this, lvl)
Write a new line to a log.
Definition log.f90:137
subroutine log_section_c(c_msg)
Begin a new log section (from C)
Definition log.f90:382
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:293
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:228
subroutine log_error(this, msg)
Write an error message to a log.
Definition log.f90:204
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:12