CAMP 1.0.0
Chemistry Across Multiple Phases
aero_rep_data.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_aero_rep_data module.
7
8!> \page camp_aero_rep CAMP: Aerosol Representation (general)
9!!
10!! An aerosol representation acts as an interface between an aerosol
11!! micro-physics model and \ref index "CAMP".
12!! Types that extend the abstract \c aero_rep_data_t type should be developed
13!! for each type of aerosol representation used by an external model (e.g.,
14!! binned, modal, single particle).
15!!
16!! The available aerosol representations are:
17!! - \subpage camp_aero_rep_single_particle "Single Particle"
18!! - \subpage camp_aero_rep_modal_binned_mass "Mass-only Binned/Modal"
19!!
20!! The general input format for an aerosol representation can be found
21!! \subpage input_format_aero_rep "here".
22
23!> The abstract aero_rep_data_t structure and associated subroutines.
25
26#ifdef CAMP_USE_JSON
27 use json_module
28#endif
29#ifdef CAMP_USE_MPI
30 use mpi
31#endif
34 use camp_constants, only : i_kind, dp
35 use camp_mpi
38 use camp_util, only : die_msg, string_t
39
40 use iso_c_binding
41
42 implicit none
43 private
44
47
48 !> Abstract aerosol representation data type
49 !!
50 !! Time-invariant data related to an aerosol representation. Derived types
51 !! extending aero_rep_data_t should describe specific types of aerosol
52 !! schemes (e.g., binned, modal, particle-resolved).
53 !!
54 !! See \ref camp_aero_rep "Aerosol Representations" for details.
55 type, abstract :: aero_rep_data_t
56 private
57 !> Name of the aerosol representation
58 character(len=:), allocatable, public :: rep_name
59 !> Aerosol phases associated with this aerosol scheme
60 !!
61 !! See \ref camp_aero_phase "Aerosol Phases" for details.
62 type(aero_phase_data_ptr), allocatable, public :: aero_phase(:)
63 !> Aerosol representation parameters. These will be available during
64 !! initialization, but not during solving. All information required
65 !! by functions of the aerosol representation must be saved by the
66 !! exdending type in the condensed data arrays.
67 type(property_t), pointer, public :: property_set => null()
68 !> Condensed representation data. Theses arrays will be available during
69 !! solving, and should contain any information required by the
70 !! functions of the aerosol representation that cannot be obtained
71 !! from the camp_camp_state::camp_state_t object. (floating-point)
72 real(kind=dp), allocatable, public :: condensed_data_real(:)
73 !> Condensed representation data. Theses arrays will be available during
74 !! solving, and should contain any information required by the
75 !! functions of the aerosol representation that cannot be obtained
76 !! from the camp_camp_state::camp_state_t object. (integer)
77 integer(kind=i_kind), allocatable, public :: condensed_data_int(:)
78 !> Array of booleans indicating if phase exists at the surface of a
79 !! particle. Used in SIMPOL and HL reactions for single particle
80 !! representation.
81 logical, allocatable, public :: aero_phase_is_at_surface(:)
82 !> Number of environment-dependent parameters
83 !! These are parameters that need updated when environmental conditions
84 !! change
85 integer(kind=i_kind), public :: num_env_params = 0
86 contains
87 !> Initialize the aerosol representation data, validating component data and
88 !! loading any required information from the \c
89 !! aero_rep_data_t::property_set. This routine should be called once for
90 !! each aerosol representation at the beginning of a model run after all
91 !! the input files have been read in. It ensures all data required during
92 !! the model run are included in the condensed data arrays.
93 procedure(initialize), deferred :: initialize
94 !> Get the size of the section of the
95 !! \c camp_camp_state::camp_state_t::state_var array required for this
96 !! aerosol representation
97 procedure(get_size), deferred :: size
98 !> Get a list of unique names for each element on the
99 !! \c camp_camp_state::camp_state_t::state_var array for this aerosol
100 !! representation. The list may be restricted to a particular phase and/or
101 !! aerosol species by including the phase_name and spec_name arguments.
102 procedure(unique_names), deferred :: unique_names
103 !> Get a species id on the \c camp_camp_state::camp_state_t::state_var
104 !! array by its unique name. These are unique ids for each element on the
105 !! state array for this \ref camp_aero_rep "aerosol representation" and
106 !! are numbered:
107 !!
108 !! \f[x_u \in x_f ... (x_f+n-1)\f]
109 !!
110 !! where \f$x_u\f$ is the id of the element corresponding to the species
111 !! with unique name \f$u\f$ on the \c
112 !! camp_camp_state::camp_state_t::state_var array, \f$x_f\f$ is the index
113 !! of the first element for this aerosol representation on the state array
114 !! and \f$n\f$ is the total number of variables on the state array from
115 !! this aerosol representation.
116 procedure(spec_state_id), deferred :: spec_state_id
117 !> Get the non-unique name of a species by its unique name
118 procedure(spec_name), deferred :: spec_name
119 !> Get the number of instances of an aerosol phase
121 !> Get the number of Jacobian elements for calculations of mass, volume,
122 !! number, etc for a particular phase
123 procedure(num_jac_elem), deferred :: num_jac_elem
124 !> Determine if specified phase(s) exist in adjacent layers.
125 procedure(adjacent_phases), deferred :: adjacent_phases
126 !> Get the species id on the state array by phase_id and species name
128 !> Load data from an input file
129 procedure :: load
130 !> Get the name of the aerosol representation
131 procedure :: name => get_name
132 !> Get ids for all instances of a phase in this aerosol representation for
133 !! use during solving
134 procedure :: phase_ids
135 !> Determine the number of bytes required to pack the given value
136 procedure :: pack_size
137 !> Packs the given value into the buffer, advancing position
138 procedure :: bin_pack
139 !> Unpacks the given value from the buffer, advancing position
140 procedure :: bin_unpack
141 !> Print the aerosol representation data
142 procedure :: print => do_print
143 end type aero_rep_data_t
144
145 !> Pointer to aero_rep_data_t extending types
147 !> Pointer to an aerosol representation
148 class(aero_rep_data_t), pointer :: val => null()
149 contains
150 !> Dereference the pointer
151 procedure :: dereference
152 !> Finalize the pointer
154 end type aero_rep_data_ptr
155
156 !> Update cookie
157 type, abstract :: aero_rep_update_data_t
158 !> Aerosol representation type
159 integer(kind=c_int) :: aero_rep_type
160 !> Aerosol representation solver id
161 integer(kind=c_int) :: aero_rep_solver_id = 0
162 !> Grid cell to update
163 integer(kind=c_int) :: cell_id = 1
164 !> Update data
165 type(c_ptr) :: update_data
166 contains
167 !> Get the aerosol representation type
169 !> Get the grid cell to update
170 procedure :: get_cell_id => aero_rep_update_data_get_cell_id
171 !> Get the update data
172 procedure :: get_data => aero_rep_update_data_get_data
173 !> Determine the number of bytes required to pack the given value
175 !> Packs the given value into the buffer, advancing position
177 !> Unpacks the given value from the buffer, advancing position
179 !> Extending type pack size (internal use only)
181 !> Extending type bin pack (internal use only)
182 procedure(internal_bin_pack), deferred :: internal_bin_pack
183 !> Extending type bin unpack (internal use only)
185 !> Print the update data
186 procedure :: print => do_aero_rep_update_data_print
188
189 !> Define index_pair array for adjacent_phases functions
191 integer :: first_ = -9999
192 integer :: second_ = -9999
193 end type index_pair_t
194
195interface
196!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
197
198 !> Initialize the aerosol representation data, validating component data and
199 !! loading any required information from the \c
200 !! aero_rep_data_t::property_set. This routine should be called once for
201 !! each aerosol representation at the beginning of a model run after all
202 !! the input files have been read in. It ensures all data required during
203 !! the model run are included in the condensed data arrays.
204 subroutine initialize(this, aero_phase_set, spec_state_id)
205 use camp_util, only : i_kind
208 import :: aero_rep_data_t
209
210 !> Aerosol representation data
211 class(aero_rep_data_t), intent(inout) :: this
212 !> The set of aerosol phases. Note that an aerosol representation may
213 !! implement any number of instances of each phase.
214 type(aero_phase_data_ptr), pointer, intent(in) :: aero_phase_set(:)
215 !> Beginning state id for this aerosol representation in the
216 !! \c camp_camp_state::camp_state_t::state_var array
217 integer(kind=i_kind), intent(in) :: spec_state_id
218
219 end subroutine initialize
220
221!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
222
223 !> Extending-type binary pack size (internal use only)
224 integer(kind=i_kind) function internal_pack_size(this, comm)
225 use camp_util, only : i_kind
226 import :: aero_rep_update_data_t
227
228 !> Aerosol representation data
229 class(aero_rep_update_data_t), intent(in) :: this
230 !> MPI communicator
231 integer, intent(in) :: comm
232
233 end function internal_pack_size
234
235!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
236
237 !> Extending-type binary pack function (Internal use only)
238 subroutine internal_bin_pack(this, buffer, pos, comm)
239 import :: aero_rep_update_data_t
240
241 !> Aerosol representation data
242 class(aero_rep_update_data_t), intent(in) :: this
243 !> Memory buffer
244 character, intent(inout) :: buffer(:)
245 !> Current buffer position
246 integer, intent(inout) :: pos
247 !> MPI communicator
248 integer, intent(in) :: comm
249
250 end subroutine internal_bin_pack
251
252!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
253
254 !> Extending-type binary unpack function (Internal use only)
255 subroutine internal_bin_unpack(this, buffer, pos, comm)
256 import :: aero_rep_update_data_t
257
258 !> Aerosol representation data
259 class(aero_rep_update_data_t), intent(inout) :: this
260 !> Memory buffer
261 character, intent(inout) :: buffer(:)
262 !> Current buffer position
263 integer, intent(inout) :: pos
264 !> MPI communicator
265 integer, intent(in) :: comm
266
267 end subroutine internal_bin_unpack
268
269!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
270
271 !> Get the size of the section of the
272 !! \c camp_camp_state::camp_state_t::state_var array required for this
273 !! aerosol representation
274 !! @return Size of the state array section
275 function get_size(this) result (state_size)
276 use camp_util, only : i_kind
277 import :: aero_rep_data_t
278
279 integer(kind=i_kind) :: state_size
280 !> Aerosol representation data
281 class(aero_rep_data_t), intent(in) :: this
282
283 end function get_size
284
285!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
286
287 !> Get a list of unique names for each element on the
288 !! \c camp_camp_state::camp_state_t::state_var array for this aerosol
289 !! representation.
290 !! @return List of unique names
291 function unique_names(this, phase_name, tracer_type, spec_name, &
292 phase_is_at_surface)
293 use camp_util, only : string_t, i_kind
294 import :: aero_rep_data_t
295
296 type(string_t), allocatable :: unique_names(:)
297 !> Aerosol representation data
298 class(aero_rep_data_t), intent(in) :: this
299 !> Aerosol phase name
300 character(len=*), optional, intent(in) :: phase_name
301 !> Tracer type
302 integer(kind=i_kind), optional, intent(in) :: tracer_type
303 !> Aerosol-phase species name
304 character(len=*), optional, intent(in) :: spec_name
305 !> Indicates if aerosol phase is at the surface of particle
306 logical, optional, intent(in) :: phase_is_at_surface
307
308 end function unique_names
309
310!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
311
312 !> Get a species id on the \c camp_camp_state::camp_state_t::state_var
313 !! array by unique name. These are unique ids for each element on the
314 !! state array for this \ref camp_aero_rep "aerosol representation" and
315 !! are numbered:
316 !!
317 !! \f[x_u \in x_f ... (x_f+n-1)\f]
318 !!
319 !! where \f$x_u\f$ is the id of the element corresponding to the species
320 !! with unique name \f$u\f$ on the \c
321 !! camp_camp_state::camp_state_t::state_var array, \f$x_f\f$ is the index
322 !! of the first element for this aerosol representation on the state array
323 !! and \f$n\f$ is the total number of variables on the state array from
324 !! this aerosol representation.
325 !!
326 !! If the name is not found, the return value is 0.
327 !! @return Species state id
328 function spec_state_id(this, unique_name) result (spec_id)
329 use camp_util, only : i_kind
330 import :: aero_rep_data_t
331
332 integer(kind=i_kind) :: spec_id
333 !> Aerosol representation data
334 class(aero_rep_data_t), intent(in) :: this
335 !> Unique name
336 character(len=*), intent(in) :: unique_name
337
338 end function spec_state_id
339
340!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
341
342 !> Get the non-unique name of a chemical species by its unique name
343 !! @return Chemical species name
344 function spec_name(this, unique_name)
345 use camp_util, only : i_kind
346 import :: aero_rep_data_t
347
348 character(len=:), allocatable :: spec_name
349 !> Aerosol representation data
350 class(aero_rep_data_t), intent(in) :: this
351 !> Unique name of the species in this aerosol representation
352 character(len=*), intent(in) :: unique_name
353
354 end function spec_name
355
356!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
357
358 !> Get the number of instances of a specified aerosol phase
359 !! @return Number of instances of the aerosol phase
360 function num_phase_instances(this, phase_name, is_at_surface)
361 use camp_util, only : i_kind
362 import :: aero_rep_data_t
363
364 integer(kind=i_kind) :: num_phase_instances
365 !> Aerosol representation data
366 class(aero_rep_data_t), intent(in) :: this
367 !> Aerosol phase name
368 character(len=*), intent(in) :: phase_name
369 !> Indicates if aerosol phase is at the surface of particle
370 logical, intent(in), optional :: is_at_surface
371
372 end function num_phase_instances
373
374!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
375
376 !> Get the number of Jacobian elements used in calculations of aerosol mass,
377 !! volume, number, etc. for a particular phase
378 !! @return Number of Jacobian elements used
379 function num_jac_elem(this, phase_id)
380 use camp_util, only : i_kind
381 import :: aero_rep_data_t
382
383 integer(kind=i_kind) :: num_jac_elem
384 !> Aerosol respresentation data
385 class(aero_rep_data_t), intent(in) :: this
386 !> Aerosol phase id
387 integer(kind=i_kind), intent(in) :: phase_id
388
389 end function num_jac_elem
390
391!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
392
393 !> Determine if specified phase(s) exist in adjacent layers. Returns array
394 !! of phase_ids for adjacent phases first and second.
395 !! @return Array of index pairs for adjacent phases
396 function adjacent_phases(this, phase_name_first, &
397 phase_name_second) result (index_pairs)
398 use camp_util, only : i_kind
400
401 type(index_pair_t), allocatable :: index_pairs(:)
402 !> Aerosol respresentation data
403 class(aero_rep_data_t), intent(in) :: this
404 !> Name of first phase
405 character(len=*), intent(in) :: phase_name_first
406 !> Name of second phase
407 character(len=*), intent(in) :: phase_name_second
408
409 end function adjacent_phases
410
411!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
412
413 !> Get the species id on the state array by phase_id and species name
414 !! @return Species state id
415 function spec_state_id_by_phase(this, phase_id, spec_name) result(spec_id)
417 import :: aero_rep_data_t
418
419 integer(kind=i_kind) :: spec_id
420 !> Aerosol representation data
421 class(aero_rep_data_t), intent(in) :: this
422 !> Phase id
423 integer(kind=i_kind), intent(in) :: phase_id
424 !> Species name
425 character(len=*), intent(in) :: spec_name
426
427 end function spec_state_id_by_phase
428
429!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
430
431end interface
432
433contains
434
435!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
436
437 !> \page input_format_aero_rep Input JSON Object Format: Aerosol Representation (general)
438 !!
439 !! A \c json object containing information about an \ref camp_aero_rep
440 !! "aerosol representation" has the following format:
441 !! \code{.json}
442 !! { "camp-data" : [
443 !! {
444 !! "name" : "my aero rep",
445 !! "type" : "AERO_REP_TYPE",
446 !! "some parameter" : 123.34,
447 !! "some other parameter" : true,
448 !! "nested parameters" : {
449 !! "sub param 1" : 12.43,
450 !! "sub param other" : "some text",
451 !! ...
452 !! },
453 !! ...
454 !! },
455 !! ...
456 !! ]}
457 !! \endcode
458 !! Aerosol representations must have a unique \b name that will be used to
459 !! identify the aerosol representation during initialization. The key-value
460 !! pair \b type is also required and must correspond to a valid aerosol
461 !! representation type. These include:
462 !!
463 !! - \subpage camp_aero_rep_single_particle "AERO_REP_SINGLE_PARTICLE"
464 !! - \subpage camp_aero_rep_modal_binned_mass
465 !! "AERO_REP_MODAL_BINNED_MASS"
466 !!
467 !! All remaining data are optional and may include any valid \c json value.
468 !! However, extending types will have specific requirements for the
469 !! remaining data.
470
471!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
472
473 !> Load an aerosol representation from an input file
474#ifdef CAMP_USE_JSON
475 subroutine load(this, json, j_obj)
476
477 !> Aerosol representation data
478 class(aero_rep_data_t), intent(inout) :: this
479 !> JSON core
480 type(json_core), pointer, intent(in) :: json
481 !> JSON object
482 type(json_value), pointer, intent(in) :: j_obj
483
484 type(json_value), pointer :: child, next
485 character(kind=json_ck, len=:), allocatable :: key, unicode_str_val
486 integer(kind=json_ik) :: var_type
487 logical :: found_name
488
489 ! allocate space for the aerosol representation property set
490 this%property_set => property_t()
491
492 if (.not.allocated(this%rep_name)) &
493 this%rep_name = "unknown aerosol representation"
494 found_name = .false.
495
496 ! cycle through the aerosol representation properties to find the name and
497 ! load the remaining data into the aerosol representation property set
498 next => null()
499 call json%get_child(j_obj, child)
500 do while (associated(child))
501 call json%info(child, name=key, var_type=var_type)
502
503 ! aerosol representation name
504 if (key.eq."name") then
505 call assert_msg(196193896, var_type.eq.json_string, &
506 "Received non-string value for aerosol rep name")
507 call json%get(child, unicode_str_val)
508 this%rep_name = unicode_str_val
509 found_name = .true.
510
511 ! load remaining data tinto the property set
512 else if (key.ne."type") then
513 call this%property_set%load(json, child, .false., this%rep_name)
514 end if
515
516 call json%get_next(child, next)
517 child => next
518 end do
519 call assert_msg(420903951, found_name, &
520 "Received unnamed aerosol representation.")
521#else
522 subroutine load(this)
523
524 !> Aerosol representation data
525 class(aero_rep_data_t), intent(inout) :: this
526
527 call warn_msg(433045149, "No support for input files")
528#endif
529
530 end subroutine load
531
532!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
533
534 !> Get the name of the aerosol representation
535 function get_name(this)
536
537 !> Aerosol representation name
538 character(len=:), allocatable :: get_name
539 !> Aerosol representation data
540 class(aero_rep_data_t), intent(in) :: this
541
542 get_name = this%rep_name
543
544 end function get_name
545
546!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
547
548 !> Get a set of ids for all instances of a phase in this aerosol
549 !! representation for use during solving
550 function phase_ids(this, phase_name, is_at_surface)
551
552 !> List of phase ids
553 integer(kind=i_kind), allocatable :: phase_ids(:)
554 !> Aerosol representation data
555 class(aero_rep_data_t), intent(in) :: this
556 !> Aerosol phase name
557 character(len=*), intent(in) :: phase_name
558 !> Indicates if aerosol phase is at the surface of particle
559 logical, intent(in), optional :: is_at_surface
560
561 integer(kind=i_kind) :: num_instances, i_instance, i_phase
562
563 num_instances = this%num_phase_instances(phase_name, is_at_surface)
564 allocate(phase_ids(num_instances))
565 if (present(is_at_surface)) then
566 if (is_at_surface) then
567 i_instance = 1
568 do i_phase = 1, size(this%aero_phase)
569 if (this%aero_phase(i_phase)%val%name().eq. phase_name .and. &
570 this%aero_phase_is_at_surface(i_phase)) then
571 phase_ids(i_instance) = i_phase
572 i_instance = i_instance + 1
573 end if
574 end do
575 else
576 i_instance = 1
577 do i_phase = 1, size(this%aero_phase)
578 if (this%aero_phase(i_phase)%val%name().eq. phase_name .and. &
579 .not. this%aero_phase_is_at_surface(i_phase)) then
580 phase_ids(i_instance) = i_phase
581 i_instance = i_instance + 1
582 end if
583 end do
584 end if
585 else
586 i_instance = 1
587 do i_phase = 1, size(this%aero_phase)
588 if (this%aero_phase(i_phase)%val%name().eq.phase_name) then
589 phase_ids(i_instance) = i_phase
590 i_instance = i_instance + 1
591 end if
592 end do
593 end if
594 call assert(642387392, num_instances == i_instance-1)
595
596 end function phase_ids
597
598!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
599
600 !> Determine the size of a binary required to pack the aerosol
601 !! representation data
602 integer(kind=i_kind) function pack_size(this, comm)
603
604 !> Aerosol representation data
605 class(aero_rep_data_t), intent(in) :: this
606 !> MPI communicator
607 integer, intent(in) :: comm
608
609 pack_size = &
610 camp_mpi_pack_size_real_array(this%condensed_data_real, comm) + &
611 camp_mpi_pack_size_integer_array(this%condensed_data_int, comm) + &
612 camp_mpi_pack_size_integer(this%num_env_params, comm)
613
614 end function pack_size
615
616!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
617
618 !> Pack the given value to the buffer, advancing position
619 subroutine bin_pack(this, buffer, pos, comm)
620
621 !> Aerosol representation data
622 class(aero_rep_data_t), intent(in) :: this
623 !> Memory buffer
624 character, intent(inout) :: buffer(:)
625 !> Current buffer position
626 integer, intent(inout) :: pos
627 !> MPI communicator
628 integer, intent(in) :: comm
629
630#ifdef CAMP_USE_MPI
631 integer :: prev_position
632
633 prev_position = pos
634 call camp_mpi_pack_real_array(buffer, pos, this%condensed_data_real, comm)
635 call camp_mpi_pack_integer_array(buffer, pos, this%condensed_data_int,comm)
636 call camp_mpi_pack_integer(buffer, pos, this%num_env_params,comm)
637 call assert(257024095, &
638 pos - prev_position <= this%pack_size(comm))
639#endif
640
641 end subroutine bin_pack
642
643!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
644
645 !> Unpack the given value from the buffer, advancing position
646 subroutine bin_unpack(this, buffer, pos, comm)
647
648 !> Aerosol representation data
649 class(aero_rep_data_t), intent(out) :: this
650 !> Memory buffer
651 character, intent(inout) :: buffer(:)
652 !> Current buffer position
653 integer, intent(inout) :: pos
654 !> MPI communicator
655 integer, intent(in) :: comm
656
657#ifdef CAMP_USE_MPI
658 integer :: prev_position
659
660 prev_position = pos
661 call camp_mpi_unpack_real_array(buffer, pos, this%condensed_data_real,comm)
662 call camp_mpi_unpack_integer_array(buffer, pos, this%condensed_data_int, &
663 comm)
664 call camp_mpi_unpack_integer(buffer, pos, this%num_env_params,comm)
665 call assert(954732699, &
666 pos - prev_position <= this%pack_size(comm))
667#endif
668
669 end subroutine bin_unpack
670
671!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
672
673 !> Print the aerosol representation data
674 subroutine do_print(this, file_unit)
675
676 !> Aerosol representation data
677 class(aero_rep_data_t), intent(in) :: this
678 !> File unit for output
679 integer(kind=i_kind), optional :: file_unit
680
681 integer(kind=i_kind) :: f_unit
682
683 file_unit = 6
684
685 if (present(file_unit)) f_unit = file_unit
686 write(f_unit,*) "*** Aerosol Representation: ",trim(this%rep_name)," ***"
687 if (associated(this%property_set)) call this%property_set%print(f_unit)
688 if (allocated(this%condensed_data_int)) &
689 write(f_unit,*) " *** condensed data int: ",this%condensed_data_int(:)
690 if (allocated(this%condensed_data_real)) &
691 write(f_unit,*) " *** condensed data real: ",this%condensed_data_real(:)
692
693 end subroutine do_print
694
695!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
696
697 !> Deference a pointer to an aerosol representation
698 elemental subroutine dereference(this)
699
700 !> Pointer to an aerosol representation
701 class(aero_rep_data_ptr), intent(inout) :: this
702
703 this%val => null()
704
705 end subroutine dereference
706
707!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
708
709 !> Finalize a pointer to an aerosol representation
710 subroutine ptr_finalize(this)
711
712 !> Pointer to an aerosol representation
713 type(aero_rep_data_ptr), intent(inout) :: this
714
715 if (associated(this%val)) deallocate(this%val)
716
717 end subroutine ptr_finalize
718
719!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
720
721 !> Finalize an array of pointers to aerosol representations
722 subroutine ptr_finalize_array(this)
723
724 !> Array of pointers to aerosol representations
725 type(aero_rep_data_ptr), intent(inout) :: this(:)
726
727 integer(kind=i_kind) :: i
728
729 do i = 1, size(this)
730 call ptr_finalize(this(i))
731 end do
732
733 end subroutine ptr_finalize_array
734
735!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
736
737 !> Get the update data aerosol representation type
738 function aero_rep_update_data_get_type(this) result (aero_rep_type)
739
740 !> Aerosol representation type
741 integer(kind=c_int) :: aero_rep_type
742 !> Update data
743 class(aero_rep_update_data_t), intent(in) :: this
744
745 aero_rep_type = this%aero_rep_type
746
748
749!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
750
751 !> Get the grid cell id to update
752 function aero_rep_update_data_get_cell_id(this) result(cell_id)
753
754 !> Grid cell id
755 integer(kind=c_int) :: cell_id
756 !> Update data
757 class(aero_rep_update_data_t), intent(in) :: this
758
759 cell_id = this%cell_id
760
762
763!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
764
765 !> Get the update data
766 function aero_rep_update_data_get_data(this) result (update_data)
767
768 !> Update data ptr
769 type(c_ptr) :: update_data
770 !> Update data
771 class(aero_rep_update_data_t), intent(in) :: this
772
773 update_data = this%update_data
774
776
777!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
778
779!> Determine the size of a binary required to pack the reaction data
780 integer(kind=i_kind) function aero_rep_update_data_pack_size(this, comm) &
781 result(pack_size)
782
783 !> Aerosol representation update data
784 class(aero_rep_update_data_t), intent(in) :: this
785 !> MPI communicator
786 integer, intent(in), optional :: comm
787
788#ifdef CAMP_USE_MPI
789 integer :: l_comm
790
791 if (present(comm)) then
792 l_comm = comm
793 else
794 l_comm = mpi_comm_world
795 endif
796
797 pack_size = &
798 camp_mpi_pack_size_integer(int(this%aero_rep_type, kind=i_kind), &
799 l_comm) + &
800 camp_mpi_pack_size_integer(int(this%aero_rep_solver_id, kind=i_kind), &
801 l_comm) + &
802 this%internal_pack_size(l_comm)
803#else
804 pack_size = 0
805#endif
806
808
809!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
810
811 !> Pack the given value to the buffer, advancing position
812 subroutine aero_rep_update_data_bin_pack(this, buffer, pos, comm)
813
814 !> Aerosol representation update data
815 class(aero_rep_update_data_t), intent(in) :: this
816 !> Memory buffer
817 character, intent(inout) :: buffer(:)
818 !> Current buffer position
819 integer, intent(inout) :: pos
820 !> MPI communicator
821 integer, intent(in), optional :: comm
822
823#ifdef CAMP_USE_MPI
824 integer :: prev_position, l_comm
825
826 if (present(comm)) then
827 l_comm = comm
828 else
829 l_comm = mpi_comm_world
830 endif
831
832 prev_position = pos
833 call camp_mpi_pack_integer(buffer, pos, &
834 int(this%aero_rep_type, kind=i_kind), l_comm)
835 call camp_mpi_pack_integer(buffer, pos, &
836 int(this%aero_rep_solver_id, kind=i_kind), &
837 l_comm)
838 call this%internal_bin_pack(buffer, pos, l_comm)
839 call assert(538137635, &
840 pos - prev_position <= this%pack_size(l_comm))
841#endif
842
843 end subroutine aero_rep_update_data_bin_pack
844
845!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
846
847 !> Unpack the given value from the buffer, advancing position
848 subroutine aero_rep_update_data_bin_unpack(this, buffer, pos, comm)
849
850 !> Aerosol representation update data
851 class(aero_rep_update_data_t), intent(out) :: this
852 !> Memory buffer
853 character, intent(inout) :: buffer(:)
854 !> Current buffer position
855 integer, intent(inout) :: pos
856 !> MPI communicator
857 integer, intent(in), optional :: comm
858
859#ifdef CAMP_USE_MPI
860 integer :: prev_position, l_comm
861 integer(kind=i_kind) :: temp_int
862
863 if (present(comm)) then
864 l_comm = comm
865 else
866 l_comm = mpi_comm_world
867 endif
868
869 prev_position = pos
870 call camp_mpi_unpack_integer(buffer, pos, temp_int, l_comm)
871 this%aero_rep_type = int(temp_int, kind=c_int)
872 call camp_mpi_unpack_integer(buffer, pos, temp_int, l_comm)
873 this%aero_rep_solver_id = int(temp_int, kind=c_int)
874 call this%internal_bin_unpack(buffer, pos, l_comm)
875 call assert(257567920, &
876 pos - prev_position <= this%pack_size(l_comm))
877#endif
878
880
881!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
882
883 !> Print the update data
884 subroutine do_aero_rep_update_data_print(this, file_unit)
885
886 !> Aerosol representation update data
887 class(aero_rep_update_data_t), intent(in) :: this
888 !> File unit for output
889 integer(kind=i_kind), optional :: file_unit
890
891 integer(kind=i_kind) :: f_unit
892
893 f_unit = 6
894
895 if (present(file_unit)) f_unit = file_unit
896
897 write(f_unit,*) "*** Aerosol representation update data ***"
898 write(f_unit,*) "Aerosol representation type", this%aero_rep_type
899 write(f_unit,*) "Aerosol representation solver id", this%aero_rep_solver_id
900
901 end subroutine do_aero_rep_update_data_print
902
903!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
904
905end module camp_aero_rep_data
Determine if specified phase(s) exist in adjacent layers. Returns array of phase_ids for adjacent pha...
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 the species id on the state array by phase_id and species 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...
The abstract aero_phase_data_t structure and associated subroutines.
subroutine bin_unpack(this, buffer, pos, comm)
Unpack the given value from the buffer, advancing position.
character(len=:) function, allocatable get_name(this)
Get the aerosol phase name.
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.
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.
elemental subroutine dereference(this)
Dereference a pointer to aerosol phase data.
The abstract aero_rep_data_t structure and associated subroutines.
subroutine do_aero_rep_update_data_print(this, file_unit)
Print the update data.
integer(kind=i_kind) function, dimension(:), allocatable phase_ids(this, phase_name, is_at_surface)
Get a set of ids for all instances of a phase in this aerosol representation for use during solving.
type(c_ptr) function aero_rep_update_data_get_data(this)
Get the update data.
integer(kind=i_kind) function aero_rep_update_data_pack_size(this, comm)
Determine the size of a binary required to pack the reaction data.
subroutine do_print(this, file_unit)
Print the aerosol representation data.
subroutine aero_rep_update_data_bin_pack(this, buffer, pos, comm)
Pack the given value to the buffer, advancing position.
subroutine ptr_finalize(this)
Finalize a pointer to an aerosol representation.
integer(kind=i_kind) function pack_size(this, comm)
Determine the size of a binary required to pack the aerosol representation data.
subroutine load(this, json, j_obj)
Load an aerosol representation from an input file.
subroutine aero_rep_update_data_bin_unpack(this, buffer, pos, comm)
Unpack the given value from the buffer, advancing position.
subroutine bin_unpack(this, buffer, pos, comm)
Unpack the given value from the buffer, advancing position.
elemental subroutine dereference(this)
Deference a pointer to an aerosol representation.
integer(kind=c_int) function aero_rep_update_data_get_type(this)
Get the update data aerosol representation type.
subroutine bin_pack(this, buffer, pos, comm)
Pack the given value to the buffer, advancing position.
character(len=:) function, allocatable get_name(this)
Get the name of the aerosol representation.
subroutine ptr_finalize_array(this)
Finalize an array of pointers to aerosol representations.
integer(kind=c_int) function aero_rep_update_data_get_cell_id(this)
Get the grid cell id to update.
The camp_state_t structure and associated subroutines.
Definition: camp_state.F90:9
The chem_spec_data_t structure and associated subroutines.
logical function get_type(this, spec_name, spec_type)
Get a species type by species name. Returns true if the species is found or false otherwise.
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
Wrapper functions for MPI.
Definition: mpi.F90:13
subroutine camp_mpi_pack_integer_array(buffer, position, val, comm)
Packs the given value into the buffer, advancing position.
Definition: mpi.F90:858
subroutine camp_mpi_pack_real_array(buffer, position, val, comm)
Packs the given value into the buffer, advancing position.
Definition: mpi.F90:899
subroutine camp_mpi_unpack_integer_array(buffer, position, val, comm)
Unpacks the given value from the buffer, advancing position.
Definition: mpi.F90:1201
subroutine camp_mpi_unpack_integer(buffer, position, val, comm)
Unpacks the given value from the buffer, advancing position.
Definition: mpi.F90:1023
integer function camp_mpi_pack_size_real_array(val, comm)
Determines the number of bytes required to pack the given value.
Definition: mpi.F90:578
integer function camp_mpi_pack_size_integer_array(val, comm)
Determines the number of bytes required to pack the given value.
Definition: mpi.F90:540
subroutine camp_mpi_pack_integer(buffer, position, val, comm)
Packs the given value into the buffer, advancing position.
Definition: mpi.F90:691
integer function camp_mpi_pack_size_integer(val, comm)
Determines the number of bytes required to pack the given value.
Definition: mpi.F90:398
subroutine camp_mpi_unpack_real_array(buffer, position, val, comm)
Unpacks the given value from the buffer, advancing position.
Definition: mpi.F90:1242
The property_t structure and associated subroutines.
Definition: property.F90:9
Common utility subroutines.
Definition: util.F90:9
subroutine die_msg(code, error_msg)
Error immediately.
Definition: util.F90:196
character(len=camp_util_convert_string_len) function integer_to_string(val)
Convert an integer to a string format.
Definition: util.F90:839
Pointer type for building arrays.
Pointer to aero_rep_data_t extending types.
Abstract aerosol representation data type.
Define index_pair array for adjacent_phases functions.
String type for building arrays of string of various size.
Definition: util.F90:38