PartMC  2.3.0
aero_info_array.F90
Go to the documentation of this file.
1 ! Copyright (C) 2007-2011 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_aero_info_array module.
7 
8 !> The aero_info_array_t structure and assoicated subroutines.
10 
11  use pmc_aero_info
12  use pmc_util
13  use pmc_spec_file
14  use pmc_mpi
15 #ifdef PMC_USE_MPI
16  use mpi
17 #endif
18 
19  !> 1-D arrays of aero_info_t structure.
20  !!
21  !! This type implements a variable-length array of aero_info_t
22  !! structures. To give a reasonable tradeoff between frequent
23  !! re-allocs and memory usage, the length of an aero_info_array is
24  !! generally a bit longer than the number of particles stored in
25  !! it. When the array is full then a larger array is allocated with
26  !! new extra space. As a balance between memory usage and frequency
27  !! of re-allocs the length of the array is currently doubled when
28  !! necessary and halved when possible.
29  !!
30  !! The true allocated length of the aero_info_array can be obtained
31  !! by size(aero_info_array%%aero_info), while the number of used
32  !! particle slots in it is given by aero_info_array%%n_item. It must
33  !! be that aero_info_array%%n_item is less than or equal to
34  !! size(aero_info_array%%aero_info).
36  !> Number of items in the array (not the same as the length of
37  !> the allocated memory).
38  integer :: n_item
39  !> Array of aero_info_t structures.
40  type(aero_info_t), pointer :: aero_info(:)
41  end type aero_info_array_t
42 
43 contains
44 
45 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
46 
47  !> Allocates the structure.
48  subroutine aero_info_array_allocate(aero_info_array)
49 
50  !> Result.
51  type(aero_info_array_t), intent(out) :: aero_info_array
52 
53  integer :: i
54 
55  aero_info_array%n_item = 0
56  allocate(aero_info_array%aero_info(0))
57 
58  end subroutine aero_info_array_allocate
59 
60 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
61 
62  !> Allocates with the given size.
63  subroutine aero_info_array_allocate_size(aero_info_array, n_item)
64 
65  !> Result.
66  type(aero_info_array_t), intent(out) :: aero_info_array
67  !> Number of items.
68  integer, intent(in) :: n_item
69 
70  integer :: i
71 
72  aero_info_array%n_item = n_item
73  allocate(aero_info_array%aero_info(n_item))
74  do i = 1,n_item
75  call aero_info_allocate(aero_info_array%aero_info(i))
76  end do
77 
78  end subroutine aero_info_array_allocate_size
79 
80 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
81 
82  !> Deallocates.
83  subroutine aero_info_array_deallocate(aero_info_array)
84 
85  !> Structure to deallocate.
86  type(aero_info_array_t), intent(inout) :: aero_info_array
87 
88  integer :: i
89 
90  do i = 1,aero_info_array%n_item
91  call aero_info_deallocate(aero_info_array%aero_info(i))
92  end do
93  deallocate(aero_info_array%aero_info)
94 
95  end subroutine aero_info_array_deallocate
96 
97 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
98 
99  !> Copies aero_info_array_from to aero_info_array_to, both
100  !> of which must already be allocated.
101  subroutine aero_info_array_copy(aero_info_array_from, &
102  aero_info_array_to)
103 
104  !> Origin structure.
105  type(aero_info_array_t), intent(in) :: aero_info_array_from
106  !> Destination structure.
107  type(aero_info_array_t), intent(inout) :: aero_info_array_to
108 
109  integer :: i
110 
111  call aero_info_array_deallocate(aero_info_array_to)
112  call aero_info_array_allocate_size(aero_info_array_to, &
113  aero_info_array_from%n_item)
114  do i = 1,aero_info_array_from%n_item
115  call aero_info_copy(aero_info_array_from%aero_info(i), &
116  aero_info_array_to%aero_info(i))
117  end do
118 
119  end subroutine aero_info_array_copy
120 
121 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
122 
123  !> Resets an aero_info_array to contain zero particles.
124  subroutine aero_info_array_zero(aero_info_array)
125 
126  !> Structure to reset.
127  type(aero_info_array_t), intent(inout) :: aero_info_array
128 
129  call aero_info_array_deallocate(aero_info_array)
130  allocate(aero_info_array%aero_info(0))
131  aero_info_array%n_item = 0
132 
133  end subroutine aero_info_array_zero
134 
135 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
136 
137  !> Changes the given aero_info_array to exactly the given
138  !> new_length.
139  !!
140  !! This function should not be called directly, but rather use
141  !! aero_info_array_enlarge(), aero_info_array_enlarge_to()
142  !! or aero_info_array_shrink().
143  subroutine aero_info_array_realloc(aero_info_array, new_length)
144 
145  !> Array to reallocate (must already be allocated on entry).
146  type(aero_info_array_t), intent(inout) :: aero_info_array
147  !> New length of the array.
148  integer, intent(in) :: new_length
149 
150  integer :: n_item, i
151  type(aero_info_t), pointer :: new_particles(:)
152 
153  n_item = aero_info_array%n_item
154  call assert(372938429, new_length >= n_item)
155  allocate(new_particles(new_length))
156  do i = 1,aero_info_array%n_item
157  call aero_info_copy(aero_info_array%aero_info(i), &
158  new_particles(i))
159  call aero_info_deallocate(aero_info_array%aero_info(i))
160  end do
161  deallocate(aero_info_array%aero_info)
162  aero_info_array%aero_info => new_particles
163 
164  end subroutine aero_info_array_realloc
165 
166 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
167 
168  !> Enlarges the given aero_info_array by at least one element
169  !!
170  !! Currently this doubles the length.
171  subroutine aero_info_array_enlarge(aero_info_array)
172 
173  !> Array to enlarge.
174  type(aero_info_array_t), intent(inout) :: aero_info_array
175 
176  integer :: length, new_length
177 
178  length = size(aero_info_array%aero_info)
179  new_length = max(length * 2, length + 1)
180  call aero_info_array_realloc(aero_info_array, new_length)
181 
182  end subroutine aero_info_array_enlarge
183 
184 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
185 
186  !> Enlarges the given array so that it is at least of size n.
187  subroutine aero_info_array_enlarge_to(aero_info_array, n)
188 
189  !> Array to enlarge.
190  type(aero_info_array_t), intent(inout) :: aero_info_array
191  !> Minimum new size of array.
192  integer, intent(in) :: n
193 
194  do while (size(aero_info_array%aero_info) < n)
195  call aero_info_array_enlarge(aero_info_array)
196  end do
197 
198  end subroutine aero_info_array_enlarge_to
199 
200 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
201 
202  !> Possibly shrinks the storage of the given array, ensuring that
203  !> it can still store the allocated particles.
204  subroutine aero_info_array_shrink(aero_info_array)
205 
206  !> Array to shrink.
207  type(aero_info_array_t), intent(inout) :: aero_info_array
208 
209  integer :: n_item, length, new_length
210 
211  n_item = aero_info_array%n_item
212  length = size(aero_info_array%aero_info)
213  new_length = length / 2
214  do while ((n_item <= new_length) .and. (length > 0))
215  call aero_info_array_realloc(aero_info_array, new_length)
216  length = size(aero_info_array%aero_info)
217  new_length = length / 2
218  end do
219 
220  end subroutine aero_info_array_shrink
221 
222 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
223 
224  !> Adds the given aero_info to the end of the array.
225  subroutine aero_info_array_add_aero_info(aero_info_array, &
226  aero_info)
227 
228  !> Array to add to.
229  type(aero_info_array_t), intent(inout) :: aero_info_array
230  !> Aero_info to add.
231  type(aero_info_t), intent(in) :: aero_info
232 
233  integer :: n
234 
235  n = aero_info_array%n_item + 1
236  call aero_info_array_enlarge_to(aero_info_array, n)
237  call aero_info_allocate(aero_info_array%aero_info(n))
238  call aero_info_copy(aero_info, aero_info_array%aero_info(n))
239  aero_info_array%n_item = aero_info_array%n_item + 1
240 
241  end subroutine aero_info_array_add_aero_info
242 
243 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
244 
245  !> Removes the aero_info at the given index.
246  subroutine aero_info_array_remove_aero_info(aero_info_array, &
247  index)
248 
249  !> Array to remove from.
250  type(aero_info_array_t), intent(inout) :: aero_info_array
251  !> Index of aero_info to remove.
252  integer, intent(in) :: index
253 
254  call assert(213892348, index >= 1)
255  call assert(953927392, index <= aero_info_array%n_item)
256  call aero_info_deallocate(aero_info_array%aero_info(index))
257  if (index < aero_info_array%n_item) then
258  ! shift last aero_info into empty slot to preserve dense packing
259  call aero_info_copy( &
260  aero_info_array%aero_info(aero_info_array%n_item), &
261  aero_info_array%aero_info(index))
262  call aero_info_deallocate( &
263  aero_info_array%aero_info(aero_info_array%n_item))
264  end if
265  aero_info_array%n_item = aero_info_array%n_item - 1
266  call aero_info_array_shrink(aero_info_array)
267 
268  end subroutine aero_info_array_remove_aero_info
269 
270 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
271 
272  !> Adds \c aero_info_array_delta to the end of \c aero_info_array.
273  subroutine aero_info_array_add(aero_info_array, &
274  aero_info_array_delta)
275 
276  !> Array to add to.
277  type(aero_info_array_t), intent(inout) :: aero_info_array
278  !> Aero_info to add.
279  type(aero_info_array_t), intent(in) :: aero_info_array_delta
280 
281  integer :: i, n, n_delta, n_new
282 
283  n = aero_info_array%n_item
284  n_delta = aero_info_array_delta%n_item
285  n_new = n + n_delta
286  call aero_info_array_enlarge_to(aero_info_array, n_new)
287  do i = 1,n_delta
288  call aero_info_allocate(aero_info_array%aero_info(n + i))
289  call aero_info_copy(aero_info_array_delta%aero_info(i), &
290  aero_info_array%aero_info(n + i))
291  end do
292  aero_info_array%n_item = n_new
293 
294  end subroutine aero_info_array_add
295 
296 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
297 
298  !> Determines the number of bytes required to pack the given value.
299  integer function pmc_mpi_pack_size_aia(val)
300 
301  !> Value to pack.
302  type(aero_info_array_t), intent(in) :: val
303 
304  integer :: i, total_size
305 
306  total_size = 0
307  total_size = total_size + pmc_mpi_pack_size_integer(val%n_item)
308  do i = 1,val%n_item
309  total_size = total_size &
310  + pmc_mpi_pack_size_aero_info(val%aero_info(i))
311  end do
312  pmc_mpi_pack_size_aia = total_size
313 
314  end function pmc_mpi_pack_size_aia
315 
316 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
317 
318  !> Packs the given value into the buffer, advancing position.
319  subroutine pmc_mpi_pack_aero_info_array(buffer, position, val)
320 
321  !> Memory buffer.
322  character, intent(inout) :: buffer(:)
323  !> Current buffer position.
324  integer, intent(inout) :: position
325  !> Value to pack.
326  type(aero_info_array_t), intent(in) :: val
327 
328 #ifdef PMC_USE_MPI
329  integer :: prev_position, i
330 
331  prev_position = position
332  call pmc_mpi_pack_integer(buffer, position, val%n_item)
333  do i = 1,val%n_item
334  call pmc_mpi_pack_aero_info(buffer, position, val%aero_info(i))
335  end do
336  call assert(732927292, &
337  position - prev_position <= pmc_mpi_pack_size_aia(val))
338 #endif
339 
340  end subroutine pmc_mpi_pack_aero_info_array
341 
342 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
343 
344  !> Unpacks the given value from the buffer, advancing position.
345  subroutine pmc_mpi_unpack_aero_info_array(buffer, position, val)
346 
347  !> Memory buffer.
348  character, intent(inout) :: buffer(:)
349  !> Current buffer position.
350  integer, intent(inout) :: position
351  !> Value to pack.
352  type(aero_info_array_t), intent(inout) :: val
353 
354 #ifdef PMC_USE_MPI
355  integer :: prev_position, i
356 
358  prev_position = position
359  call pmc_mpi_unpack_integer(buffer, position, val%n_item)
360  allocate(val%aero_info(val%n_item))
361  do i = 1,val%n_item
362  call aero_info_allocate(val%aero_info(i))
363  call pmc_mpi_unpack_aero_info(buffer, position, val%aero_info(i))
364  end do
365  call assert(262838429, &
366  position - prev_position <= pmc_mpi_pack_size_aia(val))
367 #endif
368 
369  end subroutine pmc_mpi_unpack_aero_info_array
370 
371 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
372 
373 end module pmc_aero_info_array
subroutine aero_info_copy(aero_info_from, aero_info_to)
Copies aero_info_from to aero_info_to, both of which must already be allocated.
Definition: aero_info.F90:86
subroutine pmc_mpi_unpack_aero_info_array(buffer, position, val)
Unpacks the given value from the buffer, advancing position.
integer function pmc_mpi_pack_size_integer(val)
Determines the number of bytes required to pack the given value.
Definition: mpi.F90:347
subroutine aero_info_deallocate(aero_info)
Deallocates.
Definition: aero_info.F90:75
integer function pmc_mpi_pack_size_aero_info(val)
Determines the number of bytes required to pack the given value.
Definition: aero_info.F90:117
The aero_info_array_t structure and assoicated subroutines.
subroutine aero_info_array_copy(aero_info_array_from, aero_info_array_to)
Copies aero_info_array_from to aero_info_array_to, both of which must already be allocated.
subroutine aero_info_allocate(aero_info)
Allocates and initializes.
Definition: aero_info.F90:63
subroutine aero_info_array_allocate(aero_info_array)
Allocates the structure.
subroutine aero_info_array_deallocate(aero_info_array)
Deallocates.
subroutine aero_info_array_enlarge(aero_info_array)
Enlarges the given aero_info_array by at least one element.
subroutine aero_info_array_add_aero_info(aero_info_array, aero_info)
Adds the given aero_info to the end of the array.
subroutine aero_info_array_shrink(aero_info_array)
Possibly shrinks the storage of the given array, ensuring that it can still store the allocated parti...
subroutine pmc_mpi_pack_integer(buffer, position, val)
Packs the given value into the buffer, advancing position.
Definition: mpi.F90:534
subroutine aero_info_array_enlarge_to(aero_info_array, n)
Enlarges the given array so that it is at least of size n.
subroutine aero_info_array_zero(aero_info_array)
Resets an aero_info_array to contain zero particles.
subroutine pmc_mpi_pack_aero_info_array(buffer, position, val)
Packs the given value into the buffer, advancing position.
Common utility subroutines.
Definition: util.F90:9
1-D arrays of aero_info_t structure.
subroutine pmc_mpi_unpack_integer(buffer, position, val)
Unpacks the given value from the buffer, advancing position.
Definition: mpi.F90:771
The aero_info_t structure and associated subroutines.
Definition: aero_info.F90:9
Wrapper functions for MPI.
Definition: mpi.F90:13
subroutine aero_info_array_allocate_size(aero_info_array, n_item)
Allocates with the given size.
subroutine aero_info_array_remove_aero_info(aero_info_array, index)
Removes the aero_info at the given index.
subroutine aero_info_array_add(aero_info_array, aero_info_array_delta)
Adds aero_info_array_delta to the end of aero_info_array.
subroutine pmc_mpi_unpack_aero_info(buffer, position, val)
Unpacks the given value from the buffer, advancing position.
Definition: aero_info.F90:160
subroutine pmc_mpi_pack_aero_info(buffer, position, val)
Packs the given value into the buffer, advancing position.
Definition: aero_info.F90:135
Reading formatted text input.
Definition: spec_file.F90:43
integer function pmc_mpi_pack_size_aia(val)
Determines the number of bytes required to pack the given value.
subroutine assert(code, condition_ok)
Errors unless condition_ok is true.
Definition: util.F90:102
subroutine aero_info_array_realloc(aero_info_array, new_length)
Changes the given aero_info_array to exactly the given new_length.
Information about removed particles describing the sink.
Definition: aero_info.F90:48