CAMP 1.0.0
Chemistry Across Multiple Phases
aero_rep_factory.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_factory module.
7
8!> \page camp_aero_rep_add CAMP: Adding an Aerosol Representation
9!!
10!! NOTE: These instructions are out-of-date. TODO update
11!!
12!! Adding an \ref camp_aero_rep "aerosol representation" to the \ref
13!! index "camp-chem" module can be done in the following steps:
14!!
15!! ## Step 1. Create a new aerosol representation module ##
16!! The module should be placed in the \c /src/aero_reps folder and
17!! extend the abstract \c camp_aero_rep_data::aero_rep_data_t type,
18!! overriding all deferred functions, and providing a constructor that
19!! returns a pointer to a newly allocated instance of the new type:
20!!
21!! \code{.f90}
22!! module camp_aero_rep_foo
23!!
24!! use ...
25!!
26!! implicit none
27!! private
28!!
29!! public :: aero_rep_foo_t
30!!
31!! type, extends(aero_rep_data_t) :: aero_rep_foo_t
32!! contains
33!! ... (all deferred functions) ...
34!! end type :: aero_rep_foo_t
35!!
36!! ! Constructor
37!! interface aero_rep_foo_t
38!! procedure :: constructor
39!! end interface aero_rep_foo_t
40!!
41!! function constructor() result (new_obj)
42!! type(aero_rep_foo_t), pointer :: new_obj
43!! allocate(new_obj)
44!! end function constructor
45!!
46!! ...
47!!
48!! end module camp_aero_rep_foo
49!! \endcode
50!!
51!! ## Step 2. Create a new aerosol representation state module ##
52!! The module should also be placed in the \c /src/aero_reps folder and
53!! should extend the abstract \c camp_aero_rep_state::aero_rep_state_t
54!! type, overriding all deferred functions, and providing a constructor
55!! that returns a pointer to a newly allocated instance of the new type:
56!!
57!! \code{.f90}
58!! module camp_aero_rep_foo_state
59!!
60!! use ...
61!!
62!! implicit none
63!! private
64!!
65!! public :: aero_rep_foo_state_t
66!!
67!! type, extends(aero_rep_state_t) :: aero_rep_foo_state_t
68!! contains
69!! ... (all deferred functions) ...
70!! end type :: aero_rep_foo_state_t
71!!
72!! ! Constructor
73!! interface aero_rep_foo_state_t
74!! procedure :: constructor
75!! end interface aero_rep_foo_state_t
76!!
77!! function constructor() result (new_obj)
78!! type(aero_rep_foo_state_t), pointer :: new_obj
79!! allocate(new_obj)
80!! end function constructor
81!!
82!! ...
83!!
84!! end module camp_aero_rep_foo_state
85!! \endcode
86!!
87!! ## Step 3. Add the aerosol representation to the \c camp_aero_rep_factory module ##
88!!
89!! \code{.f90}
90!! module camp_aero_rep_factory
91!!
92!! ...
93!!
94!! ! Use all aerosol representation modules
95!! ...
96!! use camp_aero_rep_foo
97!!
98!! ...
99!!
100!! !> Identifiers for aerosol representations - used by binary packing/unpacking
101!! !! functions
102!! ...
103!! integer(kind=i_kind), parameter :: AERO_REP_FOO = 32
104!!
105!! ...
106!!
107!! !> Create a new aerosol representation by type name
108!! function create(this, type_name) result (new_obj)
109!! ...
110!! select case (type_name)
111!! ...
112!! case ("AERO_REP_FOO")
113!! new_obj => aero_rep_foo_t()
114!! ...
115!! end function create
116!!
117!! ...
118!!
119!! !> Pack the given value to the buffer, advancing position
120!! subroutine bin_pack(this, aero_rep, buffer, pos)
121!! ...
122!! select type (aero_rep)
123!! ...
124!! type is (aero_rep_foo_t)
125!! aero_rep_type = AERO_REP_FOO
126!! ...
127!! end subroutine bin_pack
128!!
129!! ...
130!!
131!! !> Unpack the given value to the buffer, advancing position
132!! function bin_unpack(this, buffer, pos) result (aero_rep)
133!! ...
134!! select case (aero_rep_type)
135!! ...
136!! case (AERO_REP_FOO)
137!! aero_rep => aero_rep_foo_t()
138!! ...
139!! end function bin_unpack
140!!
141!! ...
142!! end module camp_aero_rep_factory
143!! \endcode
144!!
145!! ## Step 4. Add the new module to the CMakeList file in the root directory. ##
146!!
147!! \code{.unparsed}
148!! ...
149!!
150!! # partmc library
151!! ...
152!! set(AEROSOL_REPS_SRC
153!! ...
154!! src/aero_reps/aero_rep_foo.F90
155!! src/aero_reps/aero_rep_foo_state.F90
156!! )
157!!
158!! ...
159!! \endcode
160!!
161!! ## Step 5. Add unit tests for the new \c aero_rep_foo_t and \c aero_rep_foo_state_t types ##
162!!
163!! Unit testing should be based on the actual functions of the new module, but
164!! in general 80% code coverage is recommended. Some examples can be found in
165!! the \c /src/test folder
166!!
167!! ## Usage ##
168!! The new \ref camp_aero_rep "aerosol representation" is now ready to use.
169!! To include it in a \c camp_camp_core::camp_core_t instance, add an \ref
170!! input_format_aero_rep "aerosol representation object" to a new or existing
171!! \ref input_format_camp_config "camp-chem configuration file" with a
172!! \b type corresponding to the newly created type, along with any required
173!! parameters:
174!!
175!! \code{.json}
176!! { "camp-data" : [
177!! {
178!! "type" : "AERO_REP_FOO",
179!! ...
180!! },
181!! ...
182!! ]}
183!! \endcode
184!!
185
186!> The aero_rep_factory_t type and associated subroutines.
188
189#ifdef CAMP_USE_JSON
190 use json_module
191#endif
192#ifdef CAMP_USE_MPI
193 use mpi
194#endif
196 use camp_constants, only : i_kind, dp
197 use camp_mpi
198 use camp_util, only : die_msg, string_t, assert_msg, &
200
201 ! Use all aerosol representation modules
204
205 use iso_c_binding
206
207 implicit none
208 private
209
210 public :: aero_rep_factory_t
211
212 !> Identifiers for aerosol representations - used by binary
213 !! packing/unpacking functions
214 integer(kind=i_kind), parameter :: aero_rep_single_particle = 1
215 integer(kind=i_kind), parameter :: aero_rep_modal_binned_mass = 2
216
217 !> Factory type for aerosol representations
218 !!
219 !! Provides new instances of types extending aero_rep_data_t by name or
220 !! from input file data
222 contains
223 !> Create a new aerosol representation by type name
224 procedure :: create
225 !> Create a new aerosol representation from input data
226 procedure :: load
227 !> Get the aerosol representation type
228 procedure :: get_type
229 !> Initialize an update data object
231 !> Determine the number of bytes required to pack an given aerosol
232 !! representation
233 procedure :: pack_size
234 !> Pack a given aerosol representation to the buffer, advancing the
235 !! position
236 procedure :: bin_pack
237 !> Unpack a aerosol representation from the buffer, advancing the position
238 procedure :: bin_unpack
239 end type aero_rep_factory_t
240
241contains
242
243!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
244
245 !> Create a new aerosol representation by type name
246 function create(this, type_name) result (new_obj)
247
248 !> An aerosol representation
249 class(aero_rep_data_t), pointer :: new_obj
250 !> Aerosol representation factory
251 class(aero_rep_factory_t), intent(in) :: this
252 !> Name of the aerosol representation
253 character(len=*), intent(in) :: type_name
254
255 new_obj => null()
256
257 select case (type_name)
258 case ("AERO_REP_MODAL_BINNED_MASS")
260 case ("AERO_REP_SINGLE_PARTICLE")
261 new_obj => aero_rep_single_particle_t()
262 case default
263 call die_msg(792930166, "Unknown aerosol representation type: " &
264 //type_name)
265 end select
266
267 end function create
268
269!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
270
271 !> Load an aerosol represenation based on its type
272#ifdef CAMP_USE_JSON
273 function load(this, json, j_obj) result (new_obj)
274
275 !> An aerosol representation
276 class(aero_rep_data_t), pointer :: new_obj
277 !> Aerosol representation factory
278 class(aero_rep_factory_t), intent(in) :: this
279 !> JSON core
280 type(json_core), pointer, intent(in) :: json
281 !> JSON object
282 type(json_value), pointer, intent(in) :: j_obj
283
284 character(kind=json_ck, len=:), allocatable :: unicode_name
285 character(len=:), allocatable :: type_name
286 logical(kind=json_lk) :: found
287
288 new_obj => null()
289
290 ! get the aerosol representation type
291 call json%get(j_obj, "type", unicode_name, found)
292 call assert_msg(904082395, found, 'Missing aerosol representation type.')
293 type_name = unicode_name
294
295 ! create a new aerosol representation
296 new_obj => this%create(type_name)
297
298 ! load aerosol representation parameters from the json object
299 call new_obj%load(json, j_obj)
300
301#else
302 function load(this) result (new_obj)
303
304 !> An aerosol representation
305 class(aero_rep_data_t), pointer :: new_obj
306 !> Aerosol representation factory
307 class(aero_rep_factory_t), intent(in) :: this
308
309 new_obj => null()
310
311 call warn_msg(723960750, "No support for input files.")
312#endif
313 end function load
314
315!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
316
317 !> Get the aerosol reaction type
318 integer(kind=i_kind) function get_type(this, aero_rep) result(aero_rep_type)
319
320 !> Aerosol representation factory
321 class(aero_rep_factory_t), intent(in) :: this
322 !> Aerosol representation to get the type of
323 class(aero_rep_data_t), intent(in) :: aero_rep
324
325 select type (aero_rep)
327 aero_rep_type = aero_rep_modal_binned_mass
329 aero_rep_type = aero_rep_single_particle
330 class default
331 call die_msg(865927801, "Unknown aerosol representation type")
332 end select
333
334 end function get_type
335
336!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
337
338 !> Get a new update data object
339 subroutine initialize_update_data(this, aero_rep, update_data)
340
341 !> Aerosol representation factory
342 class(aero_rep_factory_t), intent(in) :: this
343 !> Aerosol representation to be updated
344 class(aero_rep_data_t), intent(inout) :: aero_rep
345 !> Update data object
346 class(aero_rep_update_data_t), intent(out) :: update_data
347
348 select type (update_data)
350 select type (aero_rep)
352 call aero_rep%update_data_initialize_number(update_data, &
354 class default
355 call die_msg(584145506, "Update data <-> aero rep mismatch")
356 end select
358 select type (aero_rep)
360 call aero_rep%update_data_initialize_GMD(update_data, &
362 class default
363 call die_msg(696463851, "Update data <-> aero rep mismatch")
364 end select
366 select type (aero_rep)
368 call aero_rep%update_data_initialize_GSD(update_data, &
370 class default
371 call die_msg(526306947, "Update data <-> aero rep mismatch")
372 end select
373 class default
374 call die_msg(916635086, "Internal error - update data type missing.")
375 end select
376
377 end subroutine initialize_update_data
378
379!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
380
381 !> Determine the size of a binary required to pack an aerosol representation
382 integer(kind=i_kind) function pack_size(this, aero_rep, comm)
383
384 !> Aerosol representation factory
385 class(aero_rep_factory_t), intent(in) :: this
386 !> Aerosol representation to pack
387 class(aero_rep_data_t), intent(in) :: aero_rep
388 !> MPI communicator
389 integer, intent(in) :: comm
390
391 pack_size = camp_mpi_pack_size_integer(int(1, kind=i_kind), comm) + &
392 aero_rep%pack_size(comm)
393
394 end function pack_size
395
396!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
397
398 !> Pack the given value to the buffer, advancing position
399 subroutine bin_pack(this, aero_rep, buffer, pos, comm)
400
401 !> Aerosol representation factory
402 class(aero_rep_factory_t), intent(in) :: this
403 !> Aerosol representation to pack
404 class(aero_rep_data_t), intent(in) :: aero_rep
405 !> Memory buffer
406 character, intent(inout) :: buffer(:)
407 !> Current buffer position
408 integer, intent(inout) :: pos
409 !> MPI communicator
410 integer, intent(in) :: comm
411
412#ifdef CAMP_USE_MPI
413 integer :: aero_rep_type, i_aero_rep, prev_position
414
415 prev_position = pos
416 select type (aero_rep)
418 aero_rep_type = aero_rep_modal_binned_mass
420 aero_rep_type = aero_rep_single_particle
421 class default
422 call die_msg(278244560, &
423 "Trying to pack aerosol representation of unknown type.")
424 end select
425 call camp_mpi_pack_integer(buffer, pos, aero_rep_type, comm)
426 call aero_rep%bin_pack(buffer, pos, comm)
427 call assert(897674844, &
428 pos - prev_position <= this%pack_size(aero_rep, comm))
429#endif
430
431 end subroutine bin_pack
432
433!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
434
435 !> Unpack the given value to the buffer, advancing position
436 function bin_unpack(this, buffer, pos, comm) result (aero_rep)
437
438 !> Unpacked aerosol representation
439 class(aero_rep_data_t), pointer :: aero_rep
440 !> Aerosol representation factory
441 class(aero_rep_factory_t), intent(in) :: this
442 !> Memory buffer
443 character, intent(inout) :: buffer(:)
444 !> Current buffer position
445 integer, intent(inout) :: pos
446 !> MPI communicator
447 integer, intent(in) :: comm
448
449#ifdef CAMP_USE_MPI
450 integer :: aero_rep_type, i_aero_rep, prev_position
451
452 prev_position = pos
453 call camp_mpi_unpack_integer(buffer, pos, aero_rep_type, comm)
454 select case (aero_rep_type)
456 aero_rep => aero_rep_modal_binned_mass_t()
458 aero_rep => aero_rep_single_particle_t()
459 case default
460 call die_msg(106634417, &
461 "Trying to unpack aerosol representation of unknown type:"// &
462 to_string(aero_rep_type))
463 end select
464 call aero_rep%bin_unpack(buffer, pos, comm)
465 call assert(948795857, &
466 pos - prev_position <= this%pack_size(aero_rep, comm))
467#endif
468
469 end function bin_unpack
470
471!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
472
473end module camp_aero_rep_factory
Interface for to_string functions.
Definition util.F90:32
The abstract aero_rep_data_t structure and associated subroutines.
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 bin_unpack(this, buffer, pos, comm)
Unpack the given value from the buffer, advancing position.
subroutine bin_pack(this, buffer, pos, comm)
Pack the given value to the buffer, advancing position.
The aero_rep_factory_t type and associated subroutines.
class(aero_rep_data_t) function, pointer create(this, type_name)
Create a new aerosol representation by type name.
subroutine initialize_update_data(this, aero_rep, update_data)
Get a new update data object.
integer(kind=i_kind), parameter aero_rep_modal_binned_mass
integer(kind=i_kind) function get_type(this, aero_rep)
Get the aerosol reaction type.
integer(kind=i_kind), parameter aero_rep_single_particle
Identifiers for aerosol representations - used by binary packing/unpacking functions.
The abstract aero_rep_modal_binned_mass_t structure and associated subroutines.
The aero_rep_single_particle_t type and associated subroutines.
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_unpack_integer(buffer, position, val, comm)
Unpacks the given value from the buffer, advancing position.
Definition mpi.F90:1023
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
Common utility subroutines.
Definition util.F90:9
subroutine assert(code, condition_ok)
Errors unless condition_ok is true.
Definition util.F90:165
subroutine die_msg(code, error_msg)
Error immediately.
Definition util.F90:196
subroutine assert_msg(code, condition_ok, error_msg)
Errors unless condition_ok is true.
Definition util.F90:130
subroutine warn_msg(code, warning_msg, already_warned)
Prints a warning message.
Definition util.F90:90
Abstract aerosol representation data type.
Factory type for aerosol representations.
String type for building arrays of string of various size.
Definition util.F90:38