MFIX  2016-1
check_cell_movement.f
Go to the documentation of this file.
1 !vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv!
2 ! !
3 ! Subroutine: CHECK_CELL_MOVEMENT !
4 ! !
5 ! Purpose: Check to see if particles have moved into ghost cells. !
6 ! !
7 ! Note: This routine needs a global communicator to identify errors. !
8 ! The collection could get expensive so the call frequency of this !
9 ! routine should probably be reduced. !
10 !^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^!
11  SUBROUTINE check_cell_movement
12 
13 ! Global Variables:
14 !---------------------------------------------------------------------//
15 ! Max number of particles in process
16  use discretelement, only: max_pip
17 ! The I/J/K/IJK indicies of the fluid cell
18  use discretelement, only: pijk
19 ! Number of particles in fluid cells
20  use discretelement, only: pinc
21 ! Run time flag indicating DEM or PIC solids.
22  use run, only: dem_solids, pic_solids
23 ! Flag for fluid cells
24  use functions, only: fluid_at
25 
26  use functions, only: is_normal
27  use mpi_utility
28  use error_manager
29 
30  IMPLICIT NONE
31 
32 ! Local Variables:
33 !----------------------------------------------------------------------!
34 ! Loop indicies:
35  INTEGER :: L, I, J, K, IJK
36 ! Integer error flag.
37  INTEGER :: IER
38 ! Flag to remove rogue DEM particles
39  LOGICAL, PARAMETER :: REMOVE_ROGUE_PARTICLES = .false.
40 
41 ! Initialize local variables.
42  ier = 0
43 
44 ! Set an error flag if any errors are found. Preform a global collection
45 ! to sync error flags. If needed, reort errors.
46 !.......................................................................
47  DO l = 1, max_pip
48 ! skipping particles that do not exist
49  IF(is_normal(l)) THEN
50 
51  i = pijk(l,1)
52  j = pijk(l,2)
53  k = pijk(l,3)
54  ijk = pijk(l,4)
55 
56  IF((i > iend1 .OR. i < istart1) .OR. &
57  (j > jend1 .OR. j < jstart1) .OR. &
58  (k > kend1 .OR. k < kstart1)) THEN
59 
60 ! This particle cannot say in the current cell.
61  pinc(ijk) = pinc(ijk) - 1
62 ! PIC parcels can be relocated.
63  IF(pic_solids) THEN
64  CALL recover_parcel(l)
65 ! DEM particles can be removed.
66  ELSEIF(remove_rogue_particles) THEN
67  CALL delete_particle(l)
68 ! Otherwise, this is a fatal error.
69  ELSE
70  ier = 1
71  ENDIF
72 
73  ENDIF
74  ENDIF
75  ENDDO
76 
77  IF(dem_solids) THEN
78  IF(remove_rogue_particles) RETURN
79  CALL global_all_sum(ier)
80  IF(ier > 0) CALL check_cell_movement_dem
81 ! ELSE
82 ! CALL CHECK_CELL_MOVEMENT_PIC
83  ENDIF
84 
85 
86  RETURN
87  END SUBROUTINE check_cell_movement
88 
89 !vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv!
90 ! !
91 ! Subroutine: CHECK_CELL_MOVEMENT_DEM !
92 ! !
93 ! Purpose: Report which DEM particles have moved into ghost cells. !
94 ! This is a dead-end routine. Once called, the simulation will exit. !
95 ! !
96 !^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^!
97  SUBROUTINE check_cell_movement_dem
98 
99 ! Global Variables:
100 !---------------------------------------------------------------------//
101 ! The global ID of a particle.
102  use discretelement, only: iglobal_id
103 ! Max number of particles in process
104  use discretelement, only: max_pip
105 ! The I/J/K/IJK indicies of the fluid cell
106  use discretelement, only: pijk
107 ! Particle positions and velocities
108  use discretelement, only: des_pos_new, des_vel_new
109 
110  use functions, only: is_normal
111  use mpi_utility
112  USE error_manager
113 
114  IMPLICIT NONE
115 
116 ! Local Variables:
117 !----------------------------------------------------------------------!
118 ! Loop indicies:.
119  INTEGER :: L, I, J, K
120 ! Integer error flag
121  INTEGER :: IER
122 
123 
124  CALL init_err_msg("CHECK_CELL_MOVEMENT_DEM")
125  CALL open_pe_log(ier)
126 
127  WRITE(err_msg, 1100)
128  CALL flush_err_msg(footer=.false.)
129 
130  1100 FORMAT('Error 1100: Particles detected in a ghost cell:',/' ')
131 
132  DO l = 1, max_pip
133 ! skipping particles that do not exist
134  IF(.NOT.is_normal(l)) cycle
135 
136 ! assigning local aliases for particle i, j, k fluid grid indices
137  i = pijk(l,1)
138  j = pijk(l,2)
139  k = pijk(l,3)
140 
141  IF (i.GT.iend1 .OR. i.LT.istart1) THEN
142  WRITE(err_msg, 1101) trim(ival(iglobal_id(l))),'I', &
143  trim(ival(i)),'X',des_pos_new(l,1),'X',des_vel_new(l,1)
144  CALL flush_err_msg(header=.false., footer=.false.)
145  ENDIF
146 
147  IF(j.GT.jend1 .OR. j.LT.jstart1) THEN
148  WRITE(err_msg, 1101) trim(ival(iglobal_id(l))),'J', &
149  trim(ival(j)),'Y',des_pos_new(l,2),'Y',des_vel_new(l,2)
150  CALL flush_err_msg(header=.false., footer=.false.)
151  ENDIF
152 
153  IF (do_k .AND. (k.GT.kend1 .OR. k.LT.kstart1)) THEN
154  WRITE(err_msg, 1101) trim(ival(iglobal_id(l))),'K', &
155  trim(ival(k)),'Z',des_pos_new(l,3),'Z',des_vel_new(l,3)
156  CALL flush_err_msg(header=.false., footer=.false.)
157  ENDIF
158  ENDDO
159 
160  1101 FORMAT('Particle ',a,' moved into cell with ',a,' index ',a,/ &
161  3x,a,'-Position: ',g11.4,6x,a,'-Velocity:',g11.4,/' ')
162 
163  WRITE(err_msg, 1102)
164  CALL flush_err_msg(header=.false.)
165  1102 FORMAT('This is a fatal error. A particle output file (vtp) ', &
166  'will be written',/'to aid debugging.')
167 
168 
169  CALL write_des_data
170  CALL mfix_exit(mype)
171 
172  END SUBROUTINE check_cell_movement_dem
173 
174 !vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv!
175 ! !
176 ! Subroutine: RECOVER_PARCEL !
177 ! !
178 ! Purpose: Try to recover the parcel. First move it back to its !
179 ! previous position, then do a full search to bin the parcel in a !
180 ! fluid cell. Delete the parcel if it still is located outside of a !
181 ! fluid cell. !
182 ! !
183 ! Possible Future Work: !
184 ! !
185 ! 1. Redistribute particle's weight among other particles in the !
186 ! domain to conserve mass. !
187 ! !
188 !^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^!
189  SUBROUTINE recover_parcel(NP)
191 ! Global Variables:
192 !---------------------------------------------------------------------//
193 ! The (max) number of particles in process
194  use discretelement, only: pip, max_pip
195 ! The I/J/K/IJK indicies of the fluid cell
196  use discretelement, only: pijk
197 ! The number of particles in cell IJK
198  use discretelement, only: pinc
199 ! Particle position and velocity
200  use discretelement, only: des_pos_new, des_vel_new
201 ! The East/North/Top face loctions of fluid cells
202  use discretelement, only: xe, yn, zt
203 ! Particle velocities
204  use discretelement, only: dtsolid
205 ! Fluid grid cell dimensions and mesh size
206  USE geometry, only: imin2, imax2
207  USE geometry, only: jmin2, jmax2
208  USE geometry, only: kmin2, kmax2
209 ! The East/North/Top face location of a given I/J/K index.
210  use discretelement, only: xe, yn, zt
211 ! Fixed array sizes in the I/J/K direction
213 
214 
215  use cutcell
216  use error_manager
217  use functions, only: funijk, fluid_at
218  use mpi_utility
219  use discretelement, only: iglobal_id
220 
221  IMPLICIT NONE
222 
223 
224 ! Dummy Arguments
225 !----------------------------------------------------------------------!
226 ! Parcel ID
227  INTEGER, INTENT(IN) :: NP
228 
229 
230 ! Local Variables:
231 !----------------------------------------------------------------------!
232 ! particle no.
233  INTEGER :: I, J, K, IJK
234 ! Integer error flag.
235  INTEGER :: IER
236 ! Local parameter to print verbose messages about particles.
237  LOGICAL, PARAMETER :: lDEBUG = .false.
238 
239  DOUBLE PRECISION :: oPOS(3)
240 !.......................................................................
241 
242  CALL init_err_msg("RECOVER_PARCEL")
243  IF(ldebug) CALL open_pe_log(ier)
244 
245  opos = des_pos_new(np,:)
246 
247 ! Reflect the parcle.
248  des_vel_new(np,:) = -des_vel_new(np,:)
249 
250 ! Move the particle back to the previous position.
251  des_pos_new(np,:) = des_pos_new(np,:) + &
252  des_vel_new(np,:) * dtsolid
253 
254 ! Rebin the particle to the fluid grid.
255  CALL pic_search(i,des_pos_new(np,1),xe,dimension_i,imin2,imax2)
256  CALL pic_search(j,des_pos_new(np,2),yn,dimension_j,jmin2,jmax2)
257  CALL pic_search(k,des_pos_new(np,3),zt,dimension_k,kmin2,kmax2)
258 
259 ! Calculate the fluid cell index.
260  ijk = funijk(i,j,k)
261  IF(fluid_at(ijk)) THEN
262 
263 ! Assign PIJK(L,1:4)
264  pijk(np,1) = i
265  pijk(np,2) = j
266  pijk(np,3) = k
267  pijk(np,4) = ijk
268 
269  pinc(ijk) = pinc(ijk) + 1
270  ELSE
271 
272  write(*,*) 'Still not cool -->', iglobal_id(np)
273 
274 ! write(*,*) 'POS:',oPOS
275 ! call write_des_data
276 ! stop 'killer stop'
277  CALL delete_particle(np)
278 
279  ENDIF
280 
281 
282  1100 FORMAT('Warninge 1100: Particle ',a,' was recovered from a ', &
283  'ghost cell.',2/2x,'Moved into cell with ',a1,' index: ',a, &
284  /2x,a1,'-Position OLD:',g11.4,/2x,a1,'-Position NEW:',g11.4, &
285  /2x,a1,'-Velocity:',g11.4)
286 
287  1110 FORMAT('Warninge 1110: Particle ',a,' was deleted from a ', &
288  'ghost cell.',2/2x,'Moved into cell with ',a1,' index: ',a, &
289  /2x,a1,'-Position OLD:',g11.4,/2x,a1,'-Position NEW:',g11.4, &
290  /2x,a1,'-Velocity:',g11.4,/2x,'Fluid Cell: ',a,/2x, &
291  'Cut cell? ',l1,/2x,'Fluid at? ',l1)
292 
293  CALL finl_err_msg
294 
295  RETURN
296  END SUBROUTINE recover_parcel
297 
298 !vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv!
299 ! !
300 ! Subroutine: CHECK_CELL_MOVEMENT_PIC !
301 ! !
302 ! Purpose: Report which PIC particles have moved into ghost cells. !
303 ! Unlike DEM particles, this routine either deletes particles that !
304 ! are out of the domain, or reassigns the index to try and recover !
305 ! the particle. !
306 ! !
307 ! Notes: !
308 ! !
309 ! PIC particles may end up in ghost cells if the cell adjacent to the !
310 ! ghost cell is a cut-cell the particle was not detected outside the !
311 ! system because of tolerances. !
312 ! !
313 ! Future Work: !
314 ! !
315 ! 1. Redistribute particle's weight among other particles in the !
316 ! domain to conserve mass. !
317 ! !
318 ! 2. Rather than deactivating the particle, reflect the particle !
319 ! inside the domain using the ghost cell bc's !
320 ! !
321 !^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^!
322  SUBROUTINE check_cell_movement_pic
324 ! Global Variables:
325 !---------------------------------------------------------------------//
326 ! The (max) number of particles in process
327  use discretelement, only: pip, max_pip
328 ! The I/J/K/IJK indicies of the fluid cell
329  use discretelement, only: pijk
330 ! The number of particles in cell IJK
331  use discretelement, only: pinc
332 ! Particle positions New/Previous
333  use discretelement, only: des_pos_new, des_pos_old
334 ! The East/North/Top face loctions of fluid cells
335  use discretelement, only: xe, yn, zt
336 ! Particle velocities
337  use discretelement, only: des_vel_new
338 ! Flag: identifies a fluid cell as a cut cell.
339  use cutcell, only: cut_cell_at
340 
341  use mpi_utility
342  use error_manager
343  use functions
344 
345  IMPLICIT NONE
346 
347 ! Local Variables:
348 !----------------------------------------------------------------------!
349 ! particle no.
350  INTEGER :: L, I, J, K, IJK
351 ! Integer error flag.
352  INTEGER :: IER
353 ! Position
354  DOUBLE PRECISION :: lPOS
355 ! Number of deleted particles found on the local process
356  INTEGER :: lDELETED, gDELETED
357 ! Number of recovered particles found on the local process
358  INTEGER :: lRECOVERED, gRECOVERED
359 ! Local parameter to print verbose messages about particles.
360  LOGICAL, PARAMETER :: lDEBUG = .false.
361 
362 !.......................................................................
363 
364 
365  CALL init_err_msg("CHECK_CELL_MOVEMENT_PIC")
366  IF(ldebug) CALL open_pe_log(ier)
367 
368 
369 ! Initialize the counters for deleted/recovered parcels.
370  ldeleted = 0
371  lrecovered = 0
372 
373  DO l = 1, max_pip
374 ! skipping particles that do not exist
375  IF(.NOT.is_normal(l)) cycle
376 
377 ! assigning local aliases for particle i, j, k fluid grid indices
378  i = pijk(l,1)
379  j = pijk(l,2)
380  k = pijk(l,3)
381 
382 ! this ijk is still an old value as it has not been updated
383  ijk=pijk(l,4)
384 
385 ! in MPPIC a particle can lie on the surface of the wall as only the
386 ! centers are tracked.
387  IF (i > iend1 .OR. i < istart1) THEN
388 
389  lpos = des_pos_new(l,1)
390  IF(i.EQ.iend1+1 .AND. &
391  (lpos >= xe(iend1-1) .AND. lpos <= xe(iend1)) )THEN
392 
393  lrecovered = lrecovered + 1
394  pijk(l,1) = iend1
395 
396  IF(ldebug) THEN
397  WRITE(err_msg,1100) trim(ival(l)),'I',trim(ival(i)), &
398  'X',des_pos_old(l,1),'X',lpos,'X',des_vel_new(l,1)
399  CALL flush_err_msg
400  ENDIF
401  ELSE
402 
403  ldeleted = ldeleted + 1
404  CALL set_nonexistent(l)
405  pinc(ijk) = pinc(ijk) - 1
406 
407  IF(ldebug) THEN
408  WRITE(err_msg,1110) trim(ival(l)),'I',trim(ival(i)), &
409  'X',des_pos_old(l,1),'X',lpos,'X',des_vel_new(l,1), &
410  trim(ival(ijk)), cut_cell_at(ijk), fluid_at(ijk)
411  CALL flush_err_msg
412  ENDIF
413  cycle
414  ENDIF
415  ENDIF
416 
417  IF(j.GT.jend1 .OR. j.LT.jstart1) THEN
418  lpos = des_pos_new(l,2)
419  IF(j.EQ.jend1+1.AND.&
420  (lpos >= yn(jend1-1) .AND. lpos <= yn(jend1)) ) THEN
421 
422  lrecovered = lrecovered + 1
423  pijk(l,2) = jend1
424 
425  IF(ldebug) THEN
426  WRITE(err_msg,1100) trim(ival(l)),'J',trim(ival(j)), &
427  'Y',des_pos_old(l,2),'Y',lpos,'Y',des_vel_new(l,2)
428  CALL flush_err_msg
429  ENDIF
430 
431  ELSE
432 
433  ldeleted = ldeleted + 1
434  CALL set_nonexistent(l)
435  pinc(ijk) = pinc(ijk) - 1
436 
437  IF(ldebug) THEN
438  WRITE(err_msg,1110) trim(ival(l)),'J',trim(ival(j)), &
439  'Y',des_pos_old(l,2),'Y',lpos,'Y',des_vel_new(l,2), &
440  trim(ival(ijk)), cut_cell_at(ijk), fluid_at(ijk)
441  CALL flush_err_msg
442  ENDIF
443  cycle
444  ENDIF
445  ENDIF
446 
447  IF(do_k .AND. (k > kend1 .OR. k < kstart1)) THEN
448  lpos = des_pos_new(l,3)
449  IF(k == kend1+1 .AND. &
450  (lpos >= zt(kend1-1) .AND. lpos <= zt(kend1)) ) THEN
451 
452  lrecovered = lrecovered + 1
453  pijk(l,3) = kend1
454 
455  IF(ldebug) THEN
456  WRITE(err_msg,1100) trim(ival(l)),'K',trim(ival(k)), &
457  'Z',des_pos_old(l,3),'Z',lpos,'Z',des_vel_new(l,3)
458  CALL flush_err_msg
459  ENDIF
460  ELSE
461 
462  ldeleted = ldeleted + 1
463  CALL set_nonexistent(l)
464  pinc(ijk) = pinc(ijk) - 1
465 
466  IF(ldebug) THEN
467  WRITE(err_msg,1110) trim(ival(l)),'K',trim(ival(k)), &
468  'Z',des_pos_old(l,3),'Z',lpos,'Z',des_vel_new(l,3), &
469  trim(ival(ijk)), cut_cell_at(ijk), fluid_at(ijk)
470  CALL flush_err_msg
471  ENDIF
472  cycle
473  ENDIF
474  ENDIF
475  ENDDO
476 
477  1100 FORMAT('Warninge 1100: Particle ',a,' was recovered from a ', &
478  'ghost cell.',2/2x,'Moved into cell with ',a1,' index: ',a, &
479  /2x,a1,'-Position OLD:',g11.4,/2x,a1,'-Position NEW:',g11.4, &
480  /2x,a1,'-Velocity:',g11.4)
481 
482  1110 FORMAT('Warninge 1110: Particle ',a,' was deleted from a ', &
483  'ghost cell.',2/2x,'Moved into cell with ',a1,' index: ',a, &
484  /2x,a1,'-Position OLD:',g11.4,/2x,a1,'-Position NEW:',g11.4, &
485  /2x,a1,'-Velocity:',g11.4,/2x,'Fluid Cell: ',a,/2x, &
486  'Cut cell? ',l1,/2x,'Fluid at? ',l1)
487 
488 ! Update the number of particles
489  pip = pip - ldeleted
490 
491 ! Send the numbers to the IO process.
492  CALL global_sum(lrecovered, grecovered, pe_io)
493  CALL global_sum(ldeleted, gdeleted, pe_io)
494 
495  IF(grecovered + gdeleted > 0) THEN
496  WRITE(err_msg,1115) trim(ival(gdeleted + grecovered)), &
497  trim(ival(gdeleted)), trim(ival(grecovered))
498  CALL flush_err_msg
499  ENDIF
500 
501  1115 FORMAT('Warning 1115: ',a,' particles detected outside the ', &
502  'domain.',/2x,a,' particles were deleted.',/2x,a,' particles',&
503  ' were recovered.')
504 
505  CALL finl_err_msg
506 
507  RETURN
508  END SUBROUTINE check_cell_movement_pic
subroutine recover_parcel(NP)
integer dimension_i
Definition: param_mod.f:7
logical dem_solids
Definition: run_mod.f:257
integer imax2
Definition: geometry_mod.f:61
subroutine write_des_data
subroutine finl_err_msg
integer dimension_k
Definition: param_mod.f:9
integer jmin2
Definition: geometry_mod.f:89
subroutine init_err_msg(CALLER)
subroutine check_cell_movement
integer jmax2
Definition: geometry_mod.f:63
subroutine check_cell_movement_dem
integer kmax2
Definition: geometry_mod.f:65
Definition: run_mod.f:13
Definition: param_mod.f:2
logical, dimension(:), allocatable cut_cell_at
Definition: cutcell_mod.f:355
subroutine pic_search(IDX, lPOS, ENT_POS, lDIMN, lSTART, lEND)
character(len=line_length), dimension(line_count) err_msg
subroutine check_cell_movement_pic
subroutine delete_particle(NP)
integer imin2
Definition: geometry_mod.f:89
logical pic_solids
Definition: run_mod.f:258
subroutine open_pe_log(IER)
Definition: open_files.f:270
subroutine flush_err_msg(DEBUG, HEADER, FOOTER, ABORT, LOG, CALL_TREE)
integer kmin2
Definition: geometry_mod.f:89
integer dimension_j
Definition: param_mod.f:8