Neko 1.99.9
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
json_utils.f90
Go to the documentation of this file.
1! Copyright (c) 2019-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!
34!
35! These are json-fortran type codes:
36! json_unknown = 0
37! json_null = 1
38! json_object = 2
39! json_array = 3
40! json_logical = 4
41! json_integer = 5
42! json_real = 6
43! json_string = 7
45 use num_types, only : dp, sp
46 use json_module, only : json_file, json_value, json_core
47 use utils, only : neko_error
48 implicit none
49 private
50
54
56 logical :: json_no_defaults = .false.
57
64 end interface json_get
65
72 end interface json_get_or_default
73
75 module procedure json_get_or_lookup_real, json_get_or_lookup_double, &
76 json_get_or_lookup_real_array, json_get_or_lookup_double_array, &
77 json_get_or_lookup_integer, json_get_or_lookup_integer_array
78 end interface json_get_or_lookup
79
81 module procedure json_get_or_lookup_or_default_real, &
82 json_get_or_lookup_or_default_double, &
83 json_get_or_lookup_or_default_integer
85
88 end interface json_extract_item
89
90 interface
91 module subroutine json_get_or_lookup_real(json, name, val)
92 type(json_file), intent(inout) :: json
93 character(len=*), intent(in) :: name
94 real(kind=sp), intent(out) :: val
95 end subroutine json_get_or_lookup_real
96
97 module subroutine json_get_or_lookup_double(json, name, val)
98 type(json_file), intent(inout) :: json
99 character(len=*), intent(in) :: name
100 real(kind=dp), intent(out) :: val
101 end subroutine json_get_or_lookup_double
102
103 module subroutine json_get_or_lookup_integer(json, name, val)
104 type(json_file), intent(inout) :: json
105 character(len=*), intent(in) :: name
106 integer, intent(out) :: val
107 end subroutine json_get_or_lookup_integer
108
109 module subroutine json_get_or_lookup_or_default_real(json, &
110 name, val, default)
111 type(json_file), intent(inout) :: json
112 character(len=*), intent(in) :: name
113 real(kind=sp), intent(out) :: val
114 real(kind=sp), intent(in) :: default
115 end subroutine json_get_or_lookup_or_default_real
116
117 module subroutine json_get_or_lookup_or_default_double(json, &
118 name, val, default)
119 type(json_file), intent(inout) :: json
120 character(len=*), intent(in) :: name
121 real(kind=dp), intent(out) :: val
122 real(kind=dp), intent(in) :: default
123 end subroutine json_get_or_lookup_or_default_double
124
125 module subroutine json_get_or_lookup_or_default_integer(json,&
126 name, val, default)
127 type(json_file), intent(inout) :: json
128 character(len=*), intent(in) :: name
129 integer, intent(out) :: val
130 integer, intent(in) :: default
131 end subroutine json_get_or_lookup_or_default_integer
132
133 module subroutine json_get_or_lookup_real_array(json, name, val)
134 type(json_file), intent(inout) :: json
135 character(len=*), intent(in) :: name
136 real(kind=sp), allocatable, intent(inout) :: val(:)
137 end subroutine json_get_or_lookup_real_array
138
139 module subroutine json_get_or_lookup_double_array(json, name, val)
140 type(json_file), intent(inout) :: json
141 character(len=*), intent(in) :: name
142 real(kind=dp), allocatable, intent(inout) :: val(:)
143 end subroutine json_get_or_lookup_double_array
144
145 module subroutine json_get_or_lookup_integer_array(json, name, val)
146 type(json_file), intent(inout) :: json
147 character(len=*), intent(in) :: name
148 integer, allocatable, intent(inout) :: val(:)
149 end subroutine json_get_or_lookup_integer_array
150
151 end interface
152contains
153
159 subroutine json_get_real(json, name, value)
160 type(json_file), intent(inout) :: json
161 character(len=*), intent(in) :: name
162 real(kind=sp), intent(out) :: value
163 logical :: found
164 integer :: var_type
165
166 call json%info(name, found = found, var_type = var_type)
167 if (.not. found) then
168 call neko_error("Parameter " // name // " missing from the case file")
169 else if (var_type .ne. 6) then
170 call neko_error("Parameter " // name // " is not a real")
171 end if
172
173 call json%get(name, value)
174 end subroutine json_get_real
175
180 subroutine json_get_double(json, name, value)
181 type(json_file), intent(inout) :: json
182 character(len=*), intent(in) :: name
183 real(kind=dp), intent(out) :: value
184 logical :: found
185 integer :: var_type
186
187 call json%info(name, found = found, var_type = var_type)
188 if (.not. found) then
189 call neko_error("Parameter " // name // " missing from the case file")
190 else if (var_type .ne. 6) then
191 call neko_error("Parameter " // name // " is not a real")
192 end if
193
194 call json%get(name, value)
195 end subroutine json_get_double
196
201 subroutine json_get_integer(json, name, value)
202 type(json_file), intent(inout) :: json
203 character(len=*), intent(in) :: name
204 integer, intent(out) :: value
205 logical :: found
206 integer :: var_type
207
208 call json%info(name, found = found, var_type = var_type)
209 if (.not. found) then
210 call neko_error("Parameter " // name // " missing from the case file")
211 else if (var_type .ne. 5) then
212 call neko_error("Parameter " // name // " is not an integer")
213 end if
214
215 call json%get(name, value)
216 end subroutine json_get_integer
217
222 subroutine json_get_logical(json, name, value)
223 type(json_file), intent(inout) :: json
224 character(len=*), intent(in) :: name
225 logical, intent(out) :: value
226 logical :: found
227 integer :: var_type
228
229 call json%info(name, found = found, var_type = var_type)
230 if (.not. found) then
231 call neko_error("Parameter " // name // " missing from the case file")
232 else if (var_type .ne. 4) then
233 call neko_error("Parameter " // name // " is not a logical")
234 end if
235
236 call json%get(name, value)
237 end subroutine json_get_logical
238
243 subroutine json_get_string(json, name, value)
244 type(json_file), intent(inout) :: json
245 character(len=*), intent(in) :: name
246 character(len=:), allocatable, intent(out) :: value
247 logical :: found
248 integer :: var_type
249
250 call json%info(name, found = found, var_type = var_type)
251 if (.not. found) then
252 call neko_error("Parameter " // name // " missing from the case file")
253 else if (var_type .ne. 7) then
254 call neko_error("Parameter " // name // " is not a string")
255 end if
256
257 call json%get(name, value)
258 end subroutine json_get_string
259
266 subroutine json_get_real_array(json, name, value, expected_size)
267 type(json_file), intent(inout) :: json
268 character(len=*), intent(in) :: name
269 real(kind=sp), allocatable, intent(out) :: value(:)
270 integer, optional, intent(in) :: expected_size
271 logical :: found
272 integer :: var_type
273 integer :: actual_size
274
275 call json%info(name, found = found, var_type = var_type, &
276 n_children = actual_size)
277
278 if (.not. found) then
279 call neko_error("Parameter " // name // " missing from the case file")
280 else if (var_type .ne. 3) then
281 call neko_error("Parameter " // name // " is not an array")
282 end if
283
284 if (present(expected_size)) then
285 call check_expected_size(name, actual_size, expected_size)
286 end if
287
288 call json%get(name, value)
289 end subroutine json_get_real_array
290
297 subroutine json_get_double_array(json, name, value, expected_size)
298 type(json_file), intent(inout) :: json
299 character(len=*), intent(in) :: name
300 real(kind=dp), allocatable, intent(out) :: value(:)
301 integer, optional, intent(in) :: expected_size
302 logical :: found
303 integer :: var_type
304 integer :: actual_size
305
306 call json%info(name, found = found, var_type = var_type, &
307 n_children = actual_size)
308
309 if (.not. found) then
310 call neko_error("Parameter " // name // " missing from the case file")
311 else if (var_type .ne. 3) then
312 call neko_error("Parameter " // name // " is not an array")
313 end if
314
315 if (present(expected_size)) then
316 call check_expected_size(name, actual_size, expected_size)
317 end if
318
319 call json%get(name, value)
320 end subroutine json_get_double_array
321
328 subroutine json_get_integer_array(json, name, value, expected_size)
329 type(json_file), intent(inout) :: json
330 character(len=*), intent(in) :: name
331 integer, allocatable, intent(out) :: value(:)
332 integer, optional, intent(in) :: expected_size
333 logical :: found
334 integer :: var_type
335 integer :: actual_size
336
337 call json%info(name, found = found, var_type = var_type, &
338 n_children = actual_size)
339
340 if (.not. found) then
341 call neko_error("Parameter " // name // " missing from the case file")
342 end if
343
344 if (present(expected_size)) then
345 call check_expected_size(name, actual_size, expected_size)
346 end if
347
348 call json%get(name, value)
349 end subroutine json_get_integer_array
350
357 subroutine json_get_logical_array(json, name, value, expected_size)
358 type(json_file), intent(inout) :: json
359 character(len=*), intent(in) :: name
360 logical, allocatable, intent(out) :: value(:)
361 integer, optional, intent(in) :: expected_size
362 logical :: found
363 integer :: var_type
364 integer :: actual_size
365
366 call json%info(name, found = found, var_type = var_type, &
367 n_children = actual_size)
368
369 if (.not. found) then
370 call neko_error("Parameter " // name // " missing from the case file")
371 else if (var_type .ne. 3) then
372 call neko_error("Parameter " // name // " is not a array")
373 end if
374
375 if (present(expected_size)) then
376 call check_expected_size(name, actual_size, expected_size)
377 end if
378
379 call json%get(name, value)
380 end subroutine json_get_logical_array
381
387 subroutine json_get_string_array(json, name, value, filler)
388 type(json_file), intent(inout) :: json
389 character(len=*), intent(in) :: name
390 character(len=*), allocatable, intent(out) :: value(:)
391 character(len=*), optional, intent(in) :: filler
392 logical :: found
393 type(json_value), pointer :: json_val, val_ptr
394 type(json_core) :: core
395 character(len=:), allocatable :: string_value
396 character(len=16) :: len_buf
397 integer :: i, n_children
398 integer :: var_type
399
400 call json%info(name, found = found, var_type = var_type, &
401 n_children = n_children)
402 if (.not. found) then
403 call neko_error("Parameter " // name // " missing from the case file")
404 else if (var_type .ne. 3) then
405 call neko_error("Parameter " // name // " is not an array")
406 end if
407
408 if (.not. allocated(value)) then
409 allocate(value(n_children))
410 else if (size(value) .lt. n_children) then
411 deallocate(value)
412 allocate(value(n_children))
413 end if
414
415 call json%get(name, json_val, found)
416 call json%get_core(core)
417
418 do i = 1, n_children
419 call core%get_child(json_val, i, val_ptr, found)
420 call core%get(val_ptr, string_value)
421
422 ! Assigning into the fixed length elements of `value` would silently
423 ! truncate anything longer, so reject it rather than hand the caller
424 ! a string that is not what the case file says.
425 if (len(string_value) .gt. len(value)) then
426 write (len_buf, '(I0)') len(value)
427 call neko_error("An entry of the array parameter " // name // &
428 " is longer than the " // trim(len_buf) // &
429 " characters available for it")
430 end if
431
432 if (len(string_value) .gt. 0) then
433 value(i) = string_value
434 else if (present(filler)) then
435 value(i) = filler
436 end if
437 end do
438
439 end subroutine json_get_string_array
440
442 subroutine json_get_subdict(json, key, output)
443 type(json_file), intent(inout) :: json
444 character(len=*), intent(in) :: key
445 type(json_file), intent(inout) :: output
446
447 type(json_value), pointer :: ptr
448 type(json_core) :: core
449 logical :: found
450 character(len=:), allocatable :: buffer
451
452 call json%get_core(core)
453 call json%get(key, ptr, found)
454
455 if (.not. found) then
456 call neko_error("Parameter " // &
457 trim(key) // " missing from the case file")
458 end if
459
460 call core%print_to_string(ptr, buffer)
461 call output%destroy()
462 call output%initialize(strict_type_checking = .true.)
463 call output%load_from_string(buffer)
464
465 end subroutine json_get_subdict
466
469 subroutine json_get_subdict_or_empty(json, key, output)
470 type(json_file), intent(inout) :: json
471 character(len=*), intent(in) :: key
472 type(json_file), intent(inout) :: output
473
474 type(json_value), pointer :: ptr
475 type(json_core) :: core
476 logical :: found
477 character(len=:), allocatable :: buffer
478
479 ! Initialize empty object to return
480 call output%destroy()
481 call output%initialize(strict_type_checking = .true.)
482
483 call json%get_core(core)
484 call json%get(key, ptr, found)
485
486 ! Load the contents if found, otherwise the object stays empty.
487 if (found) then
488 call core%print_to_string(ptr, buffer)
489 call output%load_from_string(buffer)
490 end if
491
492 end subroutine json_get_subdict_or_empty
493
499 subroutine json_get_or_default_real(json, name, value, default)
500 type(json_file), intent(inout) :: json
501 character(len=*), intent(in) :: name
502 real(kind=sp), intent(out) :: value
503 real(kind=sp), intent(in) :: default
504 logical :: found
505 integer :: var_type
506
507 call json%info(name, found = found, var_type = var_type)
508
509 if (found .and. (var_type .ne. 6)) then
510 call neko_error("Parameter " // name // " present, but is not a real")
511 end if
512
513 call json%get(name, value, found)
514
515 if ((.not. found) .and. (.not. json_no_defaults)) then
516 value = default
517 call json%add(name, value)
518 else if (.not. found) then
519 call neko_error("Parameter " // name // " missing from the case file")
520 end if
521 end subroutine json_get_or_default_real
522
529 subroutine json_get_or_default_double(json, name, value, default)
530 type(json_file), intent(inout) :: json
531 character(len=*), intent(in) :: name
532 real(kind=dp), intent(out) :: value
533 real(kind=dp), intent(in) :: default
534 logical :: found
535 integer :: var_type
536
537 call json%info(name, found = found, var_type = var_type)
538
539 if (found .and. (var_type .ne. 6)) then
540 call neko_error("Parameter " // name // " present, but is not a real")
541 end if
542
543 call json%get(name, value, found)
544
545 if ((.not. found) .and. (.not. json_no_defaults)) then
546 value = default
547 call json%add(name, value)
548 else if (.not. found) then
549 call neko_error("Parameter " // name // " missing from the case file")
550 end if
551 end subroutine json_get_or_default_double
552
558 subroutine json_get_or_default_integer(json, name, value, default)
559 type(json_file), intent(inout) :: json
560 character(len=*), intent(in) :: name
561 integer, intent(out) :: value
562 integer, intent(in) :: default
563 logical :: found
564 integer :: var_type
565
566 call json%info(name, found = found, var_type = var_type)
567
568 if (found .and. (var_type .ne. 5)) then
569 call neko_error("Parameter " // name // " present, but " // &
570 "is not an integer")
571 end if
572
573 call json%get(name, value, found)
574
575 if ((.not. found) .and. (.not. json_no_defaults)) then
576 value = default
577 call json%add(name, value)
578 else if (.not. found) then
579 call neko_error("Parameter " // name // " missing from the case file")
580 end if
581 end subroutine json_get_or_default_integer
582
588 subroutine json_get_or_default_logical(json, name, value, default)
589 type(json_file), intent(inout) :: json
590 character(len=*), intent(in) :: name
591 logical, intent(out) :: value
592 logical, intent(in) :: default
593 logical :: found
594 integer :: var_type
595
596 call json%info(name, found = found, var_type = var_type)
597
598 if ((found) .and. (var_type .ne. 4)) then
599 call neko_error("Parameter " // name // " present, but is not a logical")
600 end if
601
602 call json%get(name, value, found)
603
604 if ((.not. found) .and. (.not. json_no_defaults)) then
605 value = default
606 call json%add(name, value)
607 else if (.not. found) then
608 call neko_error("Parameter " // name // " missing from the case file")
609 end if
610 end subroutine json_get_or_default_logical
611
617 subroutine json_get_or_default_string(json, name, value, default)
618 type(json_file), intent(inout) :: json
619 character(len=*), intent(in) :: name
620 character(len=:), allocatable, intent(out) :: value
621 character(len=*), intent(in) :: default
622 logical :: found
623 integer :: var_type
624
625 call json%info(name, found = found, var_type = var_type)
626
627 if (found .and. (var_type .ne. 7)) then
628 call neko_error("Parameter " // name // &
629 " present, but is not a string")
630 end if
631
632 call json%get(name, value, found)
633
634 if ((.not. found) .and. (.not. json_no_defaults)) then
635 value = default
636 call json%add(name, value)
637 else if (.not. found) then
638 call neko_error("Parameter " // name // " missing from the case file")
639 end if
640 end subroutine json_get_or_default_string
641
647 subroutine json_extract_item_from_array(core, array, i, item)
648 type(json_core), intent(inout) :: core
649 type(json_value), pointer, intent(in) :: array
650 integer, intent(in) :: i
651 type(json_file), intent(inout) :: item
652 type(json_value), pointer :: ptr
653 logical :: found
654 character(len=:), allocatable :: buffer
655
656 call core%get_child(array, i, ptr, found)
657 call core%print_to_string(ptr, buffer)
658 call item%destroy()
659 call item%initialize(strict_type_checking = .true.)
660 call item%load_from_string(buffer)
661
662 end subroutine json_extract_item_from_array
663
669 subroutine json_extract_item_from_name(json, name, i, item)
670 type(json_file), intent(inout) :: json
671 character(len=*), intent(in) :: name
672 integer, intent(in) :: i
673 type(json_file), intent(out) :: item
674
675 type(json_core) :: core
676 type(json_value), pointer :: array
677 type(json_value), pointer :: ptr
678 logical :: found
679 character(len=:), allocatable :: buffer
680
681 call json%get_core(core)
682 call json%get(name, array, found)
683
684 if (.not. found) then
685 call neko_error("Parameter " // name // " missing from the case file")
686 end if
687
688 call core%get_child(array, i, ptr, found)
689 call core%print_to_string(ptr, buffer)
690 call item%destroy()
691 call item%initialize(strict_type_checking = .true.)
692 call item%load_from_string(buffer)
693
694 end subroutine json_extract_item_from_name
695
700 subroutine check_expected_size(name, actual_size, expected_size)
701 character(len=*), intent(in) :: name
702 integer, intent(in) :: actual_size, expected_size
703 character(len=32) :: str_actual, str_expected
704
705 if (actual_size /= expected_size) then
706 write(str_actual, '(I0)') actual_size
707 write(str_expected, '(I0)') expected_size
708 call neko_error("Parameter '" // trim(name) // &
709 "' has incorrect size: got " // &
710 trim(str_actual) // ", but expected " // trim(str_expected))
711 end if
712 end subroutine check_expected_size
713
714end module json_utils
Retrieves a parameter by name or assigns a provided default value. In the latter case also adds the m...
Retrieves a parameter by name or throws an error.
Generic buffer that is extended with buffers of varying rank.
Definition buffer.F90:34
Utilities for retrieving parameters from the case files.
subroutine json_get_integer_array(json, name, value, expected_size)
Retrieves a integer array parameter by name or throws an error.
subroutine json_extract_item_from_name(json, name, i, item)
Extract ith item from a JSON array as a separate JSON object.
subroutine json_get_real_array(json, name, value, expected_size)
Retrieves a real array parameter by name or throws an error.
subroutine json_get_logical(json, name, value)
Retrieves a logical parameter by name or throws an error.
subroutine json_get_or_default_string(json, name, value, default)
Retrieves a string parameter by name or assigns a provided default value. In the latter case also add...
subroutine json_get_double_array(json, name, value, expected_size)
Retrieves a double precision array parameter by name or throws an error.
subroutine json_get_subdict(json, key, output)
Extract a sub-object from a json object.
subroutine json_extract_item_from_array(core, array, i, item)
Extract ith item from a JSON array as a separate JSON object.
subroutine json_get_string(json, name, value)
Retrieves a string parameter by name or throws an error.
subroutine json_get_or_default_real(json, name, value, default)
Retrieves a real parameter by name or assigns a provided default value. In the latter case also adds ...
subroutine json_get_or_default_double(json, name, value, default)
Retrieves a double precision parameter by name or assigns a provided default value....
subroutine json_get_or_default_logical(json, name, value, default)
Retrieves a logical parameter by name or assigns a provided default value. In the latter case also ad...
subroutine json_get_or_default_integer(json, name, value, default)
Retrieves an integer parameter by name or assigns a provided default value. In the latter case also a...
subroutine json_get_double(json, name, value)
Retrieves a double precision real parameter by name or throws an error.
subroutine, public json_get_subdict_or_empty(json, key, output)
Extract a sub-object from a json object and returns an empty object if the key is missing.
subroutine json_get_string_array(json, name, value, filler)
Retrieves a string array parameter by name or throws an error.
subroutine json_get_real(json, name, value)
Retrieves a real parameter by name or throws an error.
logical, public json_no_defaults
If true, the json_get_or_default routines will not add missing parameters.
subroutine json_get_integer(json, name, value)
Retrieves an integer parameter by name or throws an error.
subroutine json_get_logical_array(json, name, value, expected_size)
Retrieves a logical array parameter by name or throws an error.
integer, parameter, public dp
Definition num_types.f90:10
integer, parameter, public sp
Definition num_types.f90:8
Defines an output.
Definition output.f90:34
Utilities.
Definition utils.f90:35