Neko 1.99.9
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
utils.f90
Go to the documentation of this file.
1! Copyright (c) 2019-2026, 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!
35module utils
36 use, intrinsic :: iso_fortran_env, only : error_unit, output_unit
37 use iso_c_binding
38 use num_types, only: rp, dp
39 implicit none
40 private
41
42 integer, parameter :: neko_fname_len = 1024
43 integer, parameter :: neko_varname_len = 256
44 integer, parameter :: neko_typename_len = 64
45
46 interface neko_error
47 module procedure neko_error_plain, neko_error_msg
48 end interface neko_error
49
50 interface read_duration
51 module procedure read_duration_scalar
52 module procedure read_duration_components
53 end interface read_duration
54
55 abstract interface
56
57 subroutine throw_intf(filename, line_number, message)
58 character(len=*), intent(in) :: filename
59 integer, intent(in) :: line_number
60 character(len=*), optional, intent(in) :: message
61 end subroutine throw_intf
62 end interface
63
68 procedure(throw_intf), pointer :: throw_error => null()
70 procedure(throw_intf), pointer :: throw_warning => null()
71
81
82 interface
83 function c_mkdir(path, mode) bind(C, name="mkdir")
84 import :: c_char, c_int
85 character(kind=c_char), dimension(*) :: path
86 integer(c_int), value :: mode
87 integer(c_int) :: c_mkdir
88 end function c_mkdir
89 end interface
90
91contains
92
94 subroutine default_throw_warning(filename, line_number, message)
95 character(len=*), intent(in) :: filename
96 integer, intent(in) :: line_number
97 character(len=*), optional, intent(in) :: message
98 end subroutine default_throw_warning
99
103 subroutine default_throw_error(filename, line_number, message)
104 character(len=*), intent(in) :: filename
105 integer, intent(in) :: line_number
106 character(len=*), optional, intent(in) :: message
107
108 error stop
109 end subroutine default_throw_error
110
112 pure function filename_suffix_pos(fname) result(suffix_pos)
113 character(len=*), intent(in) :: fname
114 integer :: suffix_pos
115 suffix_pos = scan(trim(fname), '.', back = .true.)
116 end function filename_suffix_pos
117
119 pure function filename_tslash_pos(fname) result(tslash_pos)
120 character(len=*), intent(in) :: fname
121 integer :: tslash_pos
122 tslash_pos = scan(trim(fname), '/', back = .true.)
123 end function filename_tslash_pos
124
126 subroutine filename_path(fname, path)
127 character(len=*), intent(in) :: fname
128 character(len=*), intent(out) :: path
129 integer :: tslash_pos
130
131 tslash_pos = filename_tslash_pos(fname)
132 if (tslash_pos .gt. 0) then
133 path = trim(fname(1:tslash_pos))
134 else
135 path = './'
136 end if
137
138 end subroutine filename_path
139
141 subroutine filename_name(fname, name)
142 character(len=*), intent(in) :: fname
143 character(len=*), intent(out) :: name
144 integer :: tslash_pos, suffix_pos, start, end
145
146 tslash_pos = filename_tslash_pos(fname)
147 suffix_pos = filename_suffix_pos(fname)
148 if (tslash_pos .eq. 0) then
149 start = 1
150 else
151 start = tslash_pos + 1
152 end if
153 if (suffix_pos .eq. 0) then
154 end = len_trim(fname)
155 else
156 end = suffix_pos - 1
157 end if
158 name = trim(fname(start:end))
159 end subroutine filename_name
160
162 subroutine filename_suffix(fname, suffix)
163 character(len=*) :: fname
164 character(len=*) :: suffix
165 suffix = trim(fname(filename_suffix_pos(fname) + 1:len_trim(fname)))
166 end subroutine filename_suffix
167
169 subroutine filename_split(fname, path, name, suffix)
170 character(len=*), intent(in) :: fname
171 character(len=*), intent(out) :: path, name, suffix
172 integer :: tslash_pos, suffix_pos
173
174 tslash_pos = filename_tslash_pos(fname)
175 suffix_pos = filename_suffix_pos(fname)
176
177 if (tslash_pos .gt. 0) then
178 path = trim(fname(1:tslash_pos))
179 else
180 path = './'
181 end if
182
183 if (suffix_pos .gt. 0) then
184 name = trim(fname(tslash_pos + 1:suffix_pos - 1))
185 suffix = trim(fname(suffix_pos:len_trim(fname)))
186 else
187 name = trim(fname(tslash_pos + 1:len_trim(fname)))
188 suffix = ''
189 end if
190
191 end subroutine filename_split
192
194 subroutine filename_chsuffix(fname, new_fname, new_suffix)
195 character(len=*) :: fname
196 character(len=*) :: new_fname
197 character(len=*) :: new_suffix
198 integer :: suffix_pos
199
200 suffix_pos = filename_suffix_pos(fname)
201 new_fname = trim(fname(1:suffix_pos))//new_suffix
202
203 end subroutine filename_chsuffix
204
212 recursive subroutine mkdir(path, mode)
213 character(len=*), intent(in) :: path
214 integer, intent(in), optional :: mode
215 integer :: slash_pos, i, path_len
216 character(kind=c_char), allocatable :: c_path(:)
217 integer(c_int) :: dir_mode, ierr
218
219 if (present(mode)) then
220 dir_mode = int(mode, kind=c_int)
221 else
222 dir_mode = int(o'777', kind=c_int)
223 end if
224
225 slash_pos = scan(path, '/', back = .true.)
226 if (slash_pos .gt. 0) then
227 call mkdir(trim(path(1:slash_pos-1)), dir_mode)
228 end if
229
230 path_len = len_trim(path)
231 allocate(c_path(path_len + 1))
232 do i = 1, path_len
233 c_path(i) = path(i:i)
234 end do
235 c_path(path_len + 1) = c_null_char
236
237 ierr = c_mkdir(c_path, dir_mode)
238 deallocate(c_path)
239 end subroutine mkdir
240
247 function extract_fld_file_index(fld_filename, default_index) result(index)
248 character(len=*), intent(in) :: fld_filename
249 integer, intent(in) :: default_index
250
251 character(len=80) :: suffix
252 integer :: index, fpos, i
253 logical :: valid
254
255 call filename_suffix(fld_filename, suffix)
256
257 valid = .true.
258
259 ! This value will be modified when reading the file name extension
260 ! e.g. "field0.f00035" will set sample_idx = 35
261 index = default_index
262
263 !
264 ! Try to extract the index of the field file from the suffix "fxxxxx"
265 !
266 fpos = scan(trim(suffix), 'f')
267 if (fpos .eq. 1) then
268 ! Make sure that the suffix only contains integers from 0 to 9
269 do i = 2, len(trim(suffix))
270 if (.not. (iachar(suffix(i:i)) >= iachar('0') &
271 .and. iachar(suffix(i:i)) <= iachar('9'))) then
272 valid = .false.
273 end if
274 end do
275 else
276 valid = .false.
277 end if
278
279 ! Must be exactly 6 characters long, i.e. an 'f' with 5 integers after
280 if (len(trim(suffix)) .ne. 6) valid = .false.
281
282 if (valid) read (suffix(2:), "(I5.5)") index
283
284 end function extract_fld_file_index
285
289 function split_string(string, delimiter) result(split_str)
290 character(len=*) :: string
291 character(len=*) :: delimiter
292 character(len=100), allocatable :: split_str(:)
293 integer :: length, i, i2, offset, j
294 i = 0
295 offset = 1
296 length = 1
297 if (len(trim(string)) .eq. 0) then
298 allocate(split_str(1))
299 split_str(1) = trim(string)
300 return
301 end if
302 do while (.true.)
303 i = scan(string(offset:), delimiter, back = .false.)
304 if (i .eq. 0) exit
305 length = length + 1
306 offset = offset + i
307 end do
308
309 allocate(split_str(length))
310 i = 0
311 j = 1
312 offset = 1
313 do while (.true.)
314 i2 = scan(trim(string(offset:)), delimiter, back = .false.)
315 if (i2 .eq. 0) then
316 split_str(j) = trim(string(offset:))
317 exit
318 end if
319 split_str(j) = trim(string(offset:offset+i2-2))
320 offset = offset+i2
321 j = j + 1
322 end do
323 end function split_string
324
327 pure function linear_index(i, j, k, l, lx, ly, lz) result(index)
328 integer, intent(in) :: i, j, k, l, lx, ly, lz
329 integer :: index
330
331 index = (i + lx * ((j - 1) + ly * ((k - 1) + lz * ((l - 1)))))
332 end function linear_index
333
336 pure function nonlinear_index(linear_index, lx, ly, lz) result(index)
337 integer, intent(in) :: linear_index, lx, ly, lz
338 integer :: index(4)
339 integer :: lin_idx
340 lin_idx = linear_index -1
341 index(4) = lin_idx/(lx*ly*lz)
342 index(3) = (lin_idx-(lx*ly*lz)*index(4))/(lx*ly)
343 index(2) = (lin_idx-(lx*ly*lz)*index(4)-(lx*ly)*index(3))/lx
344 index(1) = (lin_idx-(lx*ly*lz)*index(4)-(lx*ly)*index(3)-lx*index(2))
345 index(1) = index(1) + 1
346 index(2) = index(2) + 1
347 index(3) = index(3) + 1
348 index(4) = index(4) + 1
349
350 end function nonlinear_index
351
352 pure function index_is_on_facet(i, j, k, lx, ly, lz, facet) result(is_on)
353 integer, intent(in) :: i, j, k, lx, ly, lz, facet
354 logical :: is_on
355
356 is_on = .false.
357 select case (facet)
358 case (1)
359 if (i .eq. 1) is_on = .true.
360 case (2)
361 if (i .eq. lx) is_on = .true.
362 case (3)
363 if (j .eq. 1) is_on = .true.
364 case (4)
365 if (j .eq. ly) is_on = .true.
366 case (5)
367 if (k .eq. 1) is_on = .true.
368 case (6)
369 if (k .eq. lz) is_on = .true.
370 end select
371
372 end function index_is_on_facet
373
376 subroutine neko_error_plain(error_code)
377 integer, optional :: error_code
378
379 ! Persist buffered log output before aborting, such that the error
380 ! appears after any preceding log messages
381 flush(output_unit)
382
383 if (present(error_code)) then
384 write(error_unit, *) '*** ERROR ***', error_code
385 else
386 write(error_unit, *) '*** ERROR ***'
387 end if
388 flush(error_unit)
389
390 if (.not. associated(throw_error)) throw_error => default_throw_error
391 call throw_error('utils.f90', -1, message='')
392 end subroutine neko_error_plain
393
396 subroutine neko_error_msg(error_msg)
397 character(len=*) :: error_msg
398
399 ! Persist buffered log output before aborting, such that the error
400 ! appears after any preceding log messages
401 flush(output_unit)
402 write(error_unit, *) '*** ERROR: ', trim(error_msg), ' ***'
403 flush(error_unit)
404 if (.not. associated(throw_error)) throw_error => default_throw_error
405 call throw_error('utils.f90', -1, message='')
406 end subroutine neko_error_msg
407
414 subroutine neko_type_error(base_type, wrong_type, known_types)
415 character(len=*), intent(in) :: base_type
416 character(len=*), intent(in) :: wrong_type
417 character(len=*), intent(in) :: known_types(:)
418 integer :: i
419
420 flush(output_unit)
421 write(error_unit, *) '*** ERROR WHEN SELECTING TYPE ***'
422 write(error_unit, *) 'Type ', wrong_type, ' does not exist for ', base_type
423 write(error_unit, *) 'Valid types are:'
424 do i = 1, size(known_types)
425 write(error_unit, *) " ", known_types(i)
426 end do
427 flush(error_unit)
428 if (.not. associated(throw_error)) throw_error => default_throw_error
429 call throw_error('utils.f90', -1, message='')
430 end subroutine neko_type_error
431
432 subroutine neko_type_registration_error(base_type, wrong_type, known)
433 character(len=*), intent(in) :: base_type
434 character(len=*), intent(in) :: wrong_type
435 logical, intent(in) :: known
436
437 flush(output_unit)
438 write(error_unit, *) '*** ERROR WHEN REGISTERING TYPE ***'
439 write(error_unit, *) 'Type name ', wrong_type, &
440 ' conflicts with and already existing ', base_type, " type"
441 if (known) then
442 write(error_unit, *) 'Please rename your custom type.'
443 else
444 write(error_unit, *) 'The already existing type is also custom.' // &
445 ' Make all custom type names unique!'
446 end if
447 flush(error_unit)
448 if (.not. associated(throw_error)) throw_error => default_throw_error
449 call throw_error('utils.f90', -1, message='')
450 end subroutine neko_type_registration_error
451
453 subroutine neko_warning(warning_msg)
454 character(len=*) :: warning_msg
455 write(output_unit, *) '*** WARNING: ', trim(warning_msg), ' ***'
456 flush(output_unit)
457
458 if (.not. associated(throw_warning)) throw_warning => default_throw_warning
459 call throw_warning('utils.f90', -1, message='')
460 end subroutine neko_warning
461
467 function concat_string_array(array, sep, prepend) result(result)
468 character(len=*), intent(in) :: array(:)
469 character(len=*), intent(in) :: sep
470 logical, intent(in) :: prepend
471 character(:), allocatable :: result
472 integer :: i
473
474 result = trim(array(1))
475 do i = 2, size(array)
476 result = result // sep // trim(array(i))
477 end do
478
479 if (prepend) then
480 result = sep // result
481 end if
482
483 end function concat_string_array
484
491 subroutine read_duration_scalar(runtime_string, runtime_seconds, &
492 ierr)
493 character(len=*), intent(in) :: runtime_string
494 real(kind=rp), intent(inout) :: runtime_seconds
495 integer, optional, intent(out) :: ierr
496 real(kind=dp) :: parsed_seconds
497
498 if (present(ierr)) ierr = 0
499 if (len_trim(runtime_string) .eq. 0) return
500
501 parsed_seconds = read_duration_internal(runtime_string, ierr)
502
503 if (present(ierr)) then
504 if (ierr .ne. 0) return
505 end if
506
507 runtime_seconds = parsed_seconds
508 end subroutine read_duration_scalar
509
516 subroutine read_duration_components(runtime_string, runtime_values, ierr)
517 character(len=*), intent(in) :: runtime_string
518 real(kind=rp), intent(inout) :: runtime_values(:)
519 integer, optional, intent(out) :: ierr
520 integer, parameter :: i64 = selected_int_kind(18)
521 integer :: n_values
522 integer(kind=i64) :: total_whole, days, hours, minutes, seconds_whole
523 real(kind=dp) :: parsed_seconds, second_value, frac_seconds
524
525 if (present(ierr)) ierr = 0
526 if (len_trim(runtime_string) .eq. 0) return
527
528 n_values = size(runtime_values)
529 if (n_values .lt. 1 .or. n_values .gt. 4) then
530 call set_error_or_throw( &
531 'Error parsing duration: output array size must be 1 to 4', ierr)
532 return
533 end if
534
535 parsed_seconds = read_duration_internal(runtime_string, ierr)
536
537 if (present(ierr)) then
538 if (ierr .ne. 0) return
539 end if
540
541 total_whole = int(parsed_seconds, kind=i64)
542 frac_seconds = parsed_seconds - real(total_whole, kind=dp)
543 if (frac_seconds .lt. 0.0_dp) frac_seconds = 0.0_dp
544
545 days = total_whole / 86400_i64
546 total_whole = total_whole - 86400_i64 * days
547 hours = total_whole / 3600_i64
548 total_whole = total_whole - 3600_i64 * hours
549 minutes = total_whole / 60_i64
550 seconds_whole = total_whole - 60_i64 * minutes
551
552 second_value = real(seconds_whole, kind=dp) + frac_seconds
553 if (second_value .ge. 60.0_dp) then
554 second_value = second_value - 60.0_dp
555 minutes = minutes + 1_i64
556 if (minutes .ge. 60_i64) then
557 minutes = minutes - 60_i64
558 hours = hours + 1_i64
559 if (hours .ge. 24_i64) then
560 hours = hours - 24_i64
561 days = days + 1_i64
562 end if
563 end if
564 end if
565
566 select case (n_values)
567 case (4)
568 runtime_values(1) = real(days, kind=rp)
569 runtime_values(2) = real(hours, kind=rp)
570 runtime_values(3) = real(minutes, kind=rp)
571 runtime_values(4) = real(second_value, kind=rp)
572 case (3)
573 runtime_values(1) = real(days * 24_i64 + hours, kind=rp)
574 runtime_values(2) = real(minutes, kind=rp)
575 runtime_values(3) = real(second_value, kind=rp)
576 case (2)
577 runtime_values(1) = real((days * 24_i64 + hours) * 60_i64 + &
578 minutes, kind=rp)
579 runtime_values(2) = real(second_value, kind=rp)
580 case (1)
581 runtime_values(1) = real(parsed_seconds, kind=rp)
582 end select
583 end subroutine read_duration_components
584
586 real(kind=dp) function read_duration_internal(runtime_string, ierr) &
587 result(runtime_seconds)
588 character(len=*), intent(in) :: runtime_string
589 integer, optional, intent(out) :: ierr
590 character(len=:), allocatable :: time_string
591 real(kind=dp) :: parsed_seconds, read_real
592 logical :: has_minutes, has_hours, has_days
593 integer :: read_int, ios, sep
594
595 if (present(ierr)) ierr = 0
596
597 runtime_seconds = 0.0_dp
598 time_string = trim(adjustl(runtime_string))
599
600 sep = index(time_string, ':')
601 has_minutes = sep .gt. 0
602 has_hours = .false.
603 if (has_minutes .and. sep .lt. len_trim(time_string)) then
604 has_hours = index(time_string(sep + 1:len_trim(time_string)), ':') &
605 .gt. 0
606 end if
607 has_days = index(time_string, '-') .gt. 0
608
609 if ((has_days .and. .not. has_hours) .or. &
610 (has_hours .and. .not. has_minutes)) then
611 call set_error_or_throw('Error parsing duration: Bad format', ierr)
612 return
613 end if
614
615 parsed_seconds = 0.0_dp
616
617 ! Read the days field.
618 if (has_days) then
619 sep = index(time_string, '-')
620 read(time_string(1:sep - 1), *, iostat=ios) read_int
621 if (ios .ne. 0 .or. read_int .lt. 0) then
622 call set_error_or_throw( &
623 'Error parsing duration: Invalid days value', ierr)
624 return
625 end if
626
627 time_string = time_string(sep + 1:)
628 parsed_seconds = parsed_seconds + real(86400 * read_int, kind=dp)
629 end if
630
631 ! Read the hours.
632 if (has_hours) then
633 sep = index(time_string, ':')
634 read(time_string(1:sep - 1), *, iostat=ios) read_int
635 if (ios .ne. 0 .or. read_int .lt. 0 .or. &
636 (has_days .and. read_int .gt. 23)) then
637 call set_error_or_throw( &
638 'Error parsing duration: Invalid hours value', ierr)
639 return
640 end if
641
642 time_string = time_string(sep + 1:)
643 parsed_seconds = parsed_seconds + real(3600 * read_int, kind=dp)
644 end if
645
646 ! Read the minutes.
647 if (has_minutes) then
648 sep = index(time_string, ':')
649 read(time_string(1:sep - 1), *, iostat=ios) read_int
650 if (ios .ne. 0 .or. read_int .lt. 0 .or. &
651 (has_hours .and. read_int .gt. 59)) then
652 call set_error_or_throw( &
653 'Error parsing duration: Invalid minutes value', ierr)
654 return
655 end if
656
657 time_string = time_string(sep + 1:)
658 parsed_seconds = parsed_seconds + real(60 * read_int, kind=dp)
659 end if
660
661 ! Read the seconds.
662 read(time_string, *, iostat=ios) read_real
663 if (ios .ne. 0 .or. read_real .lt. 0.0_dp .or. &
664 (has_minutes .and. read_real .ge. 60.0_dp)) then
665 call set_error_or_throw( &
666 'Error parsing duration: Invalid seconds value', ierr)
667 return
668 end if
669
670 parsed_seconds = parsed_seconds + read_real
671 runtime_seconds = parsed_seconds
672
673 if (allocated(time_string)) deallocate(time_string)
674 end function read_duration_internal
675
677 subroutine set_error_or_throw(message, ierr)
678 character(len=*), intent(in) :: message
679 integer, optional, intent(out) :: ierr
680
681 if (present(ierr)) then
682 ierr = 1
683 else
684 call neko_error(trim(message))
685 end if
686 end subroutine set_error_or_throw
687end module utils
__inline__ __device__ void nonlinear_index(const int idx, const int lx, int *index)
Definition bc_utils.h:44
double real
Interface for the throw procedure. Follows pFunit conventions.
Definition utils.f90:57
integer, parameter, public dp
Definition num_types.f90:10
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:14
Utilities.
Definition utils.f90:35
integer function, public extract_fld_file_index(fld_filename, default_index)
Extracts the index of a field file. For example, "myfield.f00045" will return 45. If the suffix of th...
Definition utils.f90:248
character(:) function, allocatable, public concat_string_array(array, sep, prepend)
Concatenate an array of strings into one string with array items separated by spaces.
Definition utils.f90:468
subroutine, public neko_type_registration_error(base_type, wrong_type, known)
Definition utils.f90:433
subroutine, public filename_name(fname, name)
Extract the base name of a file (without path and suffix)
Definition utils.f90:142
subroutine set_error_or_throw(message, ierr)
Raise parser error or set ierr, depending on call mode.
Definition utils.f90:678
character(len=100) function, dimension(:), allocatable, public split_string(string, delimiter)
Split a string based on delimiter (tokenizer) OBS: very hacky, this should really be improved,...
Definition utils.f90:290
pure logical function, public index_is_on_facet(i, j, k, lx, ly, lz, facet)
Definition utils.f90:353
subroutine, public default_throw_error(filename, line_number, message)
Default throw method that stops execution.
Definition utils.f90:104
subroutine neko_error_msg(error_msg)
Reports an error and calls throw_error, which stops execution by default.
Definition utils.f90:397
pure integer function, public linear_index(i, j, k, l, lx, ly, lz)
Compute the address of a (i,j,k,l) array with sizes (1:lx, 1:ly, 1:lz, :)
Definition utils.f90:328
subroutine read_duration_scalar(runtime_string, runtime_seconds, ierr)
Parse runtime string to total seconds. Supported formats are:
Definition utils.f90:493
procedure(throw_intf), pointer, public throw_error
Pointer to the throw procedure.
Definition utils.f90:68
integer, parameter, public neko_fname_len
Definition utils.f90:42
subroutine, public filename_split(fname, path, name, suffix)
Extract file name components.
Definition utils.f90:170
subroutine, public neko_warning(warning_msg)
Reports a warning to standard output.
Definition utils.f90:454
real(kind=dp) function read_duration_internal(runtime_string, ierr)
Parse runtime string to total seconds.
Definition utils.f90:588
subroutine, public filename_chsuffix(fname, new_fname, new_suffix)
Change a filename's suffix.
Definition utils.f90:195
integer, parameter, public neko_typename_len
Definition utils.f90:44
subroutine, public default_throw_warning(filename, line_number, message)
Default throw method for warnings. Does nothing.
Definition utils.f90:95
subroutine read_duration_components(runtime_string, runtime_values, ierr)
Parse runtime string to components. The output array maps to the largest unit available based on size...
Definition utils.f90:517
subroutine, public filename_suffix(fname, suffix)
Extract a filename's suffix.
Definition utils.f90:163
procedure(throw_intf), pointer, public throw_warning
Same as above, but for warnings. Does nothing by default.
Definition utils.f90:70
subroutine, public neko_type_error(base_type, wrong_type, known_types)
Reports an error allocating a type for a particular base pointer class.
Definition utils.f90:415
recursive subroutine, public mkdir(path, mode)
Recursively create a directory and all parent directories if they do not exist. This should be safer ...
Definition utils.f90:213
integer, parameter, public neko_varname_len
Definition utils.f90:43
pure integer function, public filename_tslash_pos(fname)
Find position (in the string) of a filename's trailing slash.
Definition utils.f90:120
subroutine neko_error_plain(error_code)
Reports an error and calls throw_error, which stops execution by default.
Definition utils.f90:377
pure integer function, public filename_suffix_pos(fname)
Find position (in the string) of a filename's suffix.
Definition utils.f90:113
subroutine, public filename_path(fname, path)
Extract the path to a file.
Definition utils.f90:127