CAMP 1.0.0
Chemistry Across Multiple Phases
property.F90
Go to the documentation of this file.
1! Copyright (C) 2021 Barcelona Supercomputing Center and University of
2! Illinois at Urbana-Champaign
3! SPDX-License-Identifier: MIT
4
5!> \file
6!> The camp_property module.
7
8!> The property_t structure and associated subroutines.
10
11#ifdef CAMP_USE_JSON
12 use json_module
13#endif
14 use camp_constants, only : i_kind, dp
16
17
18 implicit none
19 private
20
21 public :: property_t, property_ptr
22
23 !> Property data
24 !!
25 !! A set of physical properties, sub-model parameters and similar constants
26 !! related to a chemical species, reaction, or other data object. The \c
27 !! property_t type can be used to build a set of data with a \c json -like
28 !! structure.
30 private
31 !> Number of elements
32 integer(kind=i_kind) :: num_elem = 0
33 !> First element in the set
34 type(property_link_t), pointer :: first_link => null()
35 !> Last element in the set
36 type(property_link_t), pointer :: last_link => null()
37 !> Iterator
38 type(property_link_t), pointer :: curr_link => null()
39 contains
40 !> Load input data
41 procedure :: load
42 !> Put a value in the data set
43 procedure :: put
44 !> Get the current key name
45 procedure :: get_key
46 !> Get an integer value
47 procedure :: get_int
48 !> Get a real value
49 procedure :: get_real
50 !> Get a logical value
51 procedure :: get_logical
52 !> Get a string value
53 procedure :: get_string
54 !> Get a sub-set of properties
55 procedure :: get_property_t
56 !> Get the number of key-value pairs
57 procedure :: size => get_size
58 !> Reset the iterator
59 procedure :: iter_reset
60 !> Increment the iterator
61 procedure :: iter_next
62 !> Move property data from one property_t instance to another
63 procedure :: move
64 !> Update this property_t instance with data from another
65 procedure :: update
66 !> Print the contents of a property set
67 procedure :: print => do_print
68 !> Finalize
69 final :: finalize
70
71 !> Private functions
72 !> Find a key-value pair by key name
73 procedure, private :: get
74 end type property_t
75
76 ! Constructor for property_t
77 interface property_t
78 procedure :: constructor
79 end interface property_t
80
81 ! Pointer type for property_t
83 type(property_t), pointer :: val_ => null()
84 end type property_ptr
85
86 !> Property link data
87 !!
88 !! An element of a property data set. Property values can be of any
89 !! primitive type or be a pointer to a sub-set of property data.
90 !! The property_link_t object is for internal use in the camp_property
91 !! module. All interactions with property data should be made using
92 !! property_t objects.
94 private
95 !> Key name
96 character(:), allocatable :: key_name
97 !> Value
98 class(*), pointer :: val => null()
99 !> Next link
100 type(property_link_t), pointer :: next_link => null()
101 contains
102 !> Get the key name
103 procedure :: key
104 !> Set the value
105 procedure :: set_value
106 !> Get the int value
107 procedure :: value_int
108 !> Get the real value
109 procedure :: value_real
110 !> Get the logical value
111 procedure :: value_logical
112 !> Get the string value
113 procedure :: value_string
114 !> Get the property sub-set
115 procedure :: value_property_t
116 !> Print the contents of a property key-value pair
117 procedure :: print => link_do_print
118 !> Finalize
120 end type property_link_t
121
122 ! Constructor for link
123 interface property_link_t
124 procedure link_constructor
125 end interface property_link_t
126
127contains
128
129!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
130
131 !> Constructor for property_t
132 function constructor() result(new_obj)
133
134 !> A new property set
135 type(property_t), pointer :: new_obj
136
137 allocate(new_obj)
138
139 end function constructor
140
141!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
142
143 !> Load a property set from input data
144#ifdef CAMP_USE_JSON
145 recursive subroutine load(this, json, j_obj, as_object, owner_name, &
146 allow_duplicates)
147
148 !> Property dataset
149 class(property_t), intent(inout) :: this
150 !> JSON core
151 type(json_core), pointer, intent(in) :: json
152 !> JSON object
153 type(json_value), pointer, intent(in) :: j_obj
154 !> Set to true if j_obj is a json object to parse, adding all child
155 !! key-value pairs to the data set, or false if j_obj is a single
156 !! key-value pair to add to the data set
157 logical, intent(in) :: as_object
158 !> Name of the owner of the property set. For use in error messages
159 character(len=*), intent(in):: owner_name
160 !> Flag to indicate whether to allow duplicate keys. Defaults to false
161 logical, intent(in), optional :: allow_duplicates
162
163 type(json_value), pointer :: child, next
164 type(property_t), pointer :: sub_prop
165 character(kind=json_ck, len=:), allocatable :: unicode_prop_key
166 character(len=:), allocatable :: prop_key
167 logical :: allow_dup
168
169 character(kind=json_ck, len=:), allocatable :: unicode_val
170 character(len=:), allocatable :: str_val
171 logical(json_lk) :: bool_val
172 real(json_rk) :: real_val
173 integer(json_ik) :: int_val
174
175 integer(json_ik) :: var_type
176
177 allow_dup = .false.
178
179 if (present(allow_duplicates)) allow_dup = allow_duplicates
180
181 ! initialize pointer to next object to parse
182 next => null()
183
184 ! determine whether to add parent or children key-value pairs
185 if (as_object) then
186 call json%get_child(j_obj, child)
187 else
188 child => j_obj
189 end if
190
191 ! loop through set of json objects to add to the property set
192 do while (associated(child))
193
194 ! get the key name and value
195 call json%info(child, name=unicode_prop_key, var_type=var_type)
196 prop_key = unicode_prop_key
197
198 ! add key-value pair of appropriate type
199 select case (var_type)
200
201 ! skip null objects
202 case (json_null)
203
204 ! integer
205 case (json_integer)
206 call json%get(child, int_val)
207 call this%put(prop_key, int(int_val, i_kind), allow_dup, &
208 owner_name)
209
210 ! double
211 case (json_double)
212 call json%get(child, real_val)
213 call this%put(prop_key, real(real_val, dp), allow_dup, &
214 owner_name)
215
216 ! boolean
217 case (json_logical)
218 call json%get(child, bool_val)
219 call this%put(prop_key, logical(bool_val), allow_dup, &
220 owner_name)
221
222 ! string
223 case (json_string)
224 call json%get(child, unicode_val)
225 str_val = unicode_val
226 call this%put(prop_key, str_val, allow_dup, owner_name)
227
228 ! sub-set of key-value pairs
229 case (json_object)
230 sub_prop => property_t()
231 call sub_prop%load(json, child, .true., owner_name, allow_dup)
232 call this%put(prop_key, sub_prop, allow_dup, owner_name)
233 deallocate(sub_prop)
234
235 ! sub-set of values
236 case (json_array)
237 sub_prop => property_t()
238 call sub_prop%load(json, child, .true., owner_name, allow_dup)
239 call this%put(prop_key, sub_prop, allow_dup, owner_name)
240 deallocate(sub_prop)
241
242 ! skip other types
243 case default
244 end select
245
246 ! get the next object to add
247 if (as_object) call json%get_next(child, next)
248 child => next
249
250 end do
251
252#else
253 subroutine load(this)
254
255 !> Property dataset
256 class(property_t), intent(inout) :: this
257
258 call warn_msg(733896496, "No support for input files.")
259#endif
260 end subroutine load
261
262!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
263
264 !> Put an element in the property data set
265 recursive subroutine put(this, key, val, allow_duplicates, owner_name)
266
267 !> Property data set
268 class(property_t), intent(inout) :: this
269 !> New key
270 character(len=*), intent(in) :: key
271 !> New value
272 class(*), intent(in) :: val
273 !> Flag indicating whether to allow duplicate keys
274 logical, intent(in) :: allow_duplicates
275 !> Name of owner of the property set. For use in error messages
276 character(len=*), intent(in) :: owner_name
277
278 type(property_link_t), pointer :: new_link, sub_link
279 type(property_t), allocatable :: sub_prop_set
280 class(*), pointer :: curr_val
281
282 ! if this is an array element, the key will be empty
283 if (len(key).ge.1) then
284
285 ! look for the key in the existing properties if disallowing duplictes
286 if (.not.allow_duplicates) then
287
288 new_link => this%get(key)
289
290 ! do not allow overwrites of existing properties, but allow sub-sets
291 ! of properties to be appended
292 if (associated(new_link)) then
293 curr_val => new_link%val
294 select type (curr_val)
295 class is (property_t)
296 select type (val)
297 class is (property_t)
298 sub_link => val%first_link
299 do while (associated(sub_link))
300 call curr_val%put(sub_link%key_name, sub_link%val, .false., &
301 owner_name)
302 sub_link => sub_link%next_link
303 end do
304 class default
305 call new_link%print("")
306 call die_msg(698012538, "Property type mismatch for "//key// &
307 " in property set of "//owner_name)
308 end select
309 class default
310 call new_link%print("")
311 call die_msg(359604264, "Trying to overwrite property "//key// &
312 " in property set of "//owner_name)
313 end select
314 return
315 end if
316
317 end if
318
319 end if
320
321 ! create a new link. for property_t sub-property sets,
322 ! copy the passed value to a new object
323 select type (val)
324 class is (property_t)
325 allocate(sub_prop_set)
326 sub_link => val%first_link
327 do while (associated(sub_link))
328 call sub_prop_set%put(sub_link%key_name, sub_link%val, &
329 allow_duplicates, owner_name)
330 sub_link => sub_link%next_link
331 end do
332 new_link => property_link_t(key, sub_prop_set)
333 sub_prop_set%first_link => null()
334 sub_prop_set%last_link => null()
335 deallocate(sub_prop_set)
336 class default
337 new_link => property_link_t(key, val)
338 end select
339
340 ! if the key does not exist in the property dataset,
341 ! create a new link to add it.
342 if (.not.associated(this%first_link)) then
343 this%first_link => new_link
344 this%last_link => this%first_link
345 else
346 this%last_link%next_link => new_link
347 this%last_link => new_link
348 end if
349
350 this%num_elem = this%num_elem + 1
351
352 end subroutine put
353
354!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
355
356 !> Get the key name of the element currently pointed to by the iterator.
357 !! Returns true if the iterator points to a key-value pair; false indicates
358 !! the list is empty, the iterator was never reset, or the end of the list
359 !! has been reached. Array elements return true, but have an empty key name.
360 logical function get_key(this, key) result (found)
361
362 !> Property dataset
363 class(property_t), intent(in) :: this
364 !> Key name
365 character(len=:), allocatable, intent(out) :: key
366
367 found = .false.
368 if (.not.associated(this%curr_link)) return
369 key = this%curr_link%key()
370 found = .true.
371
372 end function get_key
373
374!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
375
376 !> Get an integer value. The return value is true if the key-value pair
377 !! was found, and false otherwise. If no key name is specified, the current
378 !! value of the iterator is returned. In this case true indicates a current
379 !! key-value exists; false indicates the list is empty, the iterator was
380 !! never reset, or the end of the list has been reached.
381 logical function get_int(this, key, val) result(found)
382
383 !> Property dataset
384 class(property_t), intent(in) :: this
385 !> Key name to search for
386 character(len=*), intent(in), optional :: key
387 !> Property value
388 integer(kind=i_kind), intent(out) :: val
389
390 type(property_link_t), pointer :: link
391
392 found = .false.
393 if (present(key)) then
394 link => get(this, key)
395 if (.not. associated(link)) return
396 val = link%value_int()
397 else
398 if (.not.associated(this%curr_link)) return
399 val = this%curr_link%value_int()
400 endif
401 found = .true.
402
403 end function get_int
404
405!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
406
407 !> Get a real value. The return value is true if the key-value pair
408 !! was found, and false otherwise. If no key name is specified, the current
409 !! value of the iterator is returned. In this case true indicates a current
410 !! key-value exists; false indicates the list is empty, the iterator was
411 !! never reset, or the end of the list has been reached.
412 logical function get_real(this, key, val) result(found)
413
414 !> Property dataset
415 class(property_t), intent(in) :: this
416 !> Key name to search for
417 character(len=*), intent(in), optional :: key
418 !> Property value
419 real(kind=dp), intent(out) :: val
420
421 type(property_link_t), pointer :: link
422
423 found = .false.
424 if (present(key)) then
425 link => get(this, key)
426 if (.not. associated(link)) return
427 val = link%value_real()
428 else
429 if (.not.associated(this%curr_link)) return
430 val = this%curr_link%value_real()
431 endif
432 found = .true.
433
434 end function get_real
435
436!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
437
438 !> Get a logical value. The return value is true if the key-value pair
439 !! was found, and false otherwise. If no key name is specified, the current
440 !! value of the iterator is returned. In this case true indicates a current
441 !! key-value exists; false indicates the list is empty, the iterator was
442 !! never reset, or the end of the list has been reached.
443 logical function get_logical(this, key, val) result(found)
444
445 !> Property dataset
446 class(property_t), intent(in) :: this
447 !> Key name to search for
448 character(len=*), intent(in), optional :: key
449 !> Property value
450 logical, intent(out) :: val
451
452 type(property_link_t), pointer :: link
453
454 found = .false.
455 if (present(key)) then
456 link => get(this, key)
457 if (.not. associated(link)) return
458 val = link%value_logical()
459 else
460 if (.not.associated(this%curr_link)) return
461 val = this%curr_link%value_logical()
462 endif
463 found = .true.
464
465 end function get_logical
466
467!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
468
469 !> Get a string value. The return value is true if the key-value pair
470 !! was found, and false otherwise. If no key name is specified, the current
471 !! value of the iterator is returned. In this case true indicates a current
472 !! key-value exists; false indicates the list is empty, the iterator was
473 !! never reset, or the end of the list has been reached.
474 logical function get_string(this, key, val) result(found)
475
476 !> Property dataset
477 class(property_t), intent(in) :: this
478 !> Key name to search for
479 character(len=*), intent(in), optional :: key
480 !> Property value
481 character(len=:), allocatable, intent(out) :: val
482
483 type(property_link_t), pointer :: link
484
485 found = .false.
486 if (present(key)) then
487 link => get(this, key)
488 if (.not. associated(link)) return
489 val = link%value_string()
490 else
491 if (.not.associated(this%curr_link)) return
492 val = this%curr_link%value_string()
493 endif
494 found = .true.
495
496 end function get_string
497
498!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
499
500 !> Get a property sub-set. The return value is true if the key-value pair
501 !! was found, and false otherwise. If no key name is specified, the current
502 !! value of the iterator is returned. In this case true indicates a current
503 !! key-value exists; false indicates the list is empty, the iterator was
504 !! never reset, or the end of the list has been reached.
505 logical function get_property_t(this, key, val) result(found)
506
507 !> Property dataset
508 class(property_t), intent(in) :: this
509 !> Key name to search for
510 character(len=*), intent(in), optional :: key
511 !> Property value
512 type(property_t), pointer, intent(out) :: val
513
514 type(property_link_t), pointer :: link
515
516 found = .false.
517 val => null()
518 if (present(key)) then
519 link => get(this, key)
520 if (.not. associated(link)) return
521 val => link%value_property_t()
522 else
523 if (.not. associated(this%curr_link)) return
524 val => this%curr_link%value_property_t()
525 end if
526 found = .true.
527
528 end function get_property_t
529
530!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
531
532 !> Get the number of elements in the property set
533 function get_size(this)
534
535 !> Number of elements in the property set
536 integer(kind=i_kind) :: get_size
537 !> Property dataset
538 class(property_t), intent(in) :: this
539
540 type(property_link_t), pointer :: curr_link
541
542 get_size = 0
543 curr_link => this%first_link
544 do while (associated(curr_link))
545 get_size = get_size + 1
546 curr_link => curr_link%next_link
547 end do
548
549 end function get_size
550
551!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
552
553 !> Initialize the iterator. It will now point to the first property in the
554 !! dataset, or be NULL in the case of an empty property dataset
555 subroutine iter_reset(this)
556
557 !> Property dataset
558 class(property_t), intent(inout) :: this
559
560 this%curr_link => this%first_link
561
562 end subroutine iter_reset
563
564!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
565
566 !> Increment the interator
567 subroutine iter_next(this)
568
569 !> Property dataset
570 class(property_t), intent(inout) :: this
571
572 if (associated(this%curr_link)) then
573 this%curr_link => this%curr_link%next_link
574 else
575 call warn_msg(365476096, "Trying to iterate NULL iterator.")
576 end if
577
578 end subroutine iter_next
579
580!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
581
582 !> Move data from one property_t instance to another
583 elemental subroutine move(this, dest)
584
585 !> Property dataset to move
586 class(property_t), intent(inout) :: this
587 !> Property dataset destination
588 class(property_t), intent(inout) :: dest
589
590 dest%first_link => this%first_link
591 dest%curr_link => this%curr_link
592 dest%last_link => this%last_link
593 dest%num_elem = this%num_elem
594 this%first_link => null()
595 this%curr_link => null()
596 this%last_link => null()
597 this%num_elem = 0
598
599 end subroutine move
600
601!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
602
603 !> Update this property_t instance with data from another instance
604 subroutine update(this, source, owner_name)
605
606 !> Property dataset to update
607 class(property_t), intent(inout) :: this
608 !> Property dataset to update from
609 class(property_t), intent(inout) :: source
610 !> Name of owner of the property set. For use in error messages
611 character(len=*), intent(in) :: owner_name
612
613 type(property_link_t), pointer :: curr_prop
614
615 curr_prop => source%first_link
616 do while (associated(curr_prop))
617 call this%put(curr_prop%key_name, curr_prop%val, .false., owner_name)
618 curr_prop => curr_prop%next_link
619 end do
620
621 end subroutine update
622
623!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
624
625 !> Print the contents of a property set
626 recursive subroutine do_print(this, file_unit)
627
628 !> Property dataset
629 class(property_t), intent(in) :: this
630 !> File unit for output
631 integer(kind=i_kind), optional, intent(in) :: file_unit
632
633 type(property_link_t), pointer :: curr_link
634 integer(kind=i_kind) :: f_unit
635
636 f_unit = 6
637
638 if (present(file_unit)) f_unit = file_unit
639
640 curr_link => this%first_link
641 do while (associated(curr_link))
642 if (associated(curr_link%next_link)) then
643 call curr_link%print(",", f_unit)
644 else
645 call curr_link%print("", f_unit)
646 endif
647 curr_link => curr_link%next_link
648 end do
649
650 end subroutine do_print
651
652!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
653
654 !> Finalize a property_t variable
655 elemental subroutine finalize(this)
656
657 !> Property dataset
658 type(property_t), intent(inout) :: this
659
660 type(property_link_t), pointer :: next
661
662 next => null()
663 do while (associated(this%first_link))
664 next => this%first_link%next_link
665 deallocate(this%first_link)
666 this%first_link => next
667 end do
668
669 end subroutine finalize
670
671!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
672
673 !> Find a key-value pair by key name. Returns a null pointer if the key name
674 !! is not found.
675 function get(this, key) result(found_pair)
676
677 !> Pointer to property key-value pair
678 type(property_link_t), pointer :: found_pair
679 !> Property dataset
680 class(property_t), intent(in) :: this
681 !> Key name to search for
682 character(len=*), intent(in) :: key
683
684 type(property_link_t), pointer :: curr_link
685
686 found_pair => null()
687 if (.not. associated(this%first_link)) return
688 curr_link => this%first_link
689 do while (associated(curr_link))
690 if (key .eq. curr_link%key()) then
691 found_pair => curr_link
692 return
693 end if
694 curr_link => curr_link%next_link
695 end do
696
697 end function get
698
699!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
700!!
701!! property_link_t functions
702!!
703!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
704
705 !> Constructor for property_link_t
706 function link_constructor(key, val) result(new_obj)
707
708 !> Pointer to new property key-value pair
709 type(property_link_t), pointer :: new_obj
710 !> Key name
711 character(len=*), intent(in) :: key
712 !> New value
713 class(*), intent(in) :: val
714
715 allocate(new_obj)
716 new_obj%key_name = trim(key)
717 new_obj%next_link => null()
718 call new_obj%set_value(val)
719
720 end function link_constructor
721
722!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
723
724 !> Get the key name of a property
725 function key(this)
726
727 !> Key name
728 character(:), allocatable :: key
729 !> Property key-value pair
730 class(property_link_t), intent(in) :: this
731
732 key = this%key_name
733
734 end function key
735
736!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
737
738 !> Set the value of a property key-value pair
739 subroutine set_value(this, val)
740
741 !> Property key-value pair
742 class(property_link_t), intent(inout) :: this
743 !> New value
744 class(*), intent(in) :: val
745
746 type(string_t), pointer :: str_val
747
748 ! determine the value type
749 select type(val)
750
751 ! add integers, reals, logicals, and string_t as-is
752 type is (integer(kind=i_kind))
753 type is (real(kind=dp))
754 type is (logical)
755 type is (string_t)
756
757 ! handle empty sub-sets
758 class is (property_t)
759 if (.not.associated(val%first_link)) then
760 this%val => property_t()
761 return
762 end if
763
764 ! convert character arrays to string_t objects
765 type is (character(len=*))
766 allocate(str_val)
767 str_val%string = val
768 this%val => str_val
769 return
770
771 ! error on unsupported types
772 class default
773 call die_msg(728532218, "Unsupported property type")
774 end select
775
776 allocate(this%val, source=val)
777
778 end subroutine set_value
779
780!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
781
782 !> Get the int value of a property
783 function value_int(this) result(val)
784
785 !> Value
786 integer(kind=i_kind) :: val
787 !> Property key-value pair
788 class(property_link_t), intent(in) :: this
789
790 class(*), pointer :: this_val
791
792 this_val => this%val
793 select type(this_val)
794 type is (integer(kind=i_kind))
795 val = this_val
796 class default
797 call die_msg(509101133, "Property type mismatch for key "//&
798 trim(this%key_name))
799 end select
800
801 end function value_int
802
803!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
804
805 !> Get the real value of a property
806 function value_real(this) result(val)
807
808 !> Value
809 real(kind=dp) :: val
810 !> Property key-value pair
811 class(property_link_t), intent(in) :: this
812
813 class(*), pointer :: this_val
814
815 this_val => this%val
816 select type(this_val)
817 type is (integer(kind=i_kind))
818 val = real(this_val, kind=dp)
819 type is (real(kind=dp))
820 val = this_val
821 class default
822 call die_msg(151463892, "Property type mismatch for key "//&
823 trim(this%key_name))
824 end select
825
826 end function value_real
827
828!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
829
830 !> Get the logical value of a property
831 function value_logical(this) result(val)
832
833 !> Value
834 logical :: val
835 !> Property key-value pair
836 class(property_link_t), intent(in) :: this
837
838 class(*), pointer :: this_val
839
840 this_val => this%val
841 select type(this_val)
842 type is (logical)
843 val = this_val
844 class default
845 call die_msg(371288570, "Property type mismatch for key "//&
846 trim(this%key_name))
847 end select
848
849 end function value_logical
850
851!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
852
853 !> Get the string value of a property
854 function value_string(this) result(val)
855
856 !> Value
857 character(len=:), allocatable :: val
858 !> Property key-value pair
859 class(property_link_t), intent(in) :: this
860
861 class(*), pointer :: this_val
862
863 this_val => this%val
864 select type (this_val)
865 type is (string_t)
866 val = this_val%string
867 class default
868 call die_msg(153505401, "Property type mismatch for key "//&
869 trim(this%key_name))
870 end select
871
872 end function value_string
873
874!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
875
876 !> Get the property_t value of a property
877 function value_property_t(this) result(val)
878
879 !> Value
880 type(property_t), pointer :: val
881 !> Property key-value pair
882 class(property_link_t), intent(in) :: this
883
884 class(*), pointer :: this_val
885
886 this_val => this%val
887 select type(this_val)
888 type is (property_t)
889 val => this_val
890 class default
891 call die_msg(641781966, "Property type mismatch for key "//&
892 trim(this%key_name))
893 end select
894
895 end function value_property_t
896
897!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
898
899 !> Print the contents of a property key-value pair
900 recursive subroutine link_do_print(this, suffix, file_unit)
901
902 !> Property key-value pair
903 class(property_link_t), intent(in) :: this
904 !> Text to append to the end of the line
905 character(len=*), intent(in) :: suffix
906 !> File unit for output
907 integer(kind=i_kind), optional, intent(in) :: file_unit
908
909 class(*), pointer :: val
910 integer(kind=i_kind) :: f_unit
911
912 f_unit = 6
913
914 if (present(file_unit)) f_unit = file_unit
915
916 val => this%val
917 select type(val)
918 type is (integer(kind=i_kind))
919 write(f_unit,*) '"'//this%key_name//'" : '//trim(to_string(val))// &
920 suffix
921 type is (real(kind=dp))
922 write(f_unit,*) '"'//this%key_name//'" : '//trim(to_string(val))// &
923 suffix
924 type is (logical)
925 write(f_unit,*) '"'//this%key_name//'" : '//trim(to_string(val))// &
926 suffix
927 type is (string_t)
928 write(f_unit,*) '"'//this%key_name//'" : "'//val%string//'"'//suffix
929 class is (property_t)
930 write(f_unit,*) '"'//this%key_name//'" : {'
931 call val%print(f_unit)
932 write(f_unit,*) '}'//suffix
933 class default
934 call die_msg(711028956, "Unsupported property type")
935 end select
936
937 end subroutine link_do_print
938
939!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
940
941 !> Finalize the property_link_t variable
942 elemental subroutine link_finalize(this)
943
944 !> Property key-value pair
945 type(property_link_t), intent(inout) :: this
946
947 if (associated(this%val)) deallocate(this%val)
948
949 end subroutine link_finalize
950
951!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
952
953end module camp_property
Interface for to_string functions.
Definition util.F90:32
Physical constants.
Definition constants.F90:9
integer, parameter dp
Kind of a double precision real number.
Definition constants.F90:16
integer, parameter i_kind
Kind of an integer.
Definition constants.F90:21
The property_t structure and associated subroutines.
Definition property.F90:9
logical function get_logical(this, key, val)
Get a logical value. The return value is true if the key-value pair was found, and false otherwise....
Definition property.F90:444
logical function get_string(this, key, val)
Get a string value. The return value is true if the key-value pair was found, and false otherwise....
Definition property.F90:475
recursive subroutine do_print(this, file_unit)
Print the contents of a property set.
Definition property.F90:627
type(property_link_t) function, pointer link_constructor(key, val)
Constructor for property_link_t.
Definition property.F90:707
subroutine update(this, source, owner_name)
Update this property_t instance with data from another instance.
Definition property.F90:605
recursive subroutine link_do_print(this, suffix, file_unit)
Print the contents of a property key-value pair.
Definition property.F90:901
character(len=:) function, allocatable value_string(this)
Get the string value of a property.
Definition property.F90:855
recursive subroutine load(this, json, j_obj, as_object, owner_name, allow_duplicates)
Load a property set from input data.
Definition property.F90:147
real(kind=dp) function value_real(this)
Get the real value of a property.
Definition property.F90:807
character(:) function, allocatable key(this)
Get the key name of a property.
Definition property.F90:726
logical function get_key(this, key)
Get the key name of the element currently pointed to by the iterator. Returns true if the iterator po...
Definition property.F90:361
integer(kind=i_kind) function value_int(this)
Get the int value of a property.
Definition property.F90:784
type(property_link_t) function, pointer get(this, key)
Find a key-value pair by key name. Returns a null pointer if the key name is not found.
Definition property.F90:676
recursive subroutine put(this, key, val, allow_duplicates, owner_name)
Put an element in the property data set.
Definition property.F90:266
integer(kind=i_kind) function get_size(this)
Get the number of elements in the property set.
Definition property.F90:534
type(property_t) function, pointer constructor()
Constructor for property_t.
Definition property.F90:133
elemental subroutine link_finalize(this)
Finalize the property_link_t variable.
Definition property.F90:943
logical function get_real(this, key, val)
Get a real value. The return value is true if the key-value pair was found, and false otherwise....
Definition property.F90:413
subroutine set_value(this, val)
Set the value of a property key-value pair.
Definition property.F90:740
type(property_t) function, pointer value_property_t(this)
Get the property_t value of a property.
Definition property.F90:878
logical function get_property_t(this, key, val)
Get a property sub-set. The return value is true if the key-value pair was found, and false otherwise...
Definition property.F90:506
elemental subroutine finalize(this)
Finalize a property_t variable.
Definition property.F90:656
subroutine iter_reset(this)
Initialize the iterator. It will now point to the first property in the dataset, or be NULL in the ca...
Definition property.F90:556
elemental subroutine move(this, dest)
Move data from one property_t instance to another.
Definition property.F90:584
subroutine iter_next(this)
Increment the interator.
Definition property.F90:568
logical function value_logical(this)
Get the logical value of a property.
Definition property.F90:832
logical function get_int(this, key, val)
Get an integer value. The return value is true if the key-value pair was found, and false otherwise....
Definition property.F90:382
Common utility subroutines.
Definition util.F90:9
subroutine die_msg(code, error_msg)
Error immediately.
Definition util.F90:196
subroutine warn_msg(code, warning_msg, already_warned)
Prints a warning message.
Definition util.F90:90
String type for building arrays of string of various size.
Definition util.F90:38