MFIX  2016-1
particles_in_cell.f
Go to the documentation of this file.
1 !vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv!
2 ! Subroutine: PARTICLES_IN_CELL !
3 ! !
4 ! Purpose: !
5 ! - For each particle find the computational fluid cell !
6 ! containing the particle center. !
7 ! - Calculate the bulk density in each computational fluid !
8 ! cell. !
9 ! - Calculate the volume average solids velocity in each !
10 ! computational fluid cell. !
11 ! - For parallel processing indices are altered !
12 ! !
13 !^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^!
14  SUBROUTINE particles_in_cell
15 
16 ! The number of particles on the current process.
17  use discretelement, only: pip, max_pip
18 ! The I/J/K, IJK, and phase index of each particle
19  use discretelement, only: pijk
20 ! The number and list of particles in each fluid cell IJK.
21  use derived_types, only: pic
22  use discretelement, only: pinc
23 ! The East/North/Top face location of a given I/J/K index.
24  use discretelement, only: xe, yn, zt
25 ! Flag for 2D simulations.
26  use geometry, only: no_k
27 ! The start and end indices of IJK loops
28  use compar, only: ijkstart3, ijkend3
29 ! The Upper and Loper indices covered by the current process.
30  use compar, only: istart3, iend3
31  use compar, only: jstart3, jend3
32  use compar, only: kstart3, kend3
33 ! Fluid grid cell dimensions and mesh size
34  USE geometry, only: imin2, imax2
35  USE geometry, only: jmin2, jmax2
36  USE geometry, only: kmin2, kmax2
37 ! Fixed array sizes in the I/J/K direction
39  use param, only: dimension_3
40 ! Function to conpute IJK from I/J/K
41  use functions, only: funijk
42 
43  ! The accumulated number of particles in each IJK.
45 
46  use discretelement, only: des_pos_new
47  use functions, only: is_nonexistent, is_ghost, is_entering_ghost, is_exiting_ghost
48 
49  IMPLICIT NONE
50 
51 ! Local Variables
52 !---------------------------------------------------------------------//
53 ! particle no.
54  INTEGER L
55 ! accounted for particles
56  INTEGER PC
57 ! ijk indices
58  INTEGER I, J, K, IJK
59 ! variables that count/store the number of particles in i, j, k cell
60  INTEGER:: npic, pos
61 !......................................................................!
62 
63 ! following quantities are reset every call to particles_in_cell
64  pinc(:) = 0
65 
66 ! allocate(PARTICLE_COUNT(DIMENSION_3))
67 ! Use an incremental approach to determine the new particle location.
68 !-----------------------------------------------------------------------
69 !!$omp parallel default(shared) private(L, I, J, K, IJK)
70 !!$omp do reduction(+:PINC) schedule (guided,50)
71 
72  DO l = 1, max_pip
73 ! skipping particles that do not exist
74  IF(is_nonexistent(l)) cycle
75 
76  i = pijk(l,1)
77  IF(i <= istart3 .OR. i >= iend3) THEN
78  CALL pic_search(i, des_pos_new(l,1), xe, &
79  dimension_i, imin2, imax2)
80  ELSE
81  IF((des_pos_new(l,1) >= xe(i-1)) .AND. &
82  (des_pos_new(l,1) < xe(i))) THEN
83  i = i
84  ELSEIF((des_pos_new(l,1) >= xe(i)) .AND. &
85  (des_pos_new(l,1) < xe(i+1))) THEN
86  i = i+1
87  ELSEIF((des_pos_new(l,1) >= xe(i-2)) .AND. &
88  (des_pos_new(l,1) < xe(i-1))) THEN
89  i = i-1
90  ELSE
91  CALL pic_search(i, des_pos_new(l,1), xe, &
92  dimension_i, imin2, imax2)
93  ENDIF
94  ENDIF
95 
96  j = pijk(l,2)
97  IF(j <= jstart3 .OR. j >= jend3) THEN
98  CALL pic_search(j, des_pos_new(l,2), yn, &
99  dimension_j, jmin2, jmax2)
100  ELSE
101  IF((des_pos_new(l,2) >= yn(j-1)) .AND. &
102  (des_pos_new(l,2) < yn(j))) THEN
103  j = j
104  ELSEIF((des_pos_new(l,2) >= yn(j)) .AND. &
105  (des_pos_new(l,2) < yn(j+1))) THEN
106  j = j+1
107  ELSEIF((des_pos_new(l,2) >= yn(j-2)) .AND. &
108  (des_pos_new(l,2) < yn(j-1)))THEN
109  j = j-1
110  ELSE
111  CALL pic_search(j, des_pos_new(l,2), yn, &
112  dimension_j, jmin2, jmax2)
113  ENDIF
114  ENDIF
115 
116 
117  IF(no_k) THEN
118  k = 1
119  ELSE
120  k = pijk(l,3)
121  IF(k <= kstart3 .OR. k >= kend3) THEN
122  CALL pic_search(k, des_pos_new(l,3), zt, &
123  dimension_k, kmin2, kmax2)
124  ELSE
125  IF((des_pos_new(l,3) >= zt(k-1)) .AND. &
126  (des_pos_new(l,3) < zt(k))) THEN
127  k = k
128  ELSEIF((des_pos_new(l,3) >= zt(k)) .AND. &
129  (des_pos_new(l,3) < zt(k+1))) THEN
130  k = k+1
131  ELSEIF((des_pos_new(l,3) >= zt(k-2)) .AND. &
132  (des_pos_new(l,3) < zt(k-1))) THEN
133  k = k-1
134  ELSE
135  CALL pic_search(k, des_pos_new(l,3), zt, &
136  dimension_k, kmin2, kmax2)
137  ENDIF
138  ENDIF
139  ENDIF
140 
141 ! Calculate the fluid cell index.
142  ijk = funijk(i,j,k)
143 
144 ! Assign PIJK(L,1:4)
145  pijk(l,1) = i
146  pijk(l,2) = j
147  pijk(l,3) = k
148  pijk(l,4) = ijk
149 
150 ! Increment the number of particles in cell IJK
151  IF(.NOT.is_ghost(l) .AND. .NOT.is_entering_ghost(l) .AND. &
152  .NOT.is_exiting_ghost(l)) pinc(ijk) = pinc(ijk) + 1
153 
154  ENDDO
155 !!$omp end parallel
156 
158 
159 ! Assigning the variable PIC(IJK)%p(:). For each computational fluid
160 ! cell compare the number of current particles in the cell to what was
161 ! in the cell previously. If different reallocate. Store the particle
162 ! ids
163 ! ---------------------------------------------------------------->>>
164 !!$omp parallel do if(ijkend3 .ge. 2000) default(shared) &
165 !!$omp private(ijk,npic) !schedule (guided,50)
166  DO ijk = ijkstart3, ijkend3
167 
168 ! checking all cells (including ghost cells); updating entering/exiting
169 ! particle regions
170  npic = pinc(ijk)
171  IF (ASSOCIATED(pic(ijk)%p)) THEN
172  IF (npic.NE.SIZE(pic(ijk)%p)) THEN
173  DEALLOCATE(pic(ijk)%p)
174  IF (npic.GT.0) ALLOCATE(pic(ijk)%p(npic))
175  ENDIF
176  ELSE
177  IF (npic.GT.0) ALLOCATE(pic(ijk)%p(npic))
178  ENDIF
179  ENDDO
180 !!$omp end parallel do
181 
182  particle_count(:) = 1
183  pc = 1
184  DO l = 1, max_pip
185 ! exiting loop if reached max number of particles in processor
186  IF(pc.GT.pip) exit
187 ! skipping indices with no particles (non-existent particles)
188  IF(is_nonexistent(l)) cycle
189 ! incrementing particle account when particle exists
190  pc = pc+1
191 ! skipping ghost particles
192  IF(is_ghost(l) .OR. is_entering_ghost(l) .OR. is_exiting_ghost(l)) cycle
193  ijk = pijk(l,4)
194  pos = particle_count(ijk)
195  pic(ijk)%P(pos) = l
196  particle_count(ijk) = particle_count(ijk) + 1
197  ENDDO
198 
199 ! deallocate(PARTICLE_COUNT)
200 
201  RETURN
202  END SUBROUTINE particles_in_cell
203 
204 !vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv!
205 ! !
206 ! Subroutine: INIT_PARTICLES_IN_CELL !
207 ! !
208 ! Purpose: !
209 ! - For each particle find the computational fluid cell !
210 ! containing the particle center. !
211 ! - Calculate the bulk density in each computational fluid !
212 ! cell. !
213 ! - Calculate the volume average solids velocity in each !
214 ! computational fluid cell. !
215 ! - For parallel processing indices are altered !
216 ! !
217 !^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^!
218  SUBROUTINE init_particles_in_cell
220  use discretelement, only: pijk, pinc
221  USE discretelement, only: des_pos_new
222  USE discretelement, only: max_pip
223  USE discretelement, only: xe, yn, zt
224  USE functions, only: is_nonexistent, is_ghost, is_entering_ghost, is_exiting_ghost
225  use mpi_funs_des, only: des_par_exchange
226 
227 ! Number of particles in the I/J/K direction
229 
230  use mpi_utility
231  use sendrecv
232 
233  USE error_manager
234  USE desgrid, only: desgrid_pic
235 
236  IMPLICIT NONE
237 !-----------------------------------------------
238 ! Local Variables
239 !-----------------------------------------------
240 ! particle no.
241  INTEGER :: L
242 ! ijk indices
243  INTEGER :: I, J, K, IJK
244 
245  CALL init_err_msg("INIT_PARTICLES_IN_CELL")
246 
247 ! following quantities are reset every call to particles_in_cell
248  pinc(:) = 0
249 
250 ! Bin the particles to the DES grid.
251  CALL desgrid_pic(.true.)
252 ! Call exchange particles - this will exchange particle crossing
253 ! boundaries as well as updates ghost particles information
254  CALL des_par_exchange
255 
256 ! Assigning PIJK(L,1), PIJK(L,2) and PIJK(L,3) the i, j, k indices
257 ! of particle L (locating particle on fluid grid). Also determine
258 ! composite ijk index. If first_pass, also assigning PIJK(L,5) the
259 ! solids phase index of particle.
260 ! ---------------------------------------------------------------->>>
261  DO l = 1, max_pip
262 ! skipping particles that do not exist
263  IF(is_nonexistent(l)) cycle
264 
265 ! Use a brute force technique to determine the particle locations in
266 ! the Eulerian fluid grid.
267 
268  CALL pic_search(i, des_pos_new(l,1), xe, &
269  dimension_i, imin2, imax2)
270  pijk(l,1) = i
271 
272  CALL pic_search(j, des_pos_new(l,2), yn, &
273  dimension_j, jmin2, jmax2)
274  pijk(l,2) = j
275 
276  IF(no_k) THEN
277  k=1
278  pijk(l,3) = 1
279  ELSE
280  CALL pic_search(k, des_pos_new(l,3), zt, &
281  dimension_k, kmin2, kmax2)
282  pijk(l,3) = k
283  ENDIF
284 
285 ! Assigning PIJK(L,4) now that particles have been located on the fluid
286  ijk = funijk(i,j,k)
287  pijk(l,4) = ijk
288 
289 ! Enumerate the number of 'real' particles in the ghost cell.
290  IF(.NOT.is_ghost(l) .AND. .NOT.is_entering_ghost(l) .AND. &
291  .NOT.is_exiting_ghost(l)) pinc(ijk) = pinc(ijk) + 1
292  ENDDO
293 
294 ! Bin the particles to the DES grid.
295  CALL desgrid_pic(.true.)
296 ! Calling exchange particles - this will exchange particle crossing
297 ! boundaries as well as updates ghost particles information
298 ! unclear why this needs to be called again.
299  CALL des_par_exchange
300 
301  CALL finl_err_msg
302 
303  RETURN
304  END SUBROUTINE init_particles_in_cell
305 
306 !vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv!
307 ! !
308 ! Subroutine: PIC_SEARCH !
309 ! !
310 ! Purpose: Identify the I (or J or K) index of the fluid cell that !
311 ! contains the particle centroid. !
312 ! !
313 !^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^!
314  SUBROUTINE pic_search(IDX, lPOS, ENT_POS, lDIMN, lSTART, lEND)
316  IMPLICIT NONE
317 !-----------------------------------------------
318 ! Local Variables
319 !-----------------------------------------------
320 ! Index being searched for (I, J, or K)
321  INTEGER, INTENT(OUT) :: IDX
322 ! Particle x,y,z position
323  DOUBLE PRECISION, INTENT(IN) :: lPOS
324 ! Dimension of ENT_POS array
325  INTEGER, INTENT(IN) :: lDIMN
326 ! East, North, or Top cell face location
327  DOUBLE PRECISION, INTENT(IN) :: ENT_POS(0:ldimn)
328 ! Search bounds (by rank)
329  INTEGER, INTENT(IN) :: lSTART, lEND
330 
331  DO idx = lstart,lend
332  IF(lpos >= ent_pos(idx-1) .AND. lpos < ent_pos(idx)) EXIT
333  ENDDO
334 
335  RETURN
336  END SUBROUTINE pic_search
integer dimension_i
Definition: param_mod.f:7
integer iend3
Definition: compar_mod.f:80
integer imax2
Definition: geometry_mod.f:61
integer jstart3
Definition: compar_mod.f:80
integer ijkend3
Definition: compar_mod.f:80
subroutine finl_err_msg
integer dimension_3
Definition: param_mod.f:11
integer dimension_k
Definition: param_mod.f:9
subroutine desgrid_pic(plocate)
Definition: desgrid_mod.f:711
subroutine des_par_exchange()
integer kstart3
Definition: compar_mod.f:80
integer jmin2
Definition: geometry_mod.f:89
integer kend3
Definition: compar_mod.f:80
subroutine init_err_msg(CALLER)
subroutine check_cell_movement
integer jend3
Definition: compar_mod.f:80
integer jmax2
Definition: geometry_mod.f:63
integer kmax2
Definition: geometry_mod.f:65
subroutine particles_in_cell
Definition: param_mod.f:2
logical no_k
Definition: geometry_mod.f:28
subroutine init_particles_in_cell
integer ijkstart3
Definition: compar_mod.f:80
subroutine pic_search(IDX, lPOS, ENT_POS, lDIMN, lSTART, lEND)
double precision, dimension(:), allocatable particle_count
integer imin2
Definition: geometry_mod.f:89
type(iap1), dimension(:), allocatable pic
integer istart3
Definition: compar_mod.f:80
integer kmin2
Definition: geometry_mod.f:89
integer dimension_j
Definition: param_mod.f:8