63#define NUM_STATE_VAR_ this%condensed_data_int(1)
64#define NUM_INT_PROP_ 1
65#define NUM_REAL_PROP_ 0
66#define SPEC_TYPE_(x) this%condensed_data_int(NUM_INT_PROP_+x)
67#define MW_(x) this%condensed_data_real(NUM_REAL_PROP_+x)
68#define DENSITY_(x) this%condensed_data_real(NUM_REAL_PROP_+NUM_STATE_VAR_+x)
81 character(len=:),
allocatable :: phase_name
83 integer(kind=i_kind) :: num_spec = 0
88 type(
string_t),
pointer :: spec_name(:) => null()
100 real(kind=
dp),
allocatable,
public :: condensed_data_real(:)
105 integer(kind=i_kind),
allocatable,
public :: condensed_data_int(:)
150 procedure :: constructor
173 character(len=*),
intent(in),
optional :: phase_name
175 integer(kind=i_kind),
intent(in),
optional :: init_size
179 if (
present(init_size)) alloc_size = init_size
181 if (
present(phase_name))
then
182 new_obj%phase_name = phase_name
184 new_obj%phase_name =
""
186 allocate(new_obj%spec_name(alloc_size))
233 subroutine load(this, json, j_obj)
238 type(json_core),
pointer,
intent(in) :: json
240 type(json_value),
pointer,
intent(in) :: j_obj
242 type(json_value),
pointer :: child, next, species, species_child
243 type(json_value),
pointer :: species_obj
244 character(kind=json_ck, len=:),
allocatable :: key, unicode_str_val
245 character(kind=json_ck, len=:),
allocatable :: species_name
246 integer(kind=i_kind) :: var_type, num_spec, i_spec
248 character(len=:),
allocatable :: str_val
250 type(
property_t),
pointer :: spec_property_set
258 call json%get_child(j_obj, child)
260 do while (
associated(child))
261 call json%info(child, name=key, var_type=var_type)
263 if (key.eq.
"name")
then
264 if (var_type.ne.json_string)
call die_msg(429142134, &
265 "Received non-string aerosol phase name.")
266 call json%get(child, unicode_str_val)
267 this%phase_name = unicode_str_val
269 else if (key.eq.
"species")
then
270 if (var_type.ne.json_array)
call die_msg(293312378, &
271 "Received non-array list of aerosol phase species: "//&
273 call json%get_child(child, species)
274 do while (
associated(species))
275 num_spec = num_spec + 1
276 call json%info(species, var_type=var_type)
277 if (var_type.eq.json_object)
then
279 call json%get(species,
"name", species_name)
280 call this%add(species_name)
281 else if (var_type.eq.json_string)
then
283 call json%get(species, unicode_str_val)
284 str_val = unicode_str_val
285 call this%add(str_val)
287 call die_msg(391082805,
"Invalid species format: must be object or string.")
289 call json%get_next(species, next)
294 else if (key.ne.
"type")
then
295 call property_set%load(json, child, .false., this%phase_name)
298 call json%get_next(child, next)
303 if (
associated(this%property_set))
then
304 call this%property_set%update(property_set, this%phase_name)
305 deallocate (property_set)
307 this%property_set => property_set
314 allocate(this%spec_property_set(num_spec))
316 call json%get_child(j_obj, child)
317 do while (
associated(child))
318 call json%info(child, name=key, var_type=var_type)
320 if (key.eq.
"species")
then
321 call json%get_child(child, species)
322 do while (
associated(species))
324 allocate(spec_property_set)
325 call json%info(species, var_type=var_type)
326 if (var_type.eq.json_object)
then
327 call json%get_child(species, species_child)
328 do while (
associated(species_child))
329 call json%info(species_child, name=key, var_type=var_type)
331 if (key.ne.
"name".and.key.ne.
"type")
then
332 call spec_property_set%load(json, species_child, .false., this%spec_name(i_spec)%string)
334 call json%get_next(species_child, next)
335 species_child => next
337 this%spec_property_set(i_spec)%val_ => spec_property_set
338 spec_property_set => null()
339 else if (var_type.eq.json_string)
then
341 this%spec_property_set(i_spec)%val_ => spec_property_set
342 spec_property_set => null()
344 deallocate(spec_property_set)
345 call die_msg(195829403,
"Invalid type for Phase species")
347 call json%get_next(species, next)
351 call json%get_next(child, next)
356 subroutine load(this)
361 call warn_msg(236665532,
"No support for input files.")
376 integer(kind=i_kind) :: i_spec, i_spec_phase_type
377 character(len=:),
allocatable :: key_name
380 allocate(this%condensed_data_int(num_int_prop_+this%num_spec))
381 allocate(this%condensed_data_real(num_real_prop_+2*this%num_spec))
384 num_state_var_ = this%num_spec
387 do i_spec = 1, num_state_var_
390 call assert_msg(140971956, chem_spec_data%get_property_set( &
391 this%spec_name(i_spec)%string, spec_props), &
392 "Missing property set for species '"// &
393 this%spec_name(i_spec)%string// &
394 "' in aerosol phase '"//this%phase_name//
"'")
397 call assert_msg(129442398, chem_spec_data%get_type( &
398 this%spec_name(i_spec)%string, spec_type_(i_spec)), &
399 "Missing type for species '"// &
400 this%spec_name(i_spec)%string// &
401 "' in aerosol phase '"//this%phase_name//
"'")
404 call assert_msg(136357145, chem_spec_data%get_phase( &
405 this%spec_name(i_spec)%string, i_spec_phase_type ), &
406 "Error getting phase for species "// &
407 this%spec_name(i_spec)%string)
409 "Trying to add non-aerosol phase species to aerosol phase "// &
410 this%phase_name//
"; species: "//this%spec_name(i_spec)%string)
419 key_name =
"molecular weight [kg mol-1]"
421 spec_props%get_real(key_name, mw_(i_spec)), &
422 "Missing molecular weight for species '"// &
423 this%spec_name(i_spec)%string// &
424 "' in aerosol phase '"//this%phase_name//
"'")
427 key_name =
"density [kg m-3]"
429 spec_props%get_real(key_name, density_(i_spec)), &
430 "Missing density for species '"// &
431 this%spec_name(i_spec)%string// &
432 "' in aerosol phase '"//this%phase_name//
"'")
438 density_(i_spec) = 0.0
445 this%chem_spec_data => chem_spec_data
455 character(len=:),
allocatable :: phase_name
459 phase_name = this%phase_name
466 integer(kind=i_kind) function get_size(this)
result(num_spec)
471 num_spec = this%num_spec
486 do i_spec = 1, this%num_spec
490 num_elem = num_elem + 1
506 property_set => this%property_set
516 class(
property_t),
pointer :: spec_property_set
518 character(len=*),
intent(in) :: spec_name
522 integer(i_kind) :: i_spec
524 i_spec = this%find(spec_name)
525 spec_property_set => this%spec_property_set(i_spec)%val_
535 type(
string_t),
allocatable :: spec_names(:)
539 integer(kind=i_kind) :: i_spec
541 allocate(spec_names(this%num_spec))
542 do i_spec = 1, this%num_spec
543 spec_names(i_spec)%string = this%spec_name(i_spec)%string
554 integer(kind=i_kind) :: spec_type
558 character(len=*),
intent(in) :: spec_name
560 call assert_msg(163269315, this%find(spec_name).gt.0, &
561 "Species '"//spec_name//
"' is not in aerosol phase '"// &
562 this%phase_name//
"'.")
563 call assert(255786656, this%chem_spec_data%get_type(spec_name, spec_type))
576 integer,
intent(in) :: comm
592 character,
intent(inout) :: buffer(:)
594 integer,
intent(inout) :: pos
596 integer,
intent(in) :: comm
599 integer :: prev_position
605 pos - prev_position <= this%pack_size(comm))
618 character,
intent(inout) :: buffer(:)
620 integer,
intent(inout) :: pos
622 integer,
intent(in) :: comm
625 integer :: prev_position
632 pos - prev_position <= this%pack_size(comm))
645 integer(kind=i_kind),
optional :: file_unit
647 integer(kind=i_kind) :: f_unit
648 integer(kind=i_kind) :: i_spec
652 if (
present(file_unit)) f_unit = file_unit
653 write(f_unit,*)
"Aerosol phase: ", this%phase_name
654 write(f_unit,*)
"Number of species: ", this%num_spec
655 write(f_unit,*)
"Species: ["
656 do i_spec = 1, this%num_spec
657 write(*,*) this%spec_name(i_spec)%string
660 call this%property_set%print(f_unit)
661 write(f_unit,*)
"End aerosol phase: ", this%phase_name
672 integer(kind=i_kind) :: i
674 if (
allocated(this%phase_name))
deallocate(this%phase_name)
675 if (
associated(this%spec_name))
deallocate(this%spec_name)
676 if (
associated(this%property_set))
deallocate(this%property_set)
677 if (
allocated(this%condensed_data_real)) &
678 deallocate(this%condensed_data_real)
679 if (
allocated(this%condensed_data_int)) &
680 deallocate(this%condensed_data_int)
682 if (
allocated(this%spec_property_set))
then
683 do i = 1,
size(this%spec_property_set)
684 if (
associated(this%spec_property_set(i)%val_))
then
685 deallocate(this%spec_property_set(i)%val_)
688 deallocate(this%spec_property_set)
701 integer(kind=i_kind) :: i_phase
703 do i_phase = 1,
size(this)
718 integer(kind=i_kind),
intent(in) :: num_spec
721 type(
string_t),
pointer :: new_name(:)
723 if (
size(this%spec_name) .ge. this%num_spec + num_spec)
return
725 allocate(new_name(new_size))
726 new_name(1:this%num_spec) = this%spec_name(1:this%num_spec)
727 deallocate(this%spec_name)
728 this%spec_name => new_name
735 subroutine add(this, spec_name)
740 character(len=*),
intent(in) :: spec_name
742 integer(kind=i_kind) :: i_spec
744 i_spec = this%find(spec_name)
745 if (i_spec.ne.0)
then
746 call warn_msg(980242449,
"Species "//spec_name//&
747 " added more than once to phase "//this%name())
750 call this%ensure_size(1)
751 this%num_spec = this%num_spec + 1
752 this%spec_name(this%num_spec)%string = spec_name
760 integer(kind=i_kind) function find(this, spec_name) &
766 character(len=*),
intent(in) :: spec_name
768 integer(kind=i_kind) :: i_spec
771 do i_spec = 1, this%num_spec
772 if (this%spec_name(i_spec)%string .eq. spec_name)
then
800 if (
associated(this%val))
deallocate(this%val)
812 integer(kind=i_kind) :: i_ptr
814 do i_ptr = 1,
size(this)
Interface for to_string functions.
The abstract aero_phase_data_t structure and associated subroutines.
integer(kind=i_kind), parameter realloc_inc
Reallocation increment.
subroutine finalize_array(this)
Finalize the aerosol phase data.
subroutine bin_unpack(this, buffer, pos, comm)
Unpack the given value from the buffer, advancing position.
class(property_t) function, pointer get_spec_property_set(this, spec_name)
Get the aerosol phase species property set.
integer(kind=i_kind) function get_size(this)
Get the number of species in the phase.
subroutine initialize(this, chem_spec_data)
Initialize the aerosol phase data, validating species names.
class(property_t) function, pointer get_property_set(this)
Get the aerosol phase property set.
character(len=:) function, allocatable get_name(this)
Get the aerosol phase name.
type(string_t) function, dimension(:), allocatable get_species_names(this)
Get an aerosol phase species name.
type(aero_phase_data_t) function, pointer constructor(phase_name, init_size)
Constructor for aero_phase_data_t.
subroutine ptr_finalize_array(this)
Finalize an array of pointers to aerosol phase data.
subroutine bin_pack(this, buffer, pos, comm)
Pack the given value to the buffer, advancing position.
subroutine load(this, json, j_obj)
Load species from an input file.
subroutine add(this, spec_name)
Add a new chemical species to the phase.
integer(kind=i_kind) function num_jac_elem(this)
Get the number of Jacobian row elements needed during solving.
subroutine ensure_size(this, num_spec)
Ensure there is enough room in the species dataset to add a specified number of species.
integer(kind=i_kind) function find(this, spec_name)
Get the index of an aerosol-phase species by name. Return 0 if the species is not found.
subroutine finalize(this)
Finalize the aerosol phase data.
integer(kind=i_kind) function pack_size(this, comm)
Determine the size of a binary required to pack the aerosol representation data.
subroutine ptr_finalize(this)
Finalize a pointer to aerosol phase data.
subroutine do_print(this, file_unit)
Print out the aerosol phase data.
integer(kind=i_kind) function get_species_type(this, spec_name)
Get an aerosol phase species type.
elemental subroutine dereference(this)
Dereference a pointer to aerosol phase data.
The camp_state_t structure and associated subroutines.
The chem_spec_data_t structure and associated subroutines.
integer(kind=i_kind), parameter, public chem_spec_aero_phase
integer(kind=i_kind), parameter, public chem_spec_constant
integer(kind=i_kind), parameter, public chem_spec_variable
integer(kind=i_kind), parameter, public chem_spec_pssa
integer, parameter dp
Kind of a double precision real number.
integer, parameter i_kind
Kind of an integer.
Wrapper functions for MPI.
subroutine camp_mpi_pack_integer_array(buffer, position, val, comm)
Packs the given value into the buffer, advancing position.
subroutine camp_mpi_pack_real_array(buffer, position, val, comm)
Packs the given value into the buffer, advancing position.
subroutine camp_mpi_unpack_integer_array(buffer, position, val, comm)
Unpacks the given value from the buffer, advancing position.
integer function camp_mpi_pack_size_real_array(val, comm)
Determines the number of bytes required to pack the given value.
integer function camp_mpi_pack_size_integer_array(val, comm)
Determines the number of bytes required to pack the given value.
subroutine camp_mpi_unpack_real_array(buffer, position, val, comm)
Unpacks the given value from the buffer, advancing position.
The property_t structure and associated subroutines.
Common utility subroutines.
subroutine assert(code, condition_ok)
Errors unless condition_ok is true.
subroutine die_msg(code, error_msg)
Error immediately.
subroutine assert_msg(code, condition_ok, error_msg)
Errors unless condition_ok is true.
subroutine warn_msg(code, warning_msg, already_warned)
Prints a warning message.
Pointer type for building arrays.
String type for building arrays of string of various size.