51#define NUM_LAYERS_ this%condensed_data_int(1)
52#define AERO_REP_ID_ this%condensed_data_int(2)
53#define MAX_PARTICLES_ this%condensed_data_int(3)
54#define PARTICLE_STATE_SIZE_ this%condensed_data_int(4)
55#define NUM_INT_PROP_ 4
56#define NUM_REAL_PROP_ 0
57#define NUM_ENV_PARAM_PER_PARTICLE_ 1
58#define LAYER_PHASE_START_(l) this%condensed_data_int(NUM_INT_PROP_+l)
59#define LAYER_PHASE_END_(l) this%condensed_data_int(NUM_INT_PROP_+NUM_LAYERS_+l)
60#define TOTAL_NUM_PHASES_ (LAYER_PHASE_END_(NUM_LAYERS_))
61#define NUM_PHASES_(l) (LAYER_PHASE_END_(l)-LAYER_PHASE_START_(l)+1)
62#define PHASE_STATE_ID_(l,p) this%condensed_data_int(NUM_INT_PROP_+2*NUM_LAYERS_+LAYER_PHASE_START_(l)+p-1)
63#define PHASE_MODEL_DATA_ID_(l,p) this%condensed_data_int(NUM_INT_PROP_+2*NUM_LAYERS_+TOTAL_NUM_PHASES_+LAYER_PHASE_START_(l)+p-1)
64#define PHASE_NUM_JAC_ELEM_(l,p) this%condensed_data_int(NUM_INT_PROP_+2*NUM_LAYERS_+2*TOTAL_NUM_PHASES_+LAYER_PHASE_START_(l)+p-1)
79 type(
string_t),
allocatable,
private :: unique_names_(:)
81 type(
string_t),
allocatable,
private :: layer_names_(:)
83 integer(kind=i_kind) :: state_id_start = -99999
151 procedure :: constructor
159 logical :: is_malloced = .false.
161 integer(kind=i_kind) :: aero_rep_unique_id = 0
182 result(update_data)
bind (c)
185 type(c_ptr) :: update_data
190 update_data, aero_rep_unique_id, particle_id, number_conc) &
194 type(c_ptr),
value :: update_data
196 integer(kind=c_int),
value :: aero_rep_unique_id
198 integer(kind=c_int),
value :: particle_id
200 real(kind=c_double),
value :: number_conc
207 type(c_ptr),
value,
intent(in) :: update_data
242 integer(kind=i_kind),
intent(in) :: spec_state_id
245 type(
string_t),
allocatable :: layer_names_unordered(:)
247 type(
string_t),
allocatable :: cover_names_unordered(:)
250 integer(kind=i_kind),
allocatable :: ordered_layer_id(:)
252 character(len=:),
allocatable :: key_name, layer_name, layer_covers, &
256 integer(kind=i_kind) :: i_particle, i_phase, i_layer, i_aero, curr_id
257 integer(kind=i_kind) :: i_cover, j_phase, j_layer, i_map, curr_phase
258 integer(kind=i_kind) :: num_phases, num_int_param, num_float_param, &
263 key_name =
"maximum computational particles"
265 this%property_set%get_int(key_name, num_particles), &
266 "Missing maximum number of computational particles")
271 this%property_set%get_property_t(key_name, layers), &
272 "Missing layers for single-particle aerosol "// &
273 "representation '"//this%rep_name//
"'")
274 call assert_msg(168669831, layers%size() .gt. 0, &
275 "No Layers specified for single-particle layer "// &
276 "aerosol representation '"//this%rep_name//
"'")
279 allocate(phases(layers%size()))
280 allocate(cover_names_unordered(layers%size()))
281 allocate(layer_names_unordered(layers%size()))
286 call layers%iter_reset()
287 do i_layer = 1, layers%size()
290 call assert_msg(303808978, layers%get_property_t(val=layer), &
291 "Invalid structure for layer '"// &
292 layer_names_unordered(i_layer)%string// &
293 "' in single-particle layer representation '"// &
298 call assert_msg(364496472, layer%get_string(key_name, layer_name), &
299 "Missing layer name in single-particle layer aerosol "// &
300 "representation '"//this%rep_name//
"'")
301 layer_names_unordered(i_layer)%string = layer_name
305 call assert_msg(350939595, layer%get_string(key_name, layer_covers), &
306 "Missing cover name in layer'"// &
307 layer_names_unordered(i_layer)%string// &
308 "' in single-particle layer aerosol representation '"// &
310 cover_names_unordered(i_layer)%string = layer_covers
315 layer%get_property_t(key_name, phases(i_layer)%val_), &
316 "Missing phases for layer '"// &
317 layer_names_unordered(i_layer)%string// &
318 "' in single-particle layer aerosol representation '"// &
322 call assert_msg(002679882, phases(i_layer)%val_%size().gt.0, &
323 "No phases specified for layer '"// &
324 layer_names_unordered(i_layer)%string// &
325 "' in single-particle layer aerosol representation '"// &
329 num_phases = num_phases + phases(i_layer)%val_%size()
331 call layers%iter_next()
336 cover_names_unordered)
339 allocate(this%layer_names_(
size(ordered_layer_id)))
340 this%layer_names_(:) = layer_names_unordered(ordered_layer_id(:))
343 num_int_param = num_int_prop_ + 2 * layers%size() + 3 * num_phases
344 num_float_param = num_real_prop_
345 allocate(this%condensed_data_int(num_int_param))
346 allocate(this%condensed_data_real(num_float_param))
347 this%condensed_data_int(:) = int(0, kind=i_kind)
348 this%condensed_data_real(:) = real(0.0, kind=dp)
351 this%num_env_params = num_env_param_per_particle_ * num_particles
354 num_layers_ = layers%size()
355 max_particles_ = num_particles
360 allocate(this%aero_phase(num_phases * num_particles))
361 allocate(this%aero_phase_is_at_surface(num_phases * num_particles))
363 do i_layer = 1,
size(ordered_layer_id)
364 j_layer = ordered_layer_id(i_layer)
367 layer_phase_start_(i_layer) = curr_phase
368 layer_phase_end_(i_layer) = curr_phase + phases(j_layer)%val_%size() - 1
370 curr_phase = curr_phase + phases(j_layer)%val_%size()
376 do i_layer = 1,
size(ordered_layer_id)
377 j_layer = ordered_layer_id(i_layer)
379 call phases(j_layer)%val_%iter_reset()
380 do i_phase = 1, phases(j_layer)%val_%size()
384 phases(j_layer)%val_%get_string(val=phase_name), &
385 "Non-string phase name for layer '"// &
386 layer_names_unordered(j_layer)%string// &
387 "' in single-particle layer aerosol representation '"// &
391 do j_phase = 1,
size(aero_phase_set)
392 if (aero_phase_set(j_phase)%val%name() .eq. phase_name)
then
394 do i_particle = 0, num_particles-1
395 this%aero_phase(i_particle*num_phases + curr_phase) = &
396 aero_phase_set(j_phase)
397 if (i_layer .eq. num_layers_)
then
398 this%aero_phase_is_at_surface(i_particle*num_phases + curr_phase) = &
401 this%aero_phase_is_at_surface(i_particle*num_phases + curr_phase) = &
405 phase_state_id_(i_layer,i_phase) = curr_id
406 phase_model_data_id_(i_layer,i_phase) = j_phase
407 curr_id = curr_id + aero_phase_set(j_phase)%val%size()
408 curr_phase = curr_phase + 1
412 call assert(373124707, found)
414 call phases(j_layer)%val_%iter_next()
423 this%unique_names_ = this%unique_names( )
451 integer(kind=i_kind) :: state_size
455 state_size = max_particles_ * particle_state_size_
469 integer(kind=i_kind) :: state_size
473 state_size = particle_state_size_
496 character(len=*),
optional,
intent(in) :: phase_name
498 integer(kind=i_kind),
optional,
intent(in) :: tracer_type
500 character(len=*),
optional,
intent(in) ::
spec_name
502 logical,
optional,
intent(in) :: phase_is_at_surface
504 integer :: i_particle, i_layer, i_phase, i_spec, j_spec
505 integer :: num_spec, curr_tracer_type
506 type(
string_t),
allocatable :: spec_names(:)
509 if (.not.
present(phase_name) .and. &
510 .not.
present(tracer_type) .and. &
512 allocated(this%unique_names_))
then
519 do i_phase = 1,
size(this%aero_phase)
520 if (
present(phase_name))
then
521 if(phase_name .ne. this%aero_phase(i_phase)%val%name()) cycle
523 if (
present(phase_is_at_surface))
then
524 if (phase_is_at_surface .neqv. &
525 this%aero_phase_is_at_surface(i_phase)) cycle
527 if (
present(
spec_name) .or.
present(tracer_type))
then
528 spec_names = this%aero_phase(i_phase)%val%get_species_names()
529 do j_spec = 1,
size(spec_names)
531 if (
spec_name .ne. spec_names(j_spec)%string) cycle
533 if (
present(tracer_type))
then
535 this%aero_phase(i_phase)%val%get_species_type( &
536 spec_names(j_spec)%string)
537 if (tracer_type .ne. curr_tracer_type) cycle
539 num_spec = num_spec + 1
541 deallocate(spec_names)
543 num_spec = num_spec + this%aero_phase(i_phase)%val%size()
548 num_spec = num_spec / max_particles_
551 do i_layer = 1, num_layers_
552 do i_phase = layer_phase_start_(i_layer), layer_phase_end_(i_layer)
553 if (
present(phase_name))
then
554 if(phase_name .ne. this%aero_phase(i_phase)%val%name()) cycle
556 if (
present(phase_is_at_surface))
then
557 if (phase_is_at_surface .neqv. &
558 this%aero_phase_is_at_surface(i_phase)) cycle
560 spec_names = this%aero_phase(i_phase)%val%get_species_names()
561 do j_spec = 1, this%aero_phase(i_phase)%val%size()
563 if (
spec_name .ne. spec_names(j_spec)%string) cycle
565 if (
present(tracer_type))
then
567 this%aero_phase(i_phase)%val%get_species_type( &
568 spec_names(j_spec)%string)
569 if (tracer_type .ne. curr_tracer_type) cycle
571 do i_particle = 1, max_particles_
572 unique_names((i_particle-1)*num_spec+i_spec)%string =
'P'// &
574 this%layer_names_(i_layer)%string//
"."// &
575 this%aero_phase(i_phase)%val%name()//
"."// &
576 spec_names(j_spec)%string
580 deallocate(spec_names)
604 integer(kind=i_kind) :: spec_id
608 character(len=*),
intent(in) :: unique_name
610 integer(kind=i_kind) :: i_spec
612 spec_id = this%state_id_start
613 do i_spec = 1,
size(this%unique_names_)
614 if (this%unique_names_(i_spec)%string .eq. unique_name)
then
617 spec_id = spec_id + 1
619 call die_msg( 449087541,
"Cannot find species '"//unique_name//
"'" )
630 character(len=:),
allocatable ::
spec_name
634 character(len=*),
intent(in) :: unique_name
636 type(string_t) :: l_unique_name
637 type(string_t),
allocatable :: substrs(:)
639 l_unique_name%string = unique_name
640 substrs = l_unique_name%split(
".")
641 call assert(407537518,
size( substrs ) .eq. 4 )
657 character(len=*),
intent(in) :: phase_name
659 logical,
intent(in),
optional :: is_at_surface
661 integer(kind=i_kind) :: i_phase, i_layer, phase_index
664 if (
present(is_at_surface))
then
665 do i_layer = 1, num_layers_
666 do i_phase = layer_phase_start_(i_layer), layer_phase_end_(i_layer)
667 if (this%aero_phase(i_phase)%val%name() .eq. phase_name)
then
668 if (this%aero_phase_is_at_surface(i_phase) .eqv. is_at_surface)
then
675 do i_layer = 1, num_layers_
676 do i_phase = layer_phase_start_(i_layer), layer_phase_end_(i_layer)
677 if (this%aero_phase(i_phase)%val%name() .eq. phase_name)
then
698 integer(kind=i_kind),
intent(in) :: phase_id
700 integer(kind=i_kind) :: i_phase
702 call assert_msg(927040495, phase_id .ge. 1 .and. &
703 phase_id .le.
size( this%aero_phase ), &
704 "Aerosol phase index out of range. Got "// &
705 trim( integer_to_string( phase_id ) )//
", expected 1:"// &
706 trim( integer_to_string(
size( this%aero_phase ) ) ) )
708 do i_phase = 1, total_num_phases_
710 this%aero_phase(i_phase)%val%num_jac_elem()
735 integer,
optional,
intent(in) :: layer
737 if (
present(layer))
then
738 num_phases = layer_phase_end_(layer) - layer_phase_start_(layer) + 1
740 num_phases = layer_phase_end_(num_layers_) - layer_phase_start_(1) + 1
755 integer,
optional,
intent(in) :: layer
757 integer,
optional,
intent(in) :: phase
759 if (
present(layer) .and.
present(phase))
then
760 if (layer .eq. num_layers_ .and. phase .eq. num_phases_(layer))
then
762 phase_state_id_(layer, phase)
763 else if (phase .eq. num_phases_(layer))
then
765 phase_state_id_(layer, phase)
768 phase_state_id_(layer, phase)
770 else if (
present(layer))
then
771 if (layer .eq. num_layers_)
then
773 phase_state_id_(layer, 1)
776 phase_state_id_(layer, 1)
778 else if (
present(phase))
then
779 call die_msg(917793122,
"Must specify layer if including phase is "// &
780 "state size request")
795 if (
allocated(this%rep_name))
deallocate(this%rep_name)
796 if (
allocated(this%aero_phase))
then
798 call this%aero_phase(:)%dereference()
799 deallocate(this%aero_phase)
801 if (
allocated(this%unique_names_))
deallocate(this%unique_names_)
802 if (
allocated(this%layer_names_))
deallocate(this%layer_names_)
803 if (
associated(this%property_set))
deallocate(this%property_set)
804 if (
allocated(this%condensed_data_real)) &
805 deallocate(this%condensed_data_real)
806 if (
allocated(this%condensed_data_int)) &
807 deallocate(this%condensed_data_int)
819 integer(kind=i_kind) :: i_aero
821 do i_aero = 1,
size(this_array)
840 integer(kind=i_kind),
intent(in) :: aero_rep_type
843 if (aero_rep_id_.eq.-1)
then
847 update_data%aero_rep_unique_id = aero_rep_id_
848 update_data%maximum_computational_particles = &
849 this%maximum_computational_particles( )
850 update_data%aero_rep_type = int(aero_rep_type, kind=c_int)
851 update_data%update_data = &
853 update_data%is_malloced = .true.
863 type(string_t),
intent(in) :: layer_names_unordered(:)
865 type(string_t),
intent(in) :: cover_names_unordered(:)
869 integer(kind=i_kind) :: i_layer, j_layer, i_cover
872 do i_layer = 1,
size(layer_names_unordered)
873 do j_layer = 1,
size(layer_names_unordered)
874 if (i_layer .eq. j_layer) cycle
875 call assert_msg(781626922, layer_names_unordered(i_layer)%string .ne. &
876 layer_names_unordered(j_layer)%string, &
877 "Duplicate layer name in single particle "// &
878 "representation: '"// &
879 trim(layer_names_unordered(i_layer)%string)//
"'")
886 do i_layer = 1,
size(layer_names_unordered)
887 if (cover_names_unordered(i_layer)%string ==
"none")
then
894 do i_layer = 1,
size(layer_names_unordered)
896 .eq. cover_names_unordered(i_layer)%string)
then
915 integer(kind=i_kind),
intent(in) :: particle_id
917 real(kind=dp),
intent(in) :: number_conc
919 call assert_msg(611967802, this%is_malloced, &
920 "Trying to set number of uninitialized update object.")
921 call assert_msg(689085496, particle_id .ge. 1 .and. &
922 particle_id .le. this%maximum_computational_particles, &
923 "Invalid computational particle index: "// &
924 trim(integer_to_string(particle_id)))
926 this%get_data(), this%aero_rep_unique_id, particle_id-1, &
940 integer,
intent(in) :: comm
957 character,
intent(inout) :: buffer(:)
959 integer,
intent(inout) :: pos
961 integer,
intent(in) :: comm
964 integer :: prev_position
969 this%maximum_computational_particles, comm)
971 call assert(411585487, &
972 pos - prev_position <= this%pack_size(comm))
985 character,
intent(inout) :: buffer(:)
987 integer,
intent(inout) :: pos
989 integer,
intent(in) :: comm
992 integer :: prev_position
997 this%maximum_computational_particles, comm)
999 call assert(351557153, &
1000 pos - prev_position <= this%pack_size(comm))
1027 integer(kind=i_kind) :: i_aero
1029 do i_aero = 1,
size(this)
Get the size of the section of the camp_camp_state::camp_state_t::state_var array required for this a...
Initialize the aerosol representation data, validating component data and loading any required inform...
Extending-type binary pack function (Internal use only)
Extending-type binary unpack function (Internal use only)
Extending-type binary pack size (internal use only)
Get the number of Jacobian elements used in calculations of aerosol mass, volume, number,...
Get the number of instances of a specified aerosol phase.
Get the non-unique name of a chemical species by its unique name.
Get a species id on the camp_camp_state::camp_state_t::state_var array by unique name....
Get a list of unique names for each element on the camp_camp_state::camp_state_t::state_var array for...
Free an update data object.
Interface to c aerosol representation functions.
Set a new particle number concentration.
Interface for to_string functions.
The abstract aero_phase_data_t structure and associated subroutines.
subroutine finalize_array(this)
Finalize the aerosol phase data.
type(aero_phase_data_t) function, pointer constructor(phase_name, init_size)
Constructor for aero_phase_data_t.
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.
The abstract aero_rep_data_t structure and associated subroutines.
The aero_rep_single_particle_t type and associated subroutines.
integer(kind=i_kind) function internal_pack_size_number(this, comm)
Determine the size of a binary required to pack the reaction data.
subroutine update_data_init_number(this, update_data, aero_rep_type)
Initialize an update data object.
integer function num_layers(this)
Returns the number of layers.
subroutine update_data_number_finalize_array(this)
Finalize an array of number update data objects.
subroutine internal_bin_unpack_number(this, buffer, pos, comm)
Unpack the given value from the buffer, advancing position.
integer(kind=i_kind) function per_particle_size(this)
Get the number of state variables per-particle.
integer(kind=i_kind), parameter, public update_number_conc
subroutine update_data_number_finalize(this)
Finalize a number update data object.
subroutine update_data_set_number__n_m3(this, particle_id, number_conc)
Set packed update data for particle number (#/m3) for a particular computational particle.
integer function, dimension(:), allocatable, public ordered_layer_ids(layer_names_unordered, cover_names_unordered)
Order layer array from inner most layer to outermost.
subroutine internal_bin_pack_number(this, buffer, pos, comm)
Pack the given value to the buffer, advancing position.
integer function phase_state_size(this, layer, phase)
Returns the number of state variables for a layer and phase.
integer function num_phases(this, layer)
Returns the number of phases in a layer or overall.
integer(kind=i_kind) function maximum_computational_particles(this)
Returns the maximum nunmber of computational particles.
The camp_state_t structure and associated subroutines.
The chem_spec_data_t structure and associated subroutines.
Wrapper functions for MPI.
subroutine camp_mpi_pack_logical(buffer, position, val, comm)
Packs the given value into the buffer, advancing position.
subroutine camp_mpi_unpack_integer(buffer, position, val, comm)
Unpacks the given value from the buffer, advancing position.
subroutine camp_mpi_unpack_logical(buffer, position, val, comm)
Unpacks the given value from the buffer, advancing position.
integer function camp_mpi_pack_size_logical(val, comm)
Determines the number of bytes required to pack the given value.
subroutine camp_mpi_pack_integer(buffer, position, val, comm)
Packs the given value into the buffer, advancing position.
integer function camp_mpi_pack_size_integer(val, comm)
Determines the number of bytes required to pack the given value.
The property_t structure and associated subroutines.
Random number generators.
integer(kind=i_kind) function generate_int_id()
Generate an integer id Ids will be sequential, and can only be generated by the primary process.
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.
character(len=camp_util_convert_string_len) function integer_to_string(val)
Convert an integer to a string format.
Pointer type for building arrays.
Abstract aerosol representation data type.
Single particle aerosol representation.
Single particle update number concentration object.
String type for building arrays of string of various size.