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.
29 type property_t
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
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
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 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 !> Finalize a property_t array
674 subroutine finalize_array(this)
675
676 !> Property dataset array
677 type(property_t), dimension(:), intent(inout) :: this
678
679 integer(kind=i_kind) :: i
680
681 do i = 1, size(this)
682 call finalize(this(i))
683 end do
684
685 end subroutine finalize_array
686
687!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
688
689 !> Find a key-value pair by key name. Returns a null pointer if the key name
690 !! is not found.
691 function get(this, key) result(found_pair)
692
693 !> Pointer to property key-value pair
694 type(property_link_t), pointer :: found_pair
695 !> Property dataset
696 class(property_t), intent(in) :: this
697 !> Key name to search for
698 character(len=*), intent(in) :: key
699
700 type(property_link_t), pointer :: curr_link
701
702 found_pair => null()
703 if (.not. associated(this%first_link)) return
704 curr_link => this%first_link
705 do while (associated(curr_link))
706 if (key .eq. curr_link%key()) then
707 found_pair => curr_link
708 return
709 end if
710 curr_link => curr_link%next_link
711 end do
712
713 end function get
714
715!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
716!!
717!! property_link_t functions
718!!
719!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
720
721 !> Constructor for property_link_t
722 function link_constructor(key, val) result(new_obj)
723
724 !> Pointer to new property key-value pair
725 type(property_link_t), pointer :: new_obj
726 !> Key name
727 character(len=*), intent(in) :: key
728 !> New value
729 class(*), intent(in) :: val
730
731 allocate(new_obj)
732 new_obj%key_name = trim(key)
733 new_obj%next_link => null()
734 call new_obj%set_value(val)
735
736 end function link_constructor
737
738!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
739
740 !> Get the key name of a property
741 function key(this)
742
743 !> Key name
744 character(:), allocatable :: key
745 !> Property key-value pair
746 class(property_link_t), intent(in) :: this
747
748 key = this%key_name
749
750 end function key
751
752!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
753
754 !> Set the value of a property key-value pair
755 subroutine set_value(this, val)
756
757 !> Property key-value pair
758 class(property_link_t), intent(inout) :: this
759 !> New value
760 class(*), intent(in) :: val
761
762 type(string_t), pointer :: str_val
763
764 ! determine the value type
765 select type(val)
766
767 ! add integers, reals, logicals, and string_t as-is
768 type is (integer(kind=i_kind))
769 type is (real(kind=dp))
770 type is (logical)
771 type is (string_t)
772
773 ! handle empty sub-sets
774 class is (property_t)
775 if (.not.associated(val%first_link)) then
776 this%val => property_t()
777 return
778 end if
779
780 ! convert character arrays to string_t objects
781 type is (character(len=*))
782 allocate(str_val)
783 str_val%string = val
784 this%val => str_val
785 return
786
787 ! error on unsupported types
788 class default
789 call die_msg(728532218, "Unsupported property type")
790 end select
791
792 allocate(this%val, source=val)
793
794 end subroutine set_value
795
796!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
797
798 !> Get the int value of a property
799 function value_int(this) result(val)
800
801 !> Value
802 integer(kind=i_kind) :: val
803 !> Property key-value pair
804 class(property_link_t), intent(in) :: this
805
806 class(*), pointer :: this_val
807
808 this_val => this%val
809 select type(this_val)
810 type is (integer(kind=i_kind))
811 val = this_val
812 class default
813 call die_msg(509101133, "Property type mismatch for key "//&
814 trim(this%key_name))
815 end select
816
817 end function value_int
818
819!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
820
821 !> Get the real value of a property
822 function value_real(this) result(val)
823
824 !> Value
825 real(kind=dp) :: val
826 !> Property key-value pair
827 class(property_link_t), intent(in) :: this
828
829 class(*), pointer :: this_val
830
831 this_val => this%val
832 select type(this_val)
833 type is (integer(kind=i_kind))
834 val = real(this_val, kind=dp)
835 type is (real(kind=dp))
836 val = this_val
837 class default
838 call die_msg(151463892, "Property type mismatch for key "//&
839 trim(this%key_name))
840 end select
841
842 end function value_real
843
844!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
845
846 !> Get the logical value of a property
847 function value_logical(this) result(val)
848
849 !> Value
850 logical :: val
851 !> Property key-value pair
852 class(property_link_t), intent(in) :: this
853
854 class(*), pointer :: this_val
855
856 this_val => this%val
857 select type(this_val)
858 type is (logical)
859 val = this_val
860 class default
861 call die_msg(371288570, "Property type mismatch for key "//&
862 trim(this%key_name))
863 end select
864
865 end function value_logical
866
867!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
868
869 !> Get the string value of a property
870 function value_string(this) result(val)
871
872 !> Value
873 character(len=:), allocatable :: val
874 !> Property key-value pair
875 class(property_link_t), intent(in) :: this
876
877 class(*), pointer :: this_val
878
879 this_val => this%val
880 select type (this_val)
881 type is (string_t)
882 val = this_val%string
883 class default
884 call die_msg(153505401, "Property type mismatch for key "//&
885 trim(this%key_name))
886 end select
887
888 end function value_string
889
890!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
891
892 !> Get the property_t value of a property
893 function value_property_t(this) result(val)
894
895 !> Value
896 type(property_t), pointer :: val
897 !> Property key-value pair
898 class(property_link_t), intent(in) :: this
899
900 class(*), pointer :: this_val
901
902 this_val => this%val
903 select type(this_val)
904 type is (property_t)
905 val => this_val
906 class default
907 call die_msg(641781966, "Property type mismatch for key "//&
908 trim(this%key_name))
909 end select
910
911 end function value_property_t
912
913!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
914
915 !> Print the contents of a property key-value pair
916 recursive subroutine link_do_print(this, suffix, file_unit)
917
918 !> Property key-value pair
919 class(property_link_t), intent(in) :: this
920 !> Text to append to the end of the line
921 character(len=*), intent(in) :: suffix
922 !> File unit for output
923 integer(kind=i_kind), optional, intent(in) :: file_unit
924
925 class(*), pointer :: val
926 integer(kind=i_kind) :: f_unit
927
928 f_unit = 6
929
930 if (present(file_unit)) f_unit = file_unit
931
932 val => this%val
933 select type(val)
934 type is (integer(kind=i_kind))
935 write(f_unit,*) '"'//this%key_name//'" : '//trim(to_string(val))// &
936 suffix
937 type is (real(kind=dp))
938 write(f_unit,*) '"'//this%key_name//'" : '//trim(to_string(val))// &
939 suffix
940 type is (logical)
941 write(f_unit,*) '"'//this%key_name//'" : '//trim(to_string(val))// &
942 suffix
943 type is (string_t)
944 write(f_unit,*) '"'//this%key_name//'" : "'//val%string//'"'//suffix
945 class is (property_t)
946 write(f_unit,*) '"'//this%key_name//'" : {'
947 call val%print(f_unit)
948 write(f_unit,*) '}'//suffix
949 class default
950 call die_msg(711028956, "Unsupported property type")
951 end select
952
953 end subroutine link_do_print
954
955!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
956
957 !> Finalize the property_link_t variable
958 subroutine link_finalize(this)
959
960 !> Property key-value pair
961 type(property_link_t), intent(inout) :: this
962
963 if (associated(this%val)) deallocate(this%val)
964
965 end subroutine link_finalize
966
967!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
968
969 !> Finalize the property_link_t array
970 subroutine link_finalize_array(this)
971
972 !> Property key-value pair array
973 type(property_link_t), dimension(:), intent(inout) :: this
974
975 integer(kind=i_kind) :: i
976
977 do i = 1, size(this)
978 if (associated(this(i)%val)) deallocate(this(i)%val)
979 end do
980
981 end subroutine link_finalize_array
982
983!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
984
985end 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:723
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:917
character(len=:) function, allocatable value_string(this)
Get the string value of a property.
Definition property.F90:871
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:823
character(:) function, allocatable key(this)
Get the key name of a property.
Definition property.F90:742
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:800
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:692
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
subroutine finalize(this)
Finalize a property_t variable.
Definition property.F90:656
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:756
type(property_t) function, pointer value_property_t(this)
Get the property_t value of a property.
Definition property.F90:894
subroutine link_finalize(this)
Finalize the property_link_t variable.
Definition property.F90:959
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
subroutine link_finalize_array(this)
Finalize the property_link_t array.
Definition property.F90:971
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
subroutine finalize_array(this)
Finalize a property_t array.
Definition property.F90:675
logical function value_logical(this)
Get the logical value of a property.
Definition property.F90:848
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:53