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
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)
380 call phases(j_layer)%val_%iter_reset()
381 do i_phase = 1, phases(j_layer)%val_%size()
385 phases(j_layer)%val_%get_string(val=phase_name), &
386 "Non-string phase name for layer '"// &
387 layer_names_unordered(j_layer)%string// &
388 "' in single-particle layer aerosol representation '"// &
393 do j_phase = 1,
size(aero_phase_set)
394 if (aero_phase_set(j_phase)%val%name() .eq. phase_name)
then
396 do i_particle = 0, num_particles-1
397 this%aero_phase(i_particle*num_phases + curr_phase) = &
398 aero_phase_set(j_phase)
399 if (i_layer .eq. num_layers_)
then
400 this%aero_phase_is_at_surface(i_particle*num_phases + curr_phase) = &
403 this%aero_phase_is_at_surface(i_particle*num_phases + curr_phase) = &
407 phase_state_id_(i_layer,i_phase) = curr_id
408 phase_model_data_id_(i_layer,i_phase) = j_phase
409 curr_id = curr_id + aero_phase_set(j_phase)%val%size()
410 curr_phase = curr_phase + 1
415 call phases(j_layer)%val_%iter_next()
424 this%unique_names_ = this%unique_names( )
452 integer(kind=i_kind) :: state_size
456 state_size = max_particles_ * particle_state_size_
470 integer(kind=i_kind) :: state_size
474 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 integer :: i_particle, i_layer, i_phase, i_spec, j_spec
503 integer :: num_spec, curr_tracer_type
504 type(
string_t),
allocatable :: spec_names(:)
507 if (.not.
present(phase_name) .and. &
508 .not.
present(tracer_type) .and. &
510 allocated(this%unique_names_))
then
517 do i_phase = 1,
size(this%aero_phase)
518 if (
present(phase_name))
then
519 if(phase_name .ne. this%aero_phase(i_phase)%val%name()) cycle
521 if (
present(
spec_name) .or.
present(tracer_type))
then
522 spec_names = this%aero_phase(i_phase)%val%get_species_names()
523 do j_spec = 1,
size(spec_names)
525 if (
spec_name .ne. spec_names(j_spec)%string) cycle
527 if (
present(tracer_type))
then
529 this%aero_phase(i_phase)%val%get_species_type( &
530 spec_names(j_spec)%string)
531 if (tracer_type .ne. curr_tracer_type) cycle
533 num_spec = num_spec + 1
535 deallocate(spec_names)
537 num_spec = num_spec + this%aero_phase(i_phase)%val%size()
542 num_spec = num_spec / max_particles_
545 do i_layer = 1, num_layers_
546 do i_phase = layer_phase_start_(i_layer), layer_phase_end_(i_layer)
547 if (
present(phase_name))
then
548 if(phase_name .ne. this%aero_phase(i_phase)%val%name()) cycle
550 spec_names = this%aero_phase(i_phase)%val%get_species_names()
551 do j_spec = 1, this%aero_phase(i_phase)%val%size()
553 if (
spec_name .ne. spec_names(j_spec)%string) cycle
555 if (
present(tracer_type))
then
557 this%aero_phase(i_phase)%val%get_species_type( &
558 spec_names(j_spec)%string)
559 if (tracer_type .ne. curr_tracer_type) cycle
561 do i_particle = 1, max_particles_
562 unique_names((i_particle-1)*num_spec+i_spec)%string =
'P'// &
564 this%layer_names_(i_layer)%string//
"."// &
565 this%aero_phase(i_phase)%val%name()//
"."// &
566 spec_names(j_spec)%string
570 deallocate(spec_names)
594 integer(kind=i_kind) :: spec_id
598 character(len=*),
intent(in) :: unique_name
600 integer(kind=i_kind) :: i_spec
602 spec_id = this%state_id_start
603 do i_spec = 1,
size(this%unique_names_)
604 if (this%unique_names_(i_spec)%string .eq. unique_name)
then
607 spec_id = spec_id + 1
609 call die_msg( 449087541,
"Cannot find species '"//unique_name//
"'" )
620 character(len=:),
allocatable ::
spec_name
624 character(len=*),
intent(in) :: unique_name
626 type(string_t) :: l_unique_name
627 type(string_t),
allocatable :: substrs(:)
629 l_unique_name%string = unique_name
630 substrs = l_unique_name%split(
".")
631 call assert(407537518,
size( substrs ) .eq. 4 )
646 character(len=*),
intent(in) :: phase_name
648 integer(kind=i_kind) :: i_phase, i_layer, phase_index
652 do i_layer = 1, num_layers_
653 do i_phase = layer_phase_start_(i_layer), layer_phase_end_(i_layer)
654 if (this%aero_phase(i_phase)%val%name() .eq. phase_name)
then
655 phase_index = phase_index + 1
674 integer(kind=i_kind),
intent(in) :: phase_id
676 integer(kind=i_kind) :: i_phase
678 call assert_msg(927040495, phase_id .ge. 1 .and. &
679 phase_id .le.
size( this%aero_phase ), &
680 "Aerosol phase index out of range. Got "// &
681 trim( integer_to_string( phase_id ) )//
", expected 1:"// &
682 trim( integer_to_string(
size( this%aero_phase ) ) ) )
684 do i_phase = 1, total_num_phases_
686 this%aero_phase(i_phase)%val%num_jac_elem()
711 integer,
optional,
intent(in) :: layer
713 if (
present(layer))
then
714 num_phases = layer_phase_end_(layer) - layer_phase_start_(layer) + 1
716 num_phases = layer_phase_end_(num_layers_) - layer_phase_start_(1) + 1
731 integer,
optional,
intent(in) :: layer
733 integer,
optional,
intent(in) :: phase
735 if (
present(layer) .and.
present(phase))
then
736 if (layer .eq. num_layers_ .and. phase .eq. num_phases_(layer))
then
738 phase_state_id_(layer, phase)
739 else if (phase .eq. num_phases_(layer))
then
741 phase_state_id_(layer, phase)
744 phase_state_id_(layer, phase)
746 else if (
present(layer))
then
747 if (layer .eq. num_layers_)
then
749 phase_state_id_(layer, 1)
752 phase_state_id_(layer, 1)
754 else if (
present(phase))
then
755 call die_msg(917793122,
"Must specify layer if including phase is "// &
756 "state size request")
771 if (
allocated(this%rep_name))
deallocate(this%rep_name)
772 if (
allocated(this%aero_phase))
then
774 call this%aero_phase(:)%dereference()
775 deallocate(this%aero_phase)
777 if (
allocated(this%unique_names_))
deallocate(this%unique_names_)
778 if (
allocated(this%layer_names_))
deallocate(this%layer_names_)
779 if (
associated(this%property_set))
deallocate(this%property_set)
780 if (
allocated(this%condensed_data_real)) &
781 deallocate(this%condensed_data_real)
782 if (
allocated(this%condensed_data_int)) &
783 deallocate(this%condensed_data_int)
800 integer(kind=i_kind),
intent(in) :: aero_rep_type
803 if (aero_rep_id_.eq.-1)
then
807 update_data%aero_rep_unique_id = aero_rep_id_
808 update_data%maximum_computational_particles = &
809 this%maximum_computational_particles( )
810 update_data%aero_rep_type = int(aero_rep_type, kind=c_int)
811 update_data%update_data = &
813 update_data%is_malloced = .true.
823 type(string_t),
intent(in) :: layer_names_unordered(:)
825 type(string_t),
intent(in) :: cover_names_unordered(:)
829 integer(kind=i_kind) :: i_layer, j_layer, i_cover
832 do i_layer = 1,
size(layer_names_unordered)
833 do j_layer = 1,
size(layer_names_unordered)
834 if (i_layer .eq. j_layer) cycle
835 call assert_msg(781626922, layer_names_unordered(i_layer)%string .ne. &
836 layer_names_unordered(j_layer)%string, &
837 "Duplicate layer name in single particle "// &
838 "representation: '"// &
839 trim(layer_names_unordered(i_layer)%string)//
"'")
846 do i_layer = 1,
size(layer_names_unordered)
847 if (cover_names_unordered(i_layer)%string ==
"none")
then
854 do i_layer = 1,
size(layer_names_unordered)
856 .eq. cover_names_unordered(i_layer)%string)
then
875 integer(kind=i_kind),
intent(in) :: particle_id
877 real(kind=dp),
intent(in) :: number_conc
879 call assert_msg(611967802, this%is_malloced, &
880 "Trying to set number of uninitialized update object.")
881 call assert_msg(689085496, particle_id .ge. 1 .and. &
882 particle_id .le. this%maximum_computational_particles, &
883 "Invalid computational particle index: "// &
884 trim(integer_to_string(particle_id)))
886 this%get_data(), this%aero_rep_unique_id, particle_id-1, &
900 integer,
intent(in) :: comm
917 character,
intent(inout) :: buffer(:)
919 integer,
intent(inout) :: pos
921 integer,
intent(in) :: comm
924 integer :: prev_position
929 this%maximum_computational_particles, comm)
931 call assert(411585487, &
932 pos - prev_position <= this%pack_size(comm))
945 character,
intent(inout) :: buffer(:)
947 integer,
intent(inout) :: pos
949 integer,
intent(in) :: comm
952 integer :: prev_position
957 this%maximum_computational_particles, comm)
959 call assert(351557153, &
960 pos - prev_position <= this%pack_size(comm))
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.
elemental subroutine finalize(this)
Finalize the aerosol phase data.
type(aero_phase_data_t) function, pointer constructor(phase_name, init_size)
Constructor for aero_phase_data_t.
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.
elemental subroutine update_data_number_finalize(this)
Finalize a number update data object.
integer function num_layers(this)
Returns the number of layers.
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_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.