36 use,
intrinsic :: iso_fortran_env, only : error_unit, output_unit
58 character(len=*),
intent(in) :: filename
59 integer,
intent(in) :: line_number
60 character(len=*),
optional,
intent(in) :: message
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
95 character(len=*),
intent(in) :: filename
96 integer,
intent(in) :: line_number
97 character(len=*),
optional,
intent(in) :: message
104 character(len=*),
intent(in) :: filename
105 integer,
intent(in) :: line_number
106 character(len=*),
optional,
intent(in) :: message
113 character(len=*),
intent(in) :: fname
114 integer :: suffix_pos
115 suffix_pos = scan(trim(fname),
'.', back = .true.)
120 character(len=*),
intent(in) :: fname
121 integer :: tslash_pos
122 tslash_pos = scan(trim(fname),
'/', back = .true.)
127 character(len=*),
intent(in) :: fname
128 character(len=*),
intent(out) :: path
129 integer :: tslash_pos
132 if (tslash_pos .gt. 0)
then
133 path = trim(fname(1:tslash_pos))
142 character(len=*),
intent(in) :: fname
143 character(len=*),
intent(out) :: name
144 integer :: tslash_pos, suffix_pos, start, end
148 if (tslash_pos .eq. 0)
then
151 start = tslash_pos + 1
153 if (suffix_pos .eq. 0)
then
154 end = len_trim(fname)
158 name = trim(fname(start:
end))
163 character(len=*) :: fname
164 character(len=*) :: suffix
170 character(len=*),
intent(in) :: fname
171 character(len=*),
intent(out) :: path, name, suffix
172 integer :: tslash_pos, suffix_pos
177 if (tslash_pos .gt. 0)
then
178 path = trim(fname(1:tslash_pos))
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)))
187 name = trim(fname(tslash_pos + 1:len_trim(fname)))
195 character(len=*) :: fname
196 character(len=*) :: new_fname
197 character(len=*) :: new_suffix
198 integer :: suffix_pos
201 new_fname = trim(fname(1:suffix_pos))//new_suffix
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
219 if (
present(mode))
then
220 dir_mode = int(mode, kind=c_int)
222 dir_mode = int(o
'777', kind=c_int)
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)
230 path_len = len_trim(path)
231 allocate(c_path(path_len + 1))
233 c_path(i) = path(i:i)
235 c_path(path_len + 1) = c_null_char
237 ierr =
c_mkdir(c_path, dir_mode)
248 character(len=*),
intent(in) :: fld_filename
249 integer,
intent(in) :: default_index
251 character(len=80) :: suffix
252 integer :: index, fpos, i
261 index = default_index
266 fpos = scan(trim(suffix),
'f')
267 if (fpos .eq. 1)
then
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
280 if (len(trim(suffix)) .ne. 6) valid = .false.
282 if (valid)
read (suffix(2:),
"(I5.5)") index
290 character(len=*) :: string
291 character(len=*) :: delimiter
292 character(len=100),
allocatable :: split_str(:)
293 integer :: length, i, i2, offset, j
297 if (len(trim(string)) .eq. 0)
then
298 allocate(split_str(1))
299 split_str(1) = trim(string)
303 i = scan(string(offset:), delimiter, back = .false.)
309 allocate(split_str(length))
314 i2 = scan(trim(string(offset:)), delimiter, back = .false.)
316 split_str(j) = trim(string(offset:))
319 split_str(j) = trim(string(offset:offset+i2-2))
328 integer,
intent(in) :: i, j, k, l, lx, ly, lz
331 index = (i + lx * ((j - 1) + ly * ((k - 1) + lz * ((l - 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
353 integer,
intent(in) :: i, j, k, lx, ly, lz, facet
359 if (i .eq. 1) is_on = .true.
361 if (i .eq. lx) is_on = .true.
363 if (j .eq. 1) is_on = .true.
365 if (j .eq. ly) is_on = .true.
367 if (k .eq. 1) is_on = .true.
369 if (k .eq. lz) is_on = .true.
377 integer,
optional :: error_code
383 if (
present(error_code))
then
384 write(error_unit, *)
'*** ERROR ***', error_code
386 write(error_unit, *)
'*** ERROR ***'
397 character(len=*) :: error_msg
402 write(error_unit, *)
'*** ERROR: ', trim(error_msg),
' ***'
415 character(len=*),
intent(in) :: base_type
416 character(len=*),
intent(in) :: wrong_type
417 character(len=*),
intent(in) :: known_types(:)
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)
433 character(len=*),
intent(in) :: base_type
434 character(len=*),
intent(in) :: wrong_type
435 logical,
intent(in) :: known
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"
442 write(error_unit, *)
'Please rename your custom type.'
444 write(error_unit, *)
'The already existing type is also custom.' // &
445 ' Make all custom type names unique!'
454 character(len=*) :: warning_msg
455 write(output_unit, *)
'*** WARNING: ', trim(warning_msg),
' ***'
468 character(len=*),
intent(in) :: array(:)
469 character(len=*),
intent(in) :: sep
470 logical,
intent(in) :: prepend
471 character(:),
allocatable :: result
474 result = trim(array(1))
475 do i = 2,
size(array)
476 result = result // sep // trim(array(i))
480 result = sep // result
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
498 if (
present(ierr)) ierr = 0
499 if (len_trim(runtime_string) .eq. 0)
return
503 if (
present(ierr))
then
504 if (ierr .ne. 0)
return
507 runtime_seconds = parsed_seconds
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)
522 integer(kind=i64) :: total_whole, days, hours, minutes, seconds_whole
523 real(kind=dp) :: parsed_seconds, second_value, frac_seconds
525 if (
present(ierr)) ierr = 0
526 if (len_trim(runtime_string) .eq. 0)
return
528 n_values =
size(runtime_values)
529 if (n_values .lt. 1 .or. n_values .gt. 4)
then
531 'Error parsing duration: output array size must be 1 to 4', ierr)
537 if (
present(ierr))
then
538 if (ierr .ne. 0)
return
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
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
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
566 select case (n_values)
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)
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)
577 runtime_values(1) =
real((days * 24_i64 + hours) * 60_i64 + &
579 runtime_values(2) =
real(second_value, kind=rp)
581 runtime_values(1) =
real(parsed_seconds, kind=rp)
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
595 if (
present(ierr)) ierr = 0
597 runtime_seconds = 0.0_dp
598 time_string = trim(adjustl(runtime_string))
600 sep = index(time_string,
':')
601 has_minutes = sep .gt. 0
603 if (has_minutes .and. sep .lt. len_trim(time_string))
then
604 has_hours = index(time_string(sep + 1:len_trim(time_string)),
':') &
607 has_days = index(time_string,
'-') .gt. 0
609 if ((has_days .and. .not. has_hours) .or. &
610 (has_hours .and. .not. has_minutes))
then
615 parsed_seconds = 0.0_dp
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
623 'Error parsing duration: Invalid days value', ierr)
627 time_string = time_string(sep + 1:)
628 parsed_seconds = parsed_seconds +
real(86400 * read_int, kind=dp)
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
638 'Error parsing duration: Invalid hours value', ierr)
642 time_string = time_string(sep + 1:)
643 parsed_seconds = parsed_seconds +
real(3600 * read_int, kind=dp)
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
653 'Error parsing duration: Invalid minutes value', ierr)
657 time_string = time_string(sep + 1:)
658 parsed_seconds = parsed_seconds +
real(60 * read_int, kind=dp)
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
666 'Error parsing duration: Invalid seconds value', ierr)
670 parsed_seconds = parsed_seconds + read_real
671 runtime_seconds = parsed_seconds
673 if (
allocated(time_string))
deallocate(time_string)
678 character(len=*),
intent(in) :: message
679 integer,
optional,
intent(out) :: ierr
681 if (
present(ierr))
then
__inline__ __device__ void nonlinear_index(const int idx, const int lx, int *index)
Interface for the throw procedure. Follows pFunit conventions.
integer, parameter, public dp
integer, parameter, public rp
Global precision used in computations.
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...
character(:) function, allocatable, public concat_string_array(array, sep, prepend)
Concatenate an array of strings into one string with array items separated by spaces.
subroutine, public neko_type_registration_error(base_type, wrong_type, known)
subroutine, public filename_name(fname, name)
Extract the base name of a file (without path and suffix)
subroutine set_error_or_throw(message, ierr)
Raise parser error or set ierr, depending on call mode.
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,...
pure logical function, public index_is_on_facet(i, j, k, lx, ly, lz, facet)
subroutine, public default_throw_error(filename, line_number, message)
Default throw method that stops execution.
subroutine neko_error_msg(error_msg)
Reports an error and calls throw_error, which stops execution by default.
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, :)
subroutine read_duration_scalar(runtime_string, runtime_seconds, ierr)
Parse runtime string to total seconds. Supported formats are:
procedure(throw_intf), pointer, public throw_error
Pointer to the throw procedure.
integer, parameter, public neko_fname_len
subroutine, public filename_split(fname, path, name, suffix)
Extract file name components.
subroutine, public neko_warning(warning_msg)
Reports a warning to standard output.
real(kind=dp) function read_duration_internal(runtime_string, ierr)
Parse runtime string to total seconds.
subroutine, public filename_chsuffix(fname, new_fname, new_suffix)
Change a filename's suffix.
integer, parameter, public neko_typename_len
subroutine, public default_throw_warning(filename, line_number, message)
Default throw method for warnings. Does nothing.
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...
subroutine, public filename_suffix(fname, suffix)
Extract a filename's suffix.
procedure(throw_intf), pointer, public throw_warning
Same as above, but for warnings. Does nothing by default.
subroutine, public neko_type_error(base_type, wrong_type, known_types)
Reports an error allocating a type for a particular base pointer class.
recursive subroutine, public mkdir(path, mode)
Recursively create a directory and all parent directories if they do not exist. This should be safer ...
integer, parameter, public neko_varname_len
pure integer function, public filename_tslash_pos(fname)
Find position (in the string) of a filename's trailing slash.
subroutine neko_error_plain(error_code)
Reports an error and calls throw_error, which stops execution by default.
pure integer function, public filename_suffix_pos(fname)
Find position (in the string) of a filename's suffix.
subroutine, public filename_path(fname, path)
Extract the path to a file.