PartMC  2.6.1
coagulation_dist.F90
Go to the documentation of this file.
1 ! Copyright (C) 2005-2012 Nicole Riemer and Matthew West
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 !> The pmc_coagulation_dist module.
7 
8 !> Parallel aerosol particle coagulation with MPI
10 
11  use pmc_bin_grid
12  use pmc_aero_data
13  use pmc_util
14  use pmc_env_state
15  use pmc_aero_state
17  use pmc_coagulation
18  use pmc_mpi
19 #ifdef PMC_USE_MPI
20  use mpi
21 #endif
22 
23  !> Size of the outgoing buffer for \c bsend (bytes).
24  !!
25  !! FIXME: check that this size is big enough. It must be large
26  !! enough to handle the required number of messages of the given
27  !! sizes, plus MPI_BSEND_OVERHEAD per message, plus some extra room
28  !! because it's only kind of a circular buffer --- the messages
29  !! themselves aren't allowed to wrap around then end, so we might
30  !! need extra space up to the size of the largest message type.
31  integer, parameter :: coag_dist_outgoing_buffer_size = 1000000
32  !> Size of send and receive buffer for each message (bytes).
33  !!
34  !! The biggest message type will be one of the particle-sending
35  !! types, for which we need pmc_mpi_pack_size_aero_particle(), plus
36  !! a couple of integers or something. At the moment this means
37  !! something like (10 + n_spec) reals, (3 + 2) integers, which for
38  !! n_spec = 20 gives a size of 260 bytes.
39  integer, parameter :: coag_dist_max_buffer_size = 10000
40  integer, parameter :: coag_dist_max_requests = 1
41  integer, parameter :: coag_dist_tag_request_particle = 5321
42  integer, parameter :: coag_dist_tag_return_req_particle = 5322
43  integer, parameter :: coag_dist_tag_return_unreq_particle = 5323
44  integer, parameter :: coag_dist_tag_return_no_particle = 5324
45  integer, parameter :: coag_dist_tag_done = 5325
46 
47  !> A single outstanding request for a remote particle.
48  type request_t
49  !> Local \c aero_particle to maybe coagulate with the received
50  !> particle.
51  type(aero_particle_t) :: local_aero_particle
52  !> Remote process number that we sent the request to
53  !> (-1 means this request is currently not used).
54  integer :: remote_proc
55  !> Local bin number from which we took \c local_aero_particle.
56  integer :: local_bin
57  !> Remote bin number from which we requested an \c aero_particle.
58  integer :: remote_bin
59  !> Whether this request is currently active
60  logical :: active
61  end type request_t
62 
63 contains
64 
65 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
66 
67  ! Allocate a request object and set its state to invalid.
68  subroutine request_allocate(request)
69 
70  !> Request object to allocate.
71  type(request_t), intent(out) :: request
72 
73  request%active = .false.
74 
75  end subroutine request_allocate
76 
77 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
78 
79  !> Deallocate a request object and set it to be invalid.
80  subroutine request_deallocate(request)
81 
82  !> Request object to deallocate
83  type(request_t), intent(inout) :: request
84 
85  request%active = .false.
86 
87  end subroutine request_deallocate
88 
89 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
90 
91  !> Whether the given reqest object is currectly active.
92  logical function request_is_active(request)
93 
94  !> Request object to test for activeness.
95  type(request_t), intent(in) :: request
96 
97  request_is_active = request%active
98 
99  end function request_is_active
100 
101 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
102 
103  !> Do coagulation for time del_t.
104  subroutine mc_coag_dist(coag_kernel_type, env_state, aero_data, &
105  aero_state, del_t, tot_n_samp, tot_n_coag)
106 
107  !> Coagulation kernel type.
108  integer, intent(in) :: coag_kernel_type
109  !> Environment state.
110  type(env_state_t), intent(in) :: env_state
111  !> Aerosol data.
112  type(aero_data_t), intent(in) :: aero_data
113  !> Aerosol state.
114  type(aero_state_t), intent(inout) :: aero_state
115  !> Timestep.
116  real(kind=dp), intent(in) :: del_t
117  !> Total number of samples tested.
118  integer, intent(out) :: tot_n_samp
119  !> Number of coagulation events.
120  integer, intent(out) :: tot_n_coag
121 
122  integer, parameter :: s1 = 1
123  integer, parameter :: s2 = 1
124  integer, parameter :: sc = 1
125 
126 #ifdef PMC_USE_MPI
127  logical :: samps_remaining, sent_dones
128  integer :: i_bin, j_bin, n_samp, i_samp, i_proc, n_proc
129  integer :: ierr, status(MPI_STATUS_SIZE), current_i, current_j, i_req
130  real(kind=dp) :: n_samp_real, f_max
131  integer, allocatable :: n_parts(:,:)
132  real(kind=dp), allocatable :: magnitudes(:,:)
133  type(request_t) :: requests(coag_dist_max_requests)
134  integer, allocatable :: n_samps(:,:)
135  real(kind=dp), allocatable :: accept_factors(:,:), k_max(:,:)
136  logical, allocatable :: procs_done(:)
137  integer :: outgoing_buffer(COAG_DIST_OUTGOING_BUFFER_SIZE)
138  integer :: outgoing_buffer_size_check
139  type(aero_weight_array_t) :: aero_weight_total
140 
141  call assert_msg(667898741, &
142  aero_sorted_n_class(aero_state%aero_sorted) == 1, &
143  "FIXME: mc_coag_dist() can only handle one weight class")
144 
145  n_proc = pmc_mpi_size()
146 
147  call pmc_mpi_barrier()
148 
149  call aero_state_sort(aero_state, aero_data, all_procs_same=.true.)
150  if (.not. aero_state%aero_sorted%coag_kernel_bounds_valid) then
151  call est_k_minmax_binned_unweighted(aero_state%aero_sorted%bin_grid, &
152  coag_kernel_type, aero_data, env_state, &
153  aero_state%aero_sorted%coag_kernel_min, &
154  aero_state%aero_sorted%coag_kernel_max)
155  aero_state%aero_sorted%coag_kernel_bounds_valid = .true.
156  end if
157 
158  allocate(n_samps(bin_grid_size(aero_state%aero_sorted%bin_grid), &
159  bin_grid_size(aero_state%aero_sorted%bin_grid)))
160  allocate(accept_factors(bin_grid_size(aero_state%aero_sorted%bin_grid), &
161  bin_grid_size(aero_state%aero_sorted%bin_grid)))
162 
163  allocate(n_parts(bin_grid_size(aero_state%aero_sorted%bin_grid), n_proc))
164  call pmc_mpi_allgather_integer_array(integer_varray_n_entry( &
165  aero_state%aero_sorted%size_class%inverse(:, s1)), n_parts)
166 
167  allocate(magnitudes(size(aero_state%awa%weight), n_proc))
168  call pmc_mpi_allgather_real_array(aero_state%awa%weight(:, s1)%magnitude, &
169  magnitudes)
170 
171  aero_weight_total = aero_state%awa
172  aero_weight_total%weight(:, s1)%magnitude = 1d0 / sum(1d0 / magnitudes, 2)
173 
174  allocate(k_max(bin_grid_size(aero_state%aero_sorted%bin_grid), &
175  bin_grid_size(aero_state%aero_sorted%bin_grid)))
176  do i_bin = 1,bin_grid_size(aero_state%aero_sorted%bin_grid)
177  do j_bin = 1,bin_grid_size(aero_state%aero_sorted%bin_grid)
178  call max_coag_num_conc_factor(aero_weight_total, &
179  aero_data, aero_state%aero_sorted%bin_grid, &
180  i_bin, j_bin, s1, s2, sc, f_max)
181  k_max(i_bin, j_bin) &
182  = aero_state%aero_sorted%coag_kernel_max(i_bin, j_bin) * f_max
183  end do
184  end do
185 
186  call generate_n_samps(n_parts, del_t, aero_state%aero_sorted%bin_grid, &
187  aero_weight_total, k_max, n_samps, accept_factors)
188  tot_n_samp = sum(n_samps)
189  tot_n_coag = 0
190 
191  ! main loop
192  do i_req = 1,coag_dist_max_requests
193  call request_allocate(requests(i_req))
194  end do
195  samps_remaining = .true.
196  current_i = 1
197  current_j = 1
198  allocate(procs_done(n_proc))
199  procs_done = .false.
200  sent_dones = .false.
201  call mpi_buffer_attach(outgoing_buffer, &
202  coag_dist_outgoing_buffer_size, ierr)
203  call pmc_mpi_check_ierr(ierr)
204  do while (.not. all(procs_done))
205  ! add requests if we have any slots available call
206  call add_coagulation_requests(aero_state, requests, n_parts, &
207  current_i, current_j, n_samps, samps_remaining)
208 
209  ! if we have no outstanding requests, send done messages
210  if (.not. sent_dones) then
211  if (.not. any_requests_active(requests)) then
212  sent_dones = .true.
213  do i_proc = 0, (n_proc - 1)
214  call send_done(i_proc)
215  end do
216  end if
217  end if
218 
219  ! receive exactly one message
220  call coag_dist_recv(requests, env_state, aero_weight_total, aero_data, &
221  aero_state, accept_factors, coag_kernel_type, tot_n_coag, &
222  magnitudes, procs_done)
223  end do
224 
225  do i_req = 1,coag_dist_max_requests
226  call assert(502009333, .not. request_is_active(requests(i_req)))
227  call request_deallocate(requests(i_req))
228  end do
229  deallocate(procs_done)
230  deallocate(n_samps)
231  deallocate(accept_factors)
232  deallocate(n_parts)
233  deallocate(magnitudes)
234  call mpi_buffer_detach(outgoing_buffer, &
235  outgoing_buffer_size_check, ierr)
236  call pmc_mpi_check_ierr(ierr)
237  call assert(577822730, &
238  coag_dist_outgoing_buffer_size == outgoing_buffer_size_check)
239 #endif
240 
241  end subroutine mc_coag_dist
242 
243 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
244 
245  subroutine coag_dist_recv(requests, env_state, aero_weight_total, &
246  aero_data, aero_state, accept_factors, coag_kernel_type, tot_n_coag, &
247  magnitudes, procs_done)
248 
249  !> Array of outstanding requests.
250  type(request_t), intent(inout) :: requests(COAG_DIST_MAX_REQUESTS)
251  !> Environment state.
252  type(env_state_t), intent(in) :: env_state
253  !> Total weighting functions.
254  type(aero_weight_array_t), intent(in) :: aero_weight_total
255  !> Aerosol data.
256  type(aero_data_t), intent(in) :: aero_data
257  !> Aerosol state.
258  type(aero_state_t), intent(inout) :: aero_state
259  !> Accept scale factors per bin pair (1).
260  real(kind=dp), intent(in) :: accept_factors(:,:)
261  !> Coagulation kernel type.
262  integer, intent(in) :: coag_kernel_type
263  !> Number of coagulation events.
264  integer, intent(inout) :: tot_n_coag
265  !> Computational volumes on all processes.
266  real(kind=dp), intent(in) :: magnitudes(:,:)
267  !> Which processes are finished with coagulation.
268  logical, intent(inout) :: procs_done(:)
269 
270 #ifdef PMC_USE_MPI
271  integer :: status(MPI_STATUS_SIZE), ierr
272 
273  call mpi_probe(mpi_any_source, mpi_any_tag, mpi_comm_world, &
274  status, ierr)
275  call pmc_mpi_check_ierr(ierr)
276  if (status(mpi_tag) == coag_dist_tag_request_particle) then
277  call recv_request_particle(aero_state)
278  elseif (status(mpi_tag) == coag_dist_tag_return_req_particle) then
279  call recv_return_req_particle(requests, env_state, aero_weight_total, &
280  aero_data, aero_state, accept_factors, coag_kernel_type, &
281  tot_n_coag, magnitudes)
282  elseif (status(mpi_tag) == coag_dist_tag_return_unreq_particle) then
283  call recv_return_unreq_particle(aero_state, aero_data)
284  elseif (status(mpi_tag) == coag_dist_tag_return_no_particle) then
285  call recv_return_no_particle(requests, aero_data, aero_state)
286  elseif (status(mpi_tag) == coag_dist_tag_done) then
287  call recv_done(procs_done)
288  else
289  call die_msg(856123972, &
290  'unknown tag: ' // trim(integer_to_string(status(mpi_tag))))
291  end if
292 #endif
293 
294  end subroutine coag_dist_recv
295 
296 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
297 
298  subroutine add_coagulation_requests(aero_state, requests, n_parts, &
299  local_bin, remote_bin, n_samps, samps_remaining)
300 
301  !> Aerosol state.
302  type(aero_state_t), intent(inout) :: aero_state
303  !> Array of outstanding requests.
304  type(request_t), intent(inout) :: requests(COAG_DIST_MAX_REQUESTS)
305  !> Number of particles per bin per process.
306  integer, intent(in) :: n_parts(:,:)
307  !> Bin index of first particle we need to coagulate.
308  integer, intent(inout) :: local_bin
309  !> Bin index of second particle we need to coagulate.
310  integer, intent(inout) :: remote_bin
311  !> Number of samples remaining per bin pair
312  integer, intent(inout) :: n_samps(:,:)
313  !> Whether there are still coagulation samples that need to be done.
314  logical, intent(inout) :: samps_remaining
315 
316  integer, parameter :: s1 = 1
317  integer, parameter :: s2 = 1
318  integer, parameter :: sc = 1
319 
320  integer :: i_req
321 
322  if (.not. samps_remaining) return
323 
324  outer: do i_req = 1,coag_dist_max_requests
325  if (.not. request_is_active(requests(i_req))) then
326  inner: do
327  call update_n_samps(n_samps, local_bin, remote_bin, &
328  samps_remaining)
329  if (.not. samps_remaining) exit outer
330  if (integer_varray_n_entry( &
331  aero_state%aero_sorted%size_class%inverse(local_bin, s2)) &
332  > 0) then
333  call find_rand_remote_proc(n_parts, remote_bin, &
334  requests(i_req)%remote_proc)
335  requests(i_req)%active = .true.
336  requests(i_req)%local_bin = local_bin
337  requests(i_req)%remote_bin = remote_bin
339  local_bin, s2, requests(i_req)%local_aero_particle)
340  call send_request_particle(requests(i_req)%remote_proc, &
341  requests(i_req)%remote_bin)
342  exit inner
343  end if
344  end do inner
345  end if
346  end do outer
347 
348  end subroutine add_coagulation_requests
349 
350 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
351 
352  !> Returns \c .true. if any of the requests are active, otherwise
353  !> returns \c .false.
354  logical function any_requests_active(requests)
355 
356  !> Array of outstanding requests.
357  type(request_t), intent(inout) :: requests(coag_dist_max_requests)
358 
359  integer :: i_req
360 
361  do i_req = 1,coag_dist_max_requests
362  if (request_is_active(requests(i_req))) then
363  any_requests_active = .true.
364  return
365  end if
366  end do
367  any_requests_active = .false.
368 
369  end function any_requests_active
370 
371 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
372 
373  subroutine find_rand_remote_proc(n_parts, remote_bin, remote_proc)
374 
375  !> Number of particles per bin per process.
376  integer, intent(in) :: n_parts(:,:)
377  !> Remote bin number.
378  integer, intent(in) :: remote_bin
379  !> Remote process number chosen at random.
380  integer, intent(out) :: remote_proc
381 
382 #ifdef PMC_USE_MPI
383  call assert(770964285, size(n_parts, 2) == pmc_mpi_size())
384  remote_proc = sample_disc_pdf(n_parts(remote_bin, :)) - 1
385 #endif
386 
387  end subroutine find_rand_remote_proc
388 
389 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
390 
391  subroutine update_n_samps(n_samps, local_bin, remote_bin, samps_remaining)
392 
393  !> Number of samples remaining per bin pair
394  integer, intent(inout) :: n_samps(:,:)
395  !> Bin index of first particle we need to coagulate.
396  integer, intent(inout) :: local_bin
397  !> Bin index of second particle we need to coagulate.
398  integer, intent(inout) :: remote_bin
399  !> Whether there are still coagulation samples that need to be done.
400  logical, intent(inout) :: samps_remaining
401 
402  integer :: n_bin
403 
404  if (.not. samps_remaining) return
405 
406  n_bin = size(n_samps, 1)
407  do
408  if (n_samps(local_bin, remote_bin) > 0) exit
409 
410  remote_bin = remote_bin + 1
411  if (remote_bin > n_bin) then
412  remote_bin = 1
413  local_bin = local_bin + 1
414  end if
415  if (local_bin > n_bin) exit
416  end do
417 
418  if (local_bin > n_bin) then
419  samps_remaining = .false.
420  else
421  n_samps(local_bin, remote_bin) = n_samps(local_bin, remote_bin) - 1
422  end if
423 
424  end subroutine update_n_samps
425 
426 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
427 
428  subroutine send_request_particle(remote_proc, remote_bin)
429 
430  !> Remote process number.
431  integer, intent(in) :: remote_proc
432  !> Remote bin number.
433  integer, intent(in) :: remote_bin
434 
435 #ifdef PMC_USE_MPI
436  character :: buffer(COAG_DIST_MAX_BUFFER_SIZE)
437  integer :: buffer_size, max_buffer_size, position, ierr
438 
439  max_buffer_size = 0
440  max_buffer_size = max_buffer_size + pmc_mpi_pack_size_integer(remote_bin)
441  call assert(893545122, max_buffer_size <= coag_dist_max_buffer_size)
442  position = 0
443  call pmc_mpi_pack_integer(buffer, position, remote_bin)
444  call assert(610314213, position <= max_buffer_size)
445  buffer_size = position
446  call mpi_bsend(buffer, buffer_size, mpi_character, remote_proc, &
447  coag_dist_tag_request_particle, mpi_comm_world, ierr)
448  call pmc_mpi_check_ierr(ierr)
449 #endif
450 
451  end subroutine send_request_particle
452 
453 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
454 
455  subroutine recv_request_particle(aero_state)
456 
457  !> Aero state.
458  type(aero_state_t), intent(inout) :: aero_state
459 
460  integer, parameter :: s1 = 1
461  integer, parameter :: s2 = 1
462  integer, parameter :: sc = 1
463 
464 #ifdef PMC_USE_MPI
465  integer :: buffer_size, position, request_bin, sent_proc
466  integer :: ierr, remote_proc, status(MPI_STATUS_SIZE)
467  character :: buffer(COAG_DIST_MAX_BUFFER_SIZE)
468  type(aero_particle_t) :: aero_particle
469 
470  ! get the message
471  call mpi_recv(buffer, coag_dist_max_buffer_size, mpi_character, &
472  mpi_any_source, coag_dist_tag_request_particle, mpi_comm_world, &
473  status, ierr)
474  call pmc_mpi_check_ierr(ierr)
475  call assert(920139874, status(mpi_tag) &
477  call mpi_get_count(status, mpi_character, buffer_size, ierr)
478  call pmc_mpi_check_ierr(ierr)
479  call assert(190658659, buffer_size <= coag_dist_max_buffer_size)
480  remote_proc = status(mpi_source)
481 
482  ! unpack it
483  position = 0
484  call pmc_mpi_unpack_integer(buffer, position, request_bin)
485  call assert(895128380, position == buffer_size)
486 
487  ! send the particle back if we have one
488  if (integer_varray_n_entry( &
489  aero_state%aero_sorted%size_class%inverse(request_bin, s1)) == 0) then
490  call send_return_no_particle(remote_proc, request_bin)
491  else
493  request_bin, s1, aero_particle)
494  call send_return_req_particle(aero_particle, request_bin, &
495  remote_proc)
496  end if
497 #endif
498 
499  end subroutine recv_request_particle
500 
501 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
502 
503  subroutine send_return_no_particle(dest_proc, i_bin)
504 
505  !> Process number to send message to.
506  integer, intent(in) :: dest_proc
507  !> Bin number where there was no particle.
508  integer, intent(in) :: i_bin
509 
510 #ifdef PMC_USE_MPI
511  character :: buffer(COAG_DIST_MAX_BUFFER_SIZE)
512  integer :: buffer_size, max_buffer_size, position, ierr
513 
514  max_buffer_size = 0
515  max_buffer_size = max_buffer_size + pmc_mpi_pack_size_integer(i_bin)
516  call assert(744787119, max_buffer_size <= coag_dist_max_buffer_size)
517  position = 0
518  call pmc_mpi_pack_integer(buffer, position, i_bin)
519  call assert(445960340, position <= max_buffer_size)
520  buffer_size = position
521  call mpi_bsend(buffer, buffer_size, mpi_character, dest_proc, &
522  coag_dist_tag_return_no_particle, mpi_comm_world, ierr)
523  call pmc_mpi_check_ierr(ierr)
524 #endif
525 
526  end subroutine send_return_no_particle
527 
528 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
529 
530  subroutine recv_return_no_particle(requests, aero_data, aero_state)
531 
532  !> Array of outstanding requests.
533  type(request_t), intent(inout) :: requests(COAG_DIST_MAX_REQUESTS)
534  !> Aerosol data.
535  type(aero_data_t), intent(in) :: aero_data
536  !> Aerosol state.
537  type(aero_state_t), intent(inout) :: aero_state
538 
539 #ifdef PMC_USE_MPI
540  logical :: found_request
541  integer :: buffer_size, position, sent_bin, sent_proc, i_req
542  integer :: ierr, status(MPI_STATUS_SIZE)
543  character :: buffer(COAG_DIST_MAX_BUFFER_SIZE)
544 
545  ! get the message
546  call mpi_recv(buffer, coag_dist_max_buffer_size, mpi_character, &
547  mpi_any_source, coag_dist_tag_return_no_particle, &
548  mpi_comm_world, status, ierr)
549  call pmc_mpi_check_ierr(ierr)
550  call assert(918153221, status(mpi_tag) &
552  call mpi_get_count(status, mpi_character, buffer_size, ierr)
553  call pmc_mpi_check_ierr(ierr)
554  call assert(461111487, buffer_size <= coag_dist_max_buffer_size)
555  sent_proc = status(mpi_source)
556 
557  ! unpack it
558  position = 0
559  call pmc_mpi_unpack_integer(buffer, position, sent_bin)
560  call assert(518172999, position == buffer_size)
561 
562  ! find the matching request
563  found_request = .false.
564  do i_req = 1,coag_dist_max_requests
565  if ((requests(i_req)%remote_proc == sent_proc) &
566  .and. (requests(i_req)%remote_bin == sent_bin)) then
567  found_request = .true.
568  exit
569  end if
570  end do
571  call assert(215612776, found_request)
572 
573  ! We can't do coagulation with the local particle, so store it
574  ! back. If we wanted to, we could use the knowledge that it should
575  ! go into bin requests(i_req)%local_bin
576  call aero_state_add_particle(aero_state, &
577  requests(i_req)%local_aero_particle, aero_data, &
578  allow_resort=.false.)
579  call request_deallocate(requests(i_req))
580  call request_allocate(requests(i_req))
581 #endif
582 
583  end subroutine recv_return_no_particle
584 
585 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
586 
587  subroutine send_return_req_particle(aero_particle, i_bin, dest_proc)
588 
589  !> Aero particle to send.
590  type(aero_particle_t), intent(in) :: aero_particle
591  !> Bin that the particle is in.
592  integer, intent(in) :: i_bin
593  !> Process number to send particle to.
594  integer, intent(in) :: dest_proc
595 
596 #ifdef PMC_USE_MPI
597  character :: buffer(COAG_DIST_MAX_BUFFER_SIZE)
598  integer :: buffer_size, max_buffer_size, position, ierr
599 
600  max_buffer_size = 0
601  max_buffer_size = max_buffer_size + pmc_mpi_pack_size_integer(i_bin)
602  max_buffer_size = max_buffer_size &
603  + pmc_mpi_pack_size_aero_particle(aero_particle)
604  call assert(496283814, max_buffer_size <= coag_dist_max_buffer_size)
605  position = 0
606  call pmc_mpi_pack_integer(buffer, position, i_bin)
607  call pmc_mpi_pack_aero_particle(buffer, position, aero_particle)
608  call assert(263666386, position <= max_buffer_size)
609  buffer_size = position
610  call mpi_bsend(buffer, buffer_size, mpi_character, dest_proc, &
611  coag_dist_tag_return_req_particle, mpi_comm_world, ierr)
612  call pmc_mpi_check_ierr(ierr)
613 #endif
614 
615  end subroutine send_return_req_particle
616 
617 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
618 
619  subroutine recv_return_req_particle(requests, env_state, aero_weight_total, &
620  aero_data, aero_state, accept_factors, coag_kernel_type, tot_n_coag, &
621  magnitudes)
622 
623  !> Array of outstanding requests.
624  type(request_t), intent(inout) :: requests(COAG_DIST_MAX_REQUESTS)
625  !> Environment state.
626  type(env_state_t), intent(in) :: env_state
627  !> Total weighting array.
628  type(aero_weight_array_t), intent(in) :: aero_weight_total
629  !> Aerosol data.
630  type(aero_data_t), intent(in) :: aero_data
631  !> Aerosol state.
632  type(aero_state_t), intent(inout) :: aero_state
633  !> Accept scale factors per bin pair (1).
634  real(kind=dp), intent(in) :: accept_factors(:,:)
635  !> Coagulation kernel type.
636  integer, intent(in) :: coag_kernel_type
637  !> Number of coagulation events.
638  integer, intent(inout) :: tot_n_coag
639  !> Computational volumes on all processes.
640  real(kind=dp), intent(in) :: magnitudes(:,:)
641 
642  integer, parameter :: s1 = 1
643  integer, parameter :: s2 = 1
644  integer, parameter :: sc = 1
645 
646 #ifdef PMC_USE_MPI
647  logical :: found_request, remove_1, remove_2
648  integer :: buffer_size, position, sent_bin, sent_proc, i_req
649  integer :: ierr, status(MPI_STATUS_SIZE)
650  character :: buffer(COAG_DIST_MAX_BUFFER_SIZE)
651  type(aero_particle_t) :: sent_aero_particle
652  real(kind=dp) :: k, p
653 
654  ! get the message
655  call mpi_recv(buffer, coag_dist_max_buffer_size, mpi_character, &
656  mpi_any_source, coag_dist_tag_return_req_particle, &
657  mpi_comm_world, status, ierr)
658  call pmc_mpi_check_ierr(ierr)
659  call assert(133285061, status(mpi_tag) &
661  call mpi_get_count(status, mpi_character, buffer_size, ierr)
662  call pmc_mpi_check_ierr(ierr)
663  call assert(563012836, buffer_size <= coag_dist_max_buffer_size)
664  sent_proc = status(mpi_source)
665 
666  ! unpack it
667  position = 0
668  call pmc_mpi_unpack_integer(buffer, position, sent_bin)
669  call pmc_mpi_unpack_aero_particle(buffer, position, sent_aero_particle)
670  call assert(753356021, position == buffer_size)
671 
672  ! find the matching request
673  found_request = .false.
674  do i_req = 1,coag_dist_max_requests
675  if ((requests(i_req)%remote_proc == sent_proc) &
676  .and. (requests(i_req)%remote_bin == sent_bin)) then
677  found_request = .true.
678  exit
679  end if
680  end do
681  call assert(579308475, found_request)
682 
683  ! maybe do coagulation
684  call num_conc_weighted_kernel(coag_kernel_type, &
685  requests(i_req)%local_aero_particle, sent_aero_particle, &
686  s1, s2, sc, aero_data, aero_weight_total, env_state, k)
687  p = k * accept_factors(requests(i_req)%local_bin, sent_bin)
688 
689  if (pmc_random() .lt. p) then
690  ! coagulation happened, do it
691  tot_n_coag = tot_n_coag + 1
692  call coagulate_dist(aero_data, aero_state, &
693  requests(i_req)%local_aero_particle, sent_aero_particle, &
694  sent_proc, aero_weight_total, magnitudes, remove_1, remove_2)
695  else
696  remove_1 = .false.
697  remove_2 = .false.
698  end if
699 
700  ! send the particles back
701  if (.not. remove_1) then
702  ! If we wanted to, we could use the knowledge that this will go
703  ! into bin requests(i_req)%local_bin
704  call aero_state_add_particle(aero_state, &
705  requests(i_req)%local_aero_particle, aero_data, &
706  allow_resort=.false.)
707  end if
708  if (.not. remove_2) then
709  call send_return_unreq_particle(sent_aero_particle, sent_proc)
710  end if
711 
712  call request_deallocate(requests(i_req))
713  call request_allocate(requests(i_req))
714 #endif
715 
716  end subroutine recv_return_req_particle
717 
718 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
719 
720  subroutine send_return_unreq_particle(aero_particle, dest_proc)
721 
722  !> Aero particle to send.
723  type(aero_particle_t), intent(in) :: aero_particle
724  !> Process to send the particle to.
725  integer, intent(in) :: dest_proc
726 
727 #ifdef PMC_USE_MPI
728  character :: buffer(coag_dist_max_buffer_size)
729  integer :: buffer_size, max_buffer_size, position, ierr
730 
731  max_buffer_size = 0
732  max_buffer_size = max_buffer_size &
733  + pmc_mpi_pack_size_aero_particle(aero_particle)
734  call assert(414990602, max_buffer_size <= coag_dist_max_buffer_size)
735  position = 0
736  call pmc_mpi_pack_aero_particle(buffer, position, aero_particle)
737  call assert(898537822, position <= max_buffer_size)
738  buffer_size = position
739  call mpi_bsend(buffer, buffer_size, mpi_character, dest_proc, &
740  coag_dist_tag_return_unreq_particle, mpi_comm_world, ierr)
741  call pmc_mpi_check_ierr(ierr)
742 #endif
743 
744  end subroutine send_return_unreq_particle
745 
746 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
747 
748  subroutine recv_return_unreq_particle(aero_state, aero_data)
749 
750  !> Aerosol state.
751  type(aero_state_t), intent(inout) :: aero_state
752  !> Aerosol data.
753  type(aero_data_t), intent(in) :: aero_data
754 
755 #ifdef PMC_USE_MPI
756  logical :: found_request
757  integer :: buffer_size, position, sent_proc, ierr
758  character :: buffer(COAG_DIST_MAX_BUFFER_SIZE)
759  type(aero_particle_t) :: aero_particle
760  integer :: status(MPI_STATUS_SIZE), send_proc
761 
762  ! get the message
763  call mpi_recv(buffer, coag_dist_max_buffer_size, mpi_character, &
764  mpi_any_source, coag_dist_tag_return_unreq_particle, &
765  mpi_comm_world, status, ierr)
766  call pmc_mpi_check_ierr(ierr)
767  call assert(496247788, status(mpi_tag) &
769  call mpi_get_count(status, mpi_character, buffer_size, ierr)
770  call pmc_mpi_check_ierr(ierr)
771  call assert(590644042, buffer_size <= coag_dist_max_buffer_size)
772  sent_proc = status(mpi_source)
773 
774  ! unpack it
775  position = 0
776  call pmc_mpi_unpack_aero_particle(buffer, position, aero_particle)
777  call assert(833588594, position == buffer_size)
778 
779  ! put it back
780  call aero_state_add_particle(aero_state, aero_particle, aero_data, &
781  allow_resort=.false.)
782 #endif
783 
784  end subroutine recv_return_unreq_particle
785 
786 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
787 
788  !> Send a message saying that this process is finished with its
789  !> coagulation.
790  subroutine send_done(dest_proc)
791 
792  !> Process to send the message to.
793  integer, intent(in) :: dest_proc
794 
795 #ifdef PMC_USE_MPI
796  character :: buffer(COAG_DIST_MAX_BUFFER_SIZE)
797  integer :: buffer_size, ierr
798 
799  buffer_size = 0
800  call mpi_bsend(buffer, buffer_size, mpi_character, dest_proc, &
801  coag_dist_tag_done, mpi_comm_world, ierr)
802  call pmc_mpi_check_ierr(ierr)
803 #endif
804 
805  end subroutine send_done
806 
807 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
808 
809  !> Receive a done message.
810  subroutine recv_done(procs_done)
811 
812  !> Which processes are finished with coagulation.
813  logical, intent(inout) :: procs_done(:)
814 
815 #ifdef PMC_USE_MPI
816  integer :: buffer_size, sent_proc, ierr
817  character :: buffer(COAG_DIST_MAX_BUFFER_SIZE)
818  integer :: status(MPI_STATUS_SIZE)
819 
820  ! get the message
821  call mpi_recv(buffer, coag_dist_max_buffer_size, mpi_character, &
822  mpi_any_source, coag_dist_tag_done, mpi_comm_world, &
823  status, ierr)
824  call pmc_mpi_check_ierr(ierr)
825  call assert(348737947, status(mpi_tag) &
827  call mpi_get_count(status, mpi_character, buffer_size, ierr)
828  call pmc_mpi_check_ierr(ierr)
829  call assert(214904056, buffer_size == 0)
830  sent_proc = status(mpi_source)
831 
832  ! process it
833  procs_done(sent_proc + 1) = .true.
834 #endif
835 
836  end subroutine recv_done
837 
838 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
839 
840  !> generate the number of samples to do per bin pair.
841  subroutine generate_n_samps(n_parts, del_t, bin_grid, aero_weight_array, &
842  k_max, n_samps, accept_factors)
843 
844  !> Number of particles per bin on all processes.
845  integer, intent(in) :: n_parts(:,:)
846  !> Timestep.
847  real(kind=dp), intent(in) :: del_t
848  !> Bin grid.
849  type(bin_grid_t), intent(in) :: bin_grid
850  !> Weighting function array.
851  type(aero_weight_array_t), intent(in) :: aero_weight_array
852  !> Maximum kernel.
853  real(kind=dp), intent(in) :: k_max(:,:)
854  !> Number of samples to do per bin pair.
855  integer, intent(out) :: n_samps(:,:)
856  !> Accept scale factors per bin pair (1).
857  real(kind=dp), intent(out) :: accept_factors(:,:)
858 
859  integer :: i_bin, j_bin, rank, n_bin
860  real(kind=dp) :: n_samp_mean
861 
862  n_bin = size(k_max, 1)
863  rank = pmc_mpi_rank()
864  n_samps = 0
865  do i_bin = 1,n_bin
866  if (n_parts(i_bin, rank + 1) == 0) &
867  cycle
868  do j_bin = i_bin,n_bin
869  call compute_n_samp(n_parts(i_bin, rank + 1), &
870  sum(n_parts(j_bin, :)), (i_bin == j_bin), &
871  k_max(i_bin, j_bin), del_t, n_samp_mean, &
872  n_samps(i_bin, j_bin), accept_factors(i_bin, j_bin))
873  end do
874  end do
875 
876  end subroutine generate_n_samps
877 
878 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
879 
880  subroutine coagulate_dist(aero_data, aero_state, aero_particle_1, &
881  aero_particle_2, remote_proc, aero_weight_total, magnitudes, &
882  remove_1, remove_2)
883 
884  !> Aerosol data.
885  type(aero_data_t), intent(in) :: aero_data
886  !> Aerosol state.
887  type(aero_state_t), intent(inout) :: aero_state
888  !> First particle to coagulate.
889  type(aero_particle_t), intent(in) :: aero_particle_1
890  !> Second particle to coagulate.
891  type(aero_particle_t), intent(in) :: aero_particle_2
892  !> Remote process that the particle came from.
893  integer, intent(in) :: remote_proc
894  !> Total weight across all processes.
895  type(aero_weight_array_t), intent(in) :: aero_weight_total
896  !> Computational volumes on all processes (m^3).
897  real(kind=dp), intent(in) :: magnitudes(:,:)
898  !> Whether to remove aero_particle_1 after the coagulation.
899  logical, intent(out) :: remove_1
900  !> Whether to remove aero_particle_2 after the coagulation.
901  logical, intent(out) :: remove_2
902 
903  integer, parameter :: s1 = 1
904  integer, parameter :: s2 = 1
905  integer, parameter :: sc = 1
906 
907  type(aero_particle_t) :: aero_particle_new
908  integer :: new_proc, new_group
909  type(aero_info_t) :: aero_info_1, aero_info_2
910  logical :: create_new, id_1_lost, id_2_lost
911 
912  call coagulate_weighting(aero_particle_1, aero_particle_2, &
913  aero_particle_new, s1, s2, sc, aero_data, aero_state%awa, &
914  remove_1, remove_2, create_new, id_1_lost, id_2_lost, &
915  aero_info_1, aero_info_2)
916 
917  if (id_1_lost) then
918  call aero_info_array_add_aero_info(aero_state%aero_info_array, &
919  aero_info_1)
920  end if
921  if (id_2_lost) then
922  call aero_info_array_add_aero_info(aero_state%aero_info_array, &
923  aero_info_2)
924  end if
925 
926  ! add new particle
927  if (create_new) then
928  new_group = aero_weight_array_rand_group(aero_weight_total, sc, &
929  aero_particle_radius(aero_particle_new, aero_data))
930  aero_particle_new%weight_group = new_group
931  new_proc = sample_cts_pdf(1d0 / magnitudes(new_group, :)) - 1
932  call send_return_unreq_particle(aero_particle_new, new_proc)
933  end if
934 
935  end subroutine coagulate_dist
936 
937 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
938 
939 end module pmc_coagulation_dist
pmc_coagulation_dist::send_return_no_particle
subroutine send_return_no_particle(dest_proc, i_bin)
Definition: coagulation_dist.F90:504
pmc_coagulation::coagulate_weighting
subroutine coagulate_weighting(pt1, pt2, ptc, c1, c2, cc, aero_data, aero_weight_array, remove_1, remove_2, create_new, id_1_lost, id_2_lost, aero_info_1, aero_info_2)
Actually coagulate pt1 and pt2 to form ptc and compute weighting effects, including which particles s...
Definition: coagulation.F90:762
pmc_mpi::pmc_mpi_size
integer function pmc_mpi_size()
Returns the total number of processes.
Definition: mpi.F90:134
pmc_mpi
Wrapper functions for MPI.
Definition: mpi.F90:13
pmc_coagulation_dist::send_return_req_particle
subroutine send_return_req_particle(aero_particle, i_bin, dest_proc)
Definition: coagulation_dist.F90:588
pmc_coagulation_dist::coag_dist_outgoing_buffer_size
integer, parameter coag_dist_outgoing_buffer_size
Size of the outgoing buffer for bsend (bytes).
Definition: coagulation_dist.F90:31
pmc_coagulation_dist::coagulate_dist
subroutine coagulate_dist(aero_data, aero_state, aero_particle_1, aero_particle_2, remote_proc, aero_weight_total, magnitudes, remove_1, remove_2)
Definition: coagulation_dist.F90:883
pmc_coagulation_dist::coag_dist_recv
subroutine coag_dist_recv(requests, env_state, aero_weight_total, aero_data, aero_state, accept_factors, coag_kernel_type, tot_n_coag, magnitudes, procs_done)
Definition: coagulation_dist.F90:248
pmc_coagulation_dist::coag_dist_max_buffer_size
integer, parameter coag_dist_max_buffer_size
Size of send and receive buffer for each message (bytes).
Definition: coagulation_dist.F90:39
pmc_coagulation_dist::recv_done
subroutine recv_done(procs_done)
Receive a done message.
Definition: coagulation_dist.F90:811
pmc_coagulation_dist::generate_n_samps
subroutine generate_n_samps(n_parts, del_t, bin_grid, aero_weight_array, k_max, n_samps, accept_factors)
generate the number of samples to do per bin pair.
Definition: coagulation_dist.F90:843
pmc_aero_state::aero_state_remove_rand_particle_from_bin
subroutine aero_state_remove_rand_particle_from_bin(aero_state, i_bin, i_class, aero_particle)
Remove a randomly chosen particle from the given bin and return it.
Definition: aero_state.F90:425
pmc_coagulation_dist::mc_coag_dist
subroutine mc_coag_dist(coag_kernel_type, env_state, aero_data, aero_state, del_t, tot_n_samp, tot_n_coag)
Do coagulation for time del_t.
Definition: coagulation_dist.F90:106
pmc_mpi::pmc_mpi_allgather_real_array
subroutine pmc_mpi_allgather_real_array(send, recv)
Does an allgather of real arrays (must be the same size on all processes).
Definition: mpi.F90:1527
pmc_util::die_msg
subroutine die_msg(code, error_msg)
Error immediately.
Definition: util.F90:134
pmc_mpi::pmc_mpi_rank
integer function pmc_mpi_rank()
Returns the rank of the current process.
Definition: mpi.F90:117
pmc_constants::dp
integer, parameter dp
Kind of a double precision real number.
Definition: constants.F90:12
pmc_aero_state::aero_state_add_particle
subroutine aero_state_add_particle(aero_state, aero_particle, aero_data, allow_resort)
Add the given particle.
Definition: aero_state.F90:338
pmc_aero_weight_array
The aero_weight_array_t structure and associated subroutines.
Definition: aero_weight_array.F90:10
pmc_coagulation_dist::send_return_unreq_particle
subroutine send_return_unreq_particle(aero_particle, dest_proc)
Definition: coagulation_dist.F90:721
pmc_bin_grid::bin_grid_size
elemental integer function bin_grid_size(bin_grid)
Return the number of bins in the grid, or -1 if the bin grid is not allocated.
Definition: bin_grid.F90:51
pmc_coagulation_dist::any_requests_active
logical function any_requests_active(requests)
Returns .true. if any of the requests are active, otherwise returns .false.
Definition: coagulation_dist.F90:355
pmc_env_state::env_state_t
Current environment state.
Definition: env_state.F90:29
pmc_util::assert
subroutine assert(code, condition_ok)
Errors unless condition_ok is true.
Definition: util.F90:103
pmc_coagulation_dist::update_n_samps
subroutine update_n_samps(n_samps, local_bin, remote_bin, samps_remaining)
Definition: coagulation_dist.F90:392
pmc_aero_state
The aero_state_t structure and assocated subroutines.
Definition: aero_state.F90:9
pmc_aero_weight_array::aero_weight_array_t
An array of aerosol size distribution weighting functions.
Definition: aero_weight_array.F90:35
pmc_coagulation_dist::find_rand_remote_proc
subroutine find_rand_remote_proc(n_parts, remote_bin, remote_proc)
Definition: coagulation_dist.F90:374
pmc_coagulation_dist::request_allocate
subroutine request_allocate(request)
Definition: coagulation_dist.F90:69
pmc_coagulation_dist::coag_dist_tag_request_particle
integer, parameter coag_dist_tag_request_particle
Definition: coagulation_dist.F90:41
pmc_coagulation_dist::recv_request_particle
subroutine recv_request_particle(aero_state)
Definition: coagulation_dist.F90:456
pmc_coagulation_dist::send_request_particle
subroutine send_request_particle(remote_proc, remote_bin)
Definition: coagulation_dist.F90:429
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_coagulation
Aerosol particle coagulation.
Definition: coagulation.F90:11
pmc_util::assert_msg
subroutine assert_msg(code, condition_ok, error_msg)
Errors unless condition_ok is true.
Definition: util.F90:77
pmc_coagulation_dist::coag_dist_tag_return_req_particle
integer, parameter coag_dist_tag_return_req_particle
Definition: coagulation_dist.F90:42
pmc_coagulation_dist::coag_dist_tag_done
integer, parameter coag_dist_tag_done
Definition: coagulation_dist.F90:45
pmc_coagulation_dist::coag_dist_tag_return_unreq_particle
integer, parameter coag_dist_tag_return_unreq_particle
Definition: coagulation_dist.F90:43
pmc_rand::sample_cts_pdf
integer function sample_cts_pdf(pdf)
Sample the given continuous probability density function.
Definition: rand.F90:490
pmc_coagulation_dist::send_done
subroutine send_done(dest_proc)
Send a message saying that this process is finished with its coagulation.
Definition: coagulation_dist.F90:791
pmc_coagulation::compute_n_samp
subroutine compute_n_samp(ni, nj, same_bin, k_max, del_t, n_samp_mean, n_samp, accept_factor)
Compute the number of samples required for the pair of bins.
Definition: coagulation.F90:599
pmc_coagulation_dist::recv_return_req_particle
subroutine recv_return_req_particle(requests, env_state, aero_weight_total, aero_data, aero_state, accept_factors, coag_kernel_type, tot_n_coag, magnitudes)
Definition: coagulation_dist.F90:622
pmc_aero_weight_array::aero_weight_array_rand_group
integer function aero_weight_array_rand_group(aero_weight_array, i_class, radius)
Choose a random group at the given radius, with probability inversely proportional to group weight at...
Definition: aero_weight_array.F90:376
pmc_env_state
The env_state_t structure and associated subroutines.
Definition: env_state.F90:9
pmc_coagulation_dist::request_deallocate
subroutine request_deallocate(request)
Deallocate a request object and set it to be invalid.
Definition: coagulation_dist.F90:81
pmc_coagulation_dist::coag_dist_tag_return_no_particle
integer, parameter coag_dist_tag_return_no_particle
Definition: coagulation_dist.F90:44
pmc_aero_data::aero_data_t
Aerosol material properties and associated data.
Definition: aero_data.F90:49
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_coagulation_dist::add_coagulation_requests
subroutine add_coagulation_requests(aero_state, requests, n_parts, local_bin, remote_bin, n_samps, samps_remaining)
Definition: coagulation_dist.F90:300
pmc_mpi::pmc_mpi_check_ierr
subroutine pmc_mpi_check_ierr(ierr)
Dies if ierr is not ok.
Definition: mpi.F90:40
pmc_util
Common utility subroutines.
Definition: util.F90:9
pmc_mpi::pmc_mpi_allgather_integer_array
subroutine pmc_mpi_allgather_integer_array(send, recv)
Does an allgather of integer arrays (must be the same size on all processes).
Definition: mpi.F90:1492
pmc_mpi::pmc_mpi_barrier
subroutine pmc_mpi_barrier()
Synchronize all processes.
Definition: mpi.F90:103
pmc_coagulation_dist::request_is_active
logical function request_is_active(request)
Whether the given reqest object is currectly active.
Definition: coagulation_dist.F90:93
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_bin_grid
The bin_grid_t structure and associated subroutines.
Definition: bin_grid.F90:9
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_aero_data
The aero_data_t structure and associated subroutines.
Definition: aero_data.F90:9
pmc_bin_grid::bin_grid_t
1D grid, either logarithmic or linear.
Definition: bin_grid.F90:33
pmc_coagulation_dist::recv_return_no_particle
subroutine recv_return_no_particle(requests, aero_data, aero_state)
Definition: coagulation_dist.F90:531
pmc_aero_state::aero_state_t
The current collection of aerosol particles.
Definition: aero_state.F90:63
pmc_coagulation_dist::recv_return_unreq_particle
subroutine recv_return_unreq_particle(aero_state, aero_data)
Definition: coagulation_dist.F90:749
pmc_coagulation_dist
Parallel aerosol particle coagulation with MPI.
Definition: coagulation_dist.F90:9
pmc_coagulation_dist::coag_dist_max_requests
integer, parameter coag_dist_max_requests
Definition: coagulation_dist.F90:40
pmc_rand::sample_disc_pdf
integer function sample_disc_pdf(pdf)
Sample the given discrete probability density function.
Definition: rand.F90:524
pmc_aero_state::aero_state_sort
subroutine aero_state_sort(aero_state, aero_data, bin_grid, all_procs_same)
Sorts the particles if necessary.
Definition: aero_state.F90:2939
pmc_rand::pmc_random
real(kind=dp) function pmc_random()
Returns a random number between 0 and 1.
Definition: rand.F90:139
pmc_coagulation_dist::request_t
A single outstanding request for a remote particle.
Definition: coagulation_dist.F90:48