PartMC  2.6.1
photolysis.F90
Go to the documentation of this file.
1 ! Copyright (C) 2020, 2021 Matt Dawson
2 ! Licensed under the GNU General Public License version 2 or (at your
3 ! option) any later version. See the file COPYING for details.
4 
5 !> \file
6 !> PartMC interface to a photolysis module
7 
8 !> The photolysis_t type and related functions
10 
11  use pmc_constants
12 #ifdef PMC_USE_CAMP
13  use camp_camp_core
14  use camp_rxn_data
15  use camp_rxn_photolysis
16 #endif
17  use pmc_util
18 
19 #ifdef PMC_USE_CAMP
20 
21  implicit none
22  private
23 
24  public :: photolysis_t
25 
26  !> Provider of photolysis rates
27  type :: photolysis_t
28  private
29  !> Pointer to the CAMP core to update rates for
30  type(camp_core_t), pointer :: camp_core => null()
31  !> Base photolysis rates (s-1)
32  real(kind=dp), allocatable :: base_rates(:)
33  !> Rate update objects
34  type(rxn_update_data_photolysis_t), allocatable :: photo_rxns(:)
35  contains
36  !> Update the CAMP photolysis rate constants
37  procedure :: update_rate_constants
38  !> Determine the number of bytes required to pack the given value
39  procedure :: pack_size
40  !> Packs the given value into the buffer, advancing position
41  procedure :: bin_pack
42  !> Unpacks the given value from the buffer, advancing position
43  procedure :: bin_unpack
44  !> Print the photolysis module data
45  procedure :: print => do_print
46  end type photolysis_t
47 
48  !> Constructor for photolysis_t
49  interface photolysis_t
50  procedure :: constructor
51  end interface photolysis_t
52 
53 contains
54 
55 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
56 
57  !> Constructor for photolysis_t
58  function constructor(camp_core) result(new_obj)
59 
60  !> A new photolysis rate calculator
61  type(photolysis_t), pointer :: new_obj
62  !> The CAMP core containing photolysis reactions
63  type(camp_core_t), pointer, intent(in), optional :: camp_core
64 
65  character(len=:), allocatable :: rxn_key, rxn_val, rate_key, str_val
66  real(kind=dp) :: rate_val
67  integer :: i_mech, i_rxn, i_photo_rxn, n_photo_rxns
68  class(rxn_data_t), pointer :: rxn
69 
70  ! If no core is provided, return an empty object that can be
71  ! unpacked from an MPI buffer
72  new_obj => null()
73  if (.not. present(camp_core)) return
74 
75  ! Strings needed to find all the photolysis reactions
76  rxn_key = "type"
77  rxn_val = "PHOTOLYSIS"
78  rate_key = "base rate"
79 
80  call assert(254347663, associated(camp_core))
81  call assert(689045432, camp_core%is_initialized())
82  call assert(256253197, associated(camp_core%mechanism))
83 
84  allocate(new_obj)
85  new_obj%camp_core => camp_core
86 
87  ! Count the photolysis reactions
88  n_photo_rxns = 0
89  do i_mech = 1, size(camp_core%mechanism)
90  do i_rxn = 1, camp_core%mechanism(i_mech)%val%size()
91  rxn => camp_core%mechanism(i_mech)%val%get_rxn(i_rxn)
92  call assert(106297725, rxn%property_set%get_string(rxn_key, str_val))
93  if (trim(str_val) == rxn_val) n_photo_rxns = n_photo_rxns + 1
94  end do
95  end do
96 
97  ! Create update rate objects for photolysis reactions in all CAMP
98  ! mechanisms
99  i_photo_rxn = 0
100  allocate(new_obj%photo_rxns(n_photo_rxns))
101  allocate(new_obj%base_rates(n_photo_rxns))
102  do i_mech = 1, size(camp_core%mechanism)
103 
104  ! Loop through all reactions in mechanism to find photolysis reactions
105  do i_rxn = 1, camp_core%mechanism(i_mech)%val%size()
106  rxn => camp_core%mechanism(i_mech)%val%get_rxn(i_rxn)
107  call assert(799145523, rxn%property_set%get_string(rxn_key, str_val))
108 
109  ! Is this a photolysis reaction?
110  if (trim(str_val) /= rxn_val) cycle
111  i_photo_rxn = i_photo_rxn + 1
112 
113  ! Get the base photolysis rate
114  call assert_msg(501329648, &
115  rxn%property_set%get_real(rate_key, rate_val), &
116  "Missing 'base rate' for photolysis reaction "// &
117  trim(integer_to_string(i_photo_rxn)))
118  new_obj%base_rates(i_photo_rxn) = rate_val
119 
120  ! Create an update rate object for this photolysis reaction
121  select type (rxn_photo => rxn)
122  class is (rxn_photolysis_t)
123  call camp_core%initialize_update_object(rxn_photo, &
124  new_obj%photo_rxns(i_photo_rxn))
125  class default
126  call die(722633162)
127  end select
128  end do
129  end do
130 
131  end function constructor
132 
133 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
134 
135  !> Update the photolysis rates
136  subroutine update_rate_constants(this)
137 
138  !> Photolysis calculator
139  class(photolysis_t), intent(inout) :: this
140 
141  integer :: i_rxn
142 
143  ! NOTE: Update this after connection to a real photolysis module
144  do i_rxn = 1, size(this%photo_rxns)
145  call this%photo_rxns(i_rxn)%set_rate(this%base_rates(i_rxn))
146  call this%camp_core%update_data(this%photo_rxns(i_rxn))
147  end do
148 
149  end subroutine update_rate_constants
150 
151 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
152 
153  !> Determine the size of a binary required to pack the photolysis data
154  integer function pack_size(this, comm)
155 
156  use pmc_mpi
157 
158  !> Photolysis calculator
159  class(photolysis_t), intent(in) :: this
160  !> MPI communicator
161  integer, intent(in), optional :: comm
162 
163  integer :: i_rxn, l_comm
164 
165 #ifdef PMC_USE_MPI
166  if (present(comm)) then
167  l_comm = comm
168  else
169  l_comm = mpi_comm_world
170  endif
171 
172  call assert(127027009, allocated(this%base_rates))
173  call assert(634138948, allocated(this%photo_rxns))
174 
175  pack_size = &
176  pmc_mpi_pack_size_real_array(this%base_rates, l_comm) + &
177  pmc_mpi_pack_size_integer(size(this%photo_rxns), l_comm)
178 
179  do i_rxn = 1, size(this%photo_rxns)
180  pack_size = pack_size + this%photo_rxns(i_rxn)%pack_size(l_comm)
181  end do
182 #else
183  pack_size = 0
184 #endif
185 
186  end function pack_size
187 
188 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
189 
190  !> Pack the given value to the buffer, advancing position
191  subroutine bin_pack(this, buffer, pos, comm)
192 
193  use pmc_mpi
194 
195  !> Photolysis calculator
196  class(photolysis_t), intent(in) :: this
197  !> Memory buffer
198  character, intent(inout) :: buffer(:)
199  !> Current buffer position
200  integer, intent(inout) :: pos
201  !> MPI communicator
202  integer, intent(in), optional :: comm
203 
204 #ifdef PMC_USE_MPI
205  integer :: l_comm, i_rxn, prev_position
206 
207  if (present(comm)) then
208  l_comm = comm
209  else
210  l_comm = mpi_comm_world
211  endif
212 
213  call assert(971093983, allocated(this%base_rates))
214  call assert(913255424, allocated(this%photo_rxns))
215 
216  prev_position = pos
217  call pmc_mpi_pack_real_array(buffer, pos, this%base_rates, l_comm)
218  call pmc_mpi_pack_integer(buffer, pos, size(this%photo_rxns), l_comm)
219  do i_rxn = 1, size(this%photo_rxns)
220  call this%photo_rxns(i_rxn)%bin_pack(buffer, pos, l_comm)
221  end do
222  call assert(234533342, pos - prev_position <= this%pack_size(l_comm))
223 #endif
224 
225  end subroutine bin_pack
226 
227 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
228 
229  !> Pack the given value to the buffer, advancing position
230  subroutine bin_unpack(this, buffer, pos, comm)
231 
232  use pmc_mpi
233 
234  !> Photolysis calculator
235  class(photolysis_t), intent(out) :: this
236  !> Memory buffer
237  character, intent(inout) :: buffer(:)
238  !> Current buffer position
239  integer, intent(inout) :: pos
240  !> MPI communicator
241  integer, intent(in), optional :: comm
242 
243 #ifdef PMC_USE_MPI
244  integer :: l_comm, i_rxn, n_rxns, prev_position
245 
246  if (present(comm)) then
247  l_comm = comm
248  else
249  l_comm = mpi_comm_world
250  endif
251 
252  prev_position = pos
253  call pmc_mpi_unpack_real_array(buffer, pos, this%base_rates, l_comm)
254  call pmc_mpi_unpack_integer(buffer, pos, n_rxns, l_comm)
255  allocate(this%photo_rxns(n_rxns))
256  do i_rxn = 1, size(this%photo_rxns)
257  call this%photo_rxns(i_rxn)%bin_unpack(buffer, pos, l_comm)
258  end do
259  call assert(391255154, pos - prev_position <= this%pack_size(l_comm))
260 #endif
261 
262  end subroutine bin_unpack
263 
264 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
265 
266  !> Print the photolysis data
267  subroutine do_print(this, file_unit)
268 
269  !> Photolysis calculator
270  class(photolysis_t), intent(in) :: this
271  !> File unit for output
272  integer, optional :: file_unit
273 
274  integer :: f_unit, i_rxn
275 
276  f_unit = 6
277  if (present(file_unit)) f_unit = file_unit
278 
279  write(f_unit,*) "***************************"
280  write(f_unit,*) "*** Photolysis Data ***"
281  write(f_unit,*) "***************************"
282  write(f_unit,*) ""
283  if (allocated(this%base_rates)) then
284  do i_rxn = 1, size(this%base_rates)
285  write(f_unit,*) " photo rxn(",i_rxn,") = ", this%base_rates(i_rxn)
286  end do
287  else
288  write(f_unit,*) " No photolysis data"
289  end if
290  write(f_unit,*) ""
291  write(f_unit,*) "***************************"
292  write(f_unit,*) "*** End Photolysis Data ***"
293  write(f_unit,*) "***************************"
294 
295  end subroutine do_print
296 
297 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
298 #endif
299 end module pmc_photolysis
pmc_mpi
Wrapper functions for MPI.
Definition: mpi.F90:13
pmc_constants::dp
integer, parameter dp
Kind of a double precision real number.
Definition: constants.F90:12
pmc_util::assert
subroutine assert(code, condition_ok)
Errors unless condition_ok is true.
Definition: util.F90:103
pmc_mpi::pmc_mpi_pack_size_real_array
integer function pmc_mpi_pack_size_real_array(val)
Determines the number of bytes required to pack the given value.
Definition: mpi.F90:477
pmc_util::integer_to_string
character(len=pmc_util_convert_string_len) function integer_to_string(val)
Convert an integer to a string format.
Definition: util.F90:766
pmc_util::assert_msg
subroutine assert_msg(code, condition_ok, error_msg)
Errors unless condition_ok is true.
Definition: util.F90:77
pmc_photolysis
The photolysis_t type and related functions.
Definition: photolysis.F90:9
pmc_mpi::pmc_mpi_unpack_integer
subroutine pmc_mpi_unpack_integer(buffer, position, val)
Unpacks the given value from the buffer, advancing position.
Definition: mpi.F90:818
pmc_constants
Physical constants.
Definition: constants.F90:9
pmc_util
Common utility subroutines.
Definition: util.F90:9
pmc_mpi::pmc_mpi_pack_size_integer
integer function pmc_mpi_pack_size_integer(val)
Determines the number of bytes required to pack the given value.
Definition: mpi.F90:345
pmc_mpi::pmc_mpi_pack_integer
subroutine pmc_mpi_pack_integer(buffer, position, val)
Packs the given value into the buffer, advancing position.
Definition: mpi.F90:561
pmc_util::die
subroutine die(code)
Error immediately.
Definition: util.F90:122
pmc_mpi::pmc_mpi_pack_real_array
subroutine pmc_mpi_pack_real_array(buffer, position, val)
Packs the given value into the buffer, advancing position.
Definition: mpi.F90:720
pmc_mpi::pmc_mpi_unpack_real_array
subroutine pmc_mpi_unpack_real_array(buffer, position, val)
Unpacks the given value from the buffer, advancing position.
Definition: mpi.F90:978