MFIX  2016-1
apply_wall_bc_pic.f
Go to the documentation of this file.
1 !vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv!
2 ! !
3 ! Subroutine: APPLY_WALL_BC_PIC !
4 ! Author: R. Garg !
5 ! !
6 ! Purpose: Detect collisions between PIC particles and STLs. !
7 ! !
8 !^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^!
9  SUBROUTINE apply_wall_bc_pic
10 
11 ! Global Variables:
12 !---------------------------------------------------------------------//
13 ! Particle postions: Current/Previous
14  use discretelement, only: des_pos_new
15 ! Paricle velocities
16  use discretelement, only: des_vel_new
17 ! Particle radius
18  use discretelement, only: des_radius
19 ! Max number of particles on this process
20  use discretelement, only: max_pip
21 ! Map from particle to DES grid cell.
22  use discretelement, only: dg_pijk, dtsolid
23 ! Flag indicating that the index cell contains no STLs
24  use stl, only: facets_at_dg
25 ! STL Vertices
26  use stl, only: vertex
27 ! STL Facet normals
28  use stl, only: norm_face
29 ! Minimum velocity to offset gravitational forces
31 ! Solids time step size
32  use discretelement, only: dtsolid
33 ! Gravitational force vector
34  use discretelement, only: grav
35 
36 ! Global Parameters:
37 !---------------------------------------------------------------------//
38  use param1, only: zero, small_number, one, undefined
39  use functions, only: is_nonexistent
40 
41 ! Module Procedures:
42 !---------------------------------------------------------------------//
44 
45  use error_manager
46 
47  IMPLICIT NONE
48 
49 ! Local Variables:
50 !---------------------------------------------------------------------//
51 ! Loop counters.
52  INTEGER NF, NP, LC1
53 ! STL normal vector
54  DOUBLE PRECISION :: NORM_PLANE(3)
55 ! line is parameterized as p = p_ref + t * dir_line, t is line_param
56  DOUBLE PRECISION :: LINE_T
57 
58 ! distance parcel travelled out of domain along the facet normal
59  DOUBLE PRECISION :: DIST(3), tPOS(3)
60 
61  DOUBLE PRECISION :: DT_RBND, RADSQ
62 !......................................................................!
63 
64  double precision :: vv(3)
65 
66 ! Minimum velocity needed to offset gravity.
67  minvel = -dtsolid*grav(:)
68  minvel_mag = dot_product(minvel,minvel)
69  oominvel_mag = 1.0d0/minvel_mag
70 
71  dt_rbnd = 1.01d0*dtsolid
72 
73  DO np = 1, max_pip
74 
75 ! Skip non-existent particles
76  IF(is_nonexistent(np)) cycle
77 
78 ! If no neighboring facet in the surrounding 27 cells, then exit
79  IF(facets_at_dg(dg_pijk(np))%COUNT < 1) cycle
80 
81  radsq = des_radius(np)*des_radius(np)
82 
83 ! Loop through the STLs associated with the DES grid cell.
84  lc1_lp: DO lc1=1, facets_at_dg(dg_pijk(np))%COUNT
85 
86 ! Get the index of the neighbor facet
87  nf = facets_at_dg(dg_pijk(np))%ID(lc1)
88 
89  norm_plane = norm_face(:,nf)
90 
91 ! IF(dot_product(NORM_PLANE, DES_VEL_NEW(NP,:)) > 0.d0) &
92 ! CYCLE LC1_LP
93 
94  vv = vertex(1,:,nf)
95  CALL intersectlnplane(des_pos_new(np,:), des_vel_new(np,:),&
96  vv, norm_face(:,nf), line_t)
97 
98  IF(abs(line_t) <= dt_rbnd) THEN
99 
100 ! Project the parcel onto the facet.
101  dist = line_t*des_vel_new(np,:)
102  tpos = des_pos_new(np,:) + dist
103 
104 ! Avoid collisions with STLs that are not next to the parcel
105  IF(hit_facet(vertex(:,:,nf), tpos)) THEN
106 
107 ! Correct the position of particles found too close to the STL.
108  IF(dot_product(dist,dist) <= radsq .OR. &
109  line_t <= zero) THEN
110  des_pos_new(np,:) = des_pos_new(np,:) + dist(:) + &
111  des_radius(np)*norm_plane
112  ENDIF
113 
114 ! Reflect the parcel.
115  CALL pic_reflect_part(np, norm_plane(:))
116  ENDIF
117  ENDIF
118 
119  ENDDO lc1_lp
120  END DO
121 
122  RETURN
123 
124  contains
125 
126 
127 !......................................................................!
128  LOGICAL FUNCTION hit_facet(VERTS, POINT)
130  DOUBLE PRECISION, INTENT(IN) :: VERTS(3,3)
131  DOUBLE PRECISION, INTENT(IN) :: POINT(3)
132 
133  DOUBLE PRECISION :: V0(3), V1(3), V2(3)
134  DOUBLE PRECISION :: d00, d01, d02, d11, d12
135 
136  DOUBLE PRECISION :: OoDEN, u, v
137 
138  v0 = verts(3,:) - verts(1,:)
139  v1 = verts(2,:) - verts(1,:)
140  v2 = point - verts(1,:)
141 
142  d00 = dot_product(v0,v0)
143  d01 = dot_product(v0,v1)
144  d02 = dot_product(v0,v2)
145 
146  d11 = dot_product(v1,v1)
147  d12 = dot_product(v1,v2)
148 
149  ooden = 1.0d0/(d00*d11 - d01*d01)
150  u = (d11*d02 - d01*d12)*ooden
151  v = (d00*d12 - d01*d02)*ooden
152 
153  hit_facet = ((u>=0.0d0) .AND. (v>=0.0d0) .AND. (u+v < 1.0d0))
154 
155  RETURN
156  END FUNCTION hit_facet
157 
158  END SUBROUTINE apply_wall_bc_pic
159 
160 
161 !vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvC
162 ! C
163 ! Subroutine: PIC_REFLECT_PARTICLE C
164 ! Purpose: C
165 ! C
166 !^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^C
167  SUBROUTINE pic_reflect_part(LL, WALL_NORM)
169  USE discretelement, only : dimn, des_vel_new
171 
172 ! Minimum velocity to offset gravitational forces
173  use pic_bc, only: minvel, minvel_mag, oominvel_mag
174 
175 
176  use param1, only: small_number
177 
178  IMPLICIT NONE
179 !-----------------------------------------------
180 ! Dummy arguments
181 !-----------------------------------------------
182  INTEGER, INTENT(IN) :: LL
183  DOUBLE PRECISION, INTENT(IN) :: WALL_NORM(dimn)
184 !-----------------------------------------------
185 ! Local variables
186 !-----------------------------------------------
187  !magnitude of pre-collisional normal and tangential velocity components
188  DOUBLE PRECISION :: VEL_NORMMAG_APP
189 
190  !pre collisional normal and tangential velocity components in vector format
191  !APP ==> approach
192  DOUBLE PRECISION :: VEL_NORM_APP(dimn), VEL_TANG_APP(dimn)
193 
194 
195  !post collisional normal and tangential velocity components in vector format
196  !SEP ==> separation
197  DOUBLE PRECISION :: VEL_NORM_SEP(dimn), VEL_TANG_SEP(dimn)
198 
199  DOUBLE PRECISION :: COEFF_REST_EN, COEFF_REST_ET
200 
201 ! Minimum particle velocity with respect to gravity. This ensures that
202 ! walls "push back" to offset gravitational forces.
203  DOUBLE PRECISION :: projGRAV(3)
204 
205  INTEGER :: LC
206 
207 !-----------------------------------------------
208 
209 
210 
211 
212 
213  vel_normmag_app = dot_product(wall_norm(:), des_vel_new(ll,:))
214 
215 ! Currently assuming that wall is at rest. Needs improvement for moving wall
216 
217  vel_norm_app(:) = vel_normmag_app*wall_norm(:)
218  vel_tang_app(:) = des_vel_new(ll,:) - vel_norm_app(:)
219 
220 
221 !post collisional velocities
222 
223  coeff_rest_en = mppic_coeff_en_wall
224  coeff_rest_et = mppic_coeff_et_wall
225 
226  vel_norm_sep(:) = -coeff_rest_en*vel_norm_app(:)
227  vel_tang_sep(:) = coeff_rest_et*vel_tang_app(:)
228 
229  des_vel_new(ll,:) = vel_norm_sep(:) + vel_tang_sep(:)
230 
231  IF(dot_product(wall_norm, minvel) > 0.0d0)THEN
232 
233 ! Projection of rebound velocity onto mininum velocity.
234  projgrav = dot_product(minvel, des_vel_new(ll,:))*oominvel_mag
235  projgrav = minvel*projgrav
236 
237  IF(dot_product(projgrav, projgrav) < minvel_mag) THEN
238  DO lc=1,3
239  IF(minvel(lc) > small_number) THEN
240  des_vel_new(ll,lc)=max(des_vel_new(ll,lc),minvel(lc))
241  ELSEIF(minvel(lc) < -small_number) THEN
242  des_vel_new(ll,lc)=min(des_vel_new(ll,lc),minvel(lc))
243  ENDIF
244  ENDDO
245 
246  ENDIF
247  ENDIF
248 
249  RETURN
250  END SUBROUTINE pic_reflect_part
251 
252 
253 !
254  SUBROUTINE out_this_stl(LC)
256  Use usr
257 
258 ! STL Vertices
259  use stl, only: vertex
260 ! STL Facet normals
261  use stl, only: norm_face
262 
263 
264  IMPLICIT NONE
265 !-----------------------------------------------
266  integer, INTENT(IN) :: lc
267 
268  logical :: lExists
269  character(len=8) :: IDX
270 
271 
272  write(idx,"(I8.8)") lc
273  inquire(file='geo_'//idx//'.stl', exist=lexists)
274 
275  IF(lexists) RETURN
276 
277  open(unit=555, file='geo_'//idx//'.stl', status='UNKNOWN')
278  write(555,*) 'solid vcg'
279  write(555,*) ' facet normal ', norm_face(:,lc)
280  write(555,*) ' outer loop'
281  write(555,*) ' vertex ', vertex(1,1:3,lc)
282  write(555,*) ' vertex ', vertex(2,1:3,lc)
283  write(555,*) ' vertex ', vertex(3,1:3,lc)
284  write(555,*) ' endloop'
285  write(555,*) ' endfacet'
286  close(555)
287 
288  RETURN
289  END SUBROUTINE out_this_stl
290 
291 
292 
293 
294 !vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvC
295 ! C
296 ! SUBROUTINE: CHECK_IF_PARCEL_OVERLAPS_STL C
297 ! Authors: Rahul Garg Date: 21-Mar-2014 C
298 ! C
299 ! Purpose: This subroutine is special written to check if a particle C
300 ! overlaps any of the STL faces. The routine exits on C
301 ! detecting an overlap. It is called after initial C
302 ! generation of lattice configuration to remove out of domain C
303 ! particles C
304 ! C
305 !^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^C
306  SUBROUTINE check_if_parcel_overlaps_stl(POS, OVERLAP_EXISTS)
308  USE discretelement, only: max_radius
309  USE geometry, only: do_k
310 
312  USE desgrid
313  USE stl
314 
315  Implicit none
316 
317  DOUBLE PRECISION, INTENT(IN) :: POS(3)
318  LOGICAL, INTENT(OUT) :: OVERLAP_EXISTS
319 
320  INTEGER I, J, K, IJK, NF, LC
321 
322 ! line is parameterized as p = p_ref + t * dir_line, t is line_param
323  DOUBLE PRECISION :: LINE_T
324  DOUBLE PRECISION :: DIST(3), RADSQ
325  double precision :: vv(3)
326 
327  k = 1
328  IF(do_k) k = min(dg_kend2,max(dg_kstart2,kofpos(pos(3))))
329  j = min(dg_jend2,max(dg_jstart2,jofpos(pos(2))))
330  i = min(dg_iend2,max(dg_istart2,iofpos(pos(1))))
331 
332  ijk = dg_funijk(i,j,k)
333  IF(facets_at_dg(ijk)%COUNT < 1) RETURN
334 
335  overlap_exists = .true.
336 
337 ! Pad the max radius to keep parcels sufficiently away from walls.
338  radsq = (1.1d0*max_radius)**2
339 
340 ! Parametrize a line as p = p_0 + t normal and intersect with the
341 ! triangular plane.
342 
343 ! If t>0, then point is on the non-fluid side of the plane, if the
344 ! plane normal is assumed to point toward the fluid side.
345  DO lc = 1, facets_at_dg(ijk)%COUNT
346  nf = facets_at_dg(ijk)%ID(lc)
347 
348  vv = vertex(1,:,nf)
349  CALL intersectlnplane(pos, norm_face(:,nf), &
350  vv, norm_face(:,nf), line_t)
351 
352 ! Orthogonal projection puts the point outside of the domain or less than
353 ! one particle radius to the facet.
354  dist = line_t*norm_face(:,nf)
355  IF(line_t > zero .OR. dot_product(dist,dist) <= radsq) RETURN
356 
357  ENDDO
358 
359  overlap_exists = .false.
360 
361  RETURN
362  END SUBROUTINE check_if_parcel_overlaps_stl
363 
364 
365 !----------------------------------------------------------------------!
366 ! !
367 ! !
368 ! !
369 ! !
370 !----------------------------------------------------------------------!
371  SUBROUTINE write_this_facet_and_parcel(FID, position, velocity)
372  USE run
373  USE param1
374  USE discretelement
375  USE geometry
376  USE compar
377  USE constant
378  USE cutcell
379  USE funits
380  USE indices
381  USE physprop
382  USE parallel
383  USE stl
385  Implicit none
386  !facet id and particle id
387  double precision, intent(in), dimension(dimn) :: position, velocity
388  Integer, intent(in) :: fid
389  Integer :: stl_unit, vtp_unit , k
390  CHARACTER(LEN=100) :: stl_fname, vtp_fname
391  real :: temp_array(3)
392 
393  stl_unit = 1001
394  vtp_unit = 1002
395 
396  WRITE(vtp_fname,'(A,"_OFFENDING_PARTICLE",".vtp")') trim(run_name)
397  WRITE(stl_fname,'(A,"_STL_FACE",".stl")') trim(run_name)
398 
399  open(vtp_unit, file = vtp_fname, form='formatted',convert='big_endian')
400  open(stl_unit, file = stl_fname, form='formatted',convert='big_endian')
401 
402  write(vtp_unit,"(a)") '<?xml version="1.0"?>'
403  write(vtp_unit,"(a,es24.16,a)") '<!-- time =',s_time,'s -->'
404  write(vtp_unit,"(a,a)") '<VTKFile type="PolyData"',&
405  ' version="0.1" byte_order="LittleEndian">'
406  write(vtp_unit,"(3x,a)") '<PolyData>'
407  write(vtp_unit,"(6x,a,i10.10,a,a)")&
408  '<Piece NumberOfPoints="',1,'" NumberOfVerts="0" ',&
409  'NumberOfLines="0" NumberOfStrips="0" NumberOfPolys="0">'
410  write(vtp_unit,"(9x,a)")&
411  '<PointData Scalars="Diameter" Vectors="Velocity">'
412  write(vtp_unit,"(12x,a)")&
413  '<DataArray type="Float32" Name="Diameter" format="ascii">'
414  write (vtp_unit,"(15x,es13.6)") (1.d0)
415  write(vtp_unit,"(12x,a)") '</DataArray>'
416 
417  temp_array = zero
418  temp_array(1:dimn) = velocity(1:dimn)
419  write(vtp_unit,"(12x,a,a)") '<DataArray type="Float32" ',&
420  'Name="Velocity" NumberOfComponents="3" format="ascii">'
421  write (vtp_unit,"(15x,3(es13.6,3x))")&
422  ((temp_array(k)),k=1,3)
423  write(vtp_unit,"(12x,a,/9x,a)") '</DataArray>','</PointData>'
424  ! skip cell data
425  write(vtp_unit,"(9x,a)") '<CellData></CellData>'
426 
427  temp_array = zero
428  temp_array(1:dimn) = position(1:dimn)
429  write(vtp_unit,"(9x,a)") '<Points>'
430  write(vtp_unit,"(12x,a,a)") '<DataArray type="Float32" ',&
431  'Name="Position" NumberOfComponents="3" format="ascii">'
432  write (vtp_unit,"(15x,3(es13.6,3x))")&
433  ((temp_array(k)),k=1,3)
434  write(vtp_unit,"(12x,a,/9x,a)")'</DataArray>','</Points>'
435  ! Write tags for data not included (vtp format style)
436  write(vtp_unit,"(9x,a,/9x,a,/9x,a,/9x,a)")'<Verts></Verts>',&
437  '<Lines></Lines>','<Strips></Strips>','<Polys></Polys>'
438  write(vtp_unit,"(6x,a,/3x,a,/a)")&
439  '</Piece>','</PolyData>','</VTKFile>'
440 
441  !Now write the facet info
442 
443  write(stl_unit,*)'solid vcg'
444 
445  write(stl_unit,*) ' facet normal ', norm_face(1:3,fid)
446  write(stl_unit,*) ' outer loop'
447  write(stl_unit,*) ' vertex ', vertex(1,1:3,fid)
448  write(stl_unit,*) ' vertex ', vertex(2,1:3,fid)
449  write(stl_unit,*) ' vertex ', vertex(3,1:3,fid)
450  write(stl_unit,*) ' endloop'
451  write(stl_unit,*) ' endfacet'
452 
453  write(stl_unit,*)'endsolid vcg'
454 
455  close(vtp_unit, status = 'keep')
456  close(stl_unit, status = 'keep')
457  write(*,*) 'wrote a facet and a parcel. now waiting'
458  read(*,*)
459  end SUBROUTINE write_this_facet_and_parcel
460 
type(facets_to_dg), dimension(:), allocatable facets_at_dg
Definition: stl_mod.f:76
double precision, parameter one
Definition: param1_mod.f:29
double precision, dimension(3, 3, dim_stl) vertex
Definition: stl_mod.f:20
character(len=60) run_name
Definition: run_mod.f:24
integer dg_kstart2
Definition: desgrid_mod.f:53
logical function hit_facet(VERTS, POINT)
double precision, parameter undefined
Definition: param1_mod.f:18
subroutine intersectlnplane(ref_line, dir_line, ref_plane, norm_plane, line_param)
double precision oominvel_mag
Definition: pic_bc_mod.f:63
double precision mppic_coeff_et_wall
Definition: mfix_pic_mod.f:43
subroutine check_if_parcel_overlaps_stl(POS, OVERLAP_EXISTS)
subroutine apply_wall_bc_pic
integer dg_kend2
Definition: desgrid_mod.f:53
integer function iofpos(fpos)
Definition: desgrid_mod.f:348
double precision, parameter small_number
Definition: param1_mod.f:24
subroutine write_this_facet_and_parcel(FID, position, velocity)
Definition: stl_mod.f:1
integer dg_jstart2
Definition: desgrid_mod.f:49
double precision, dimension(3, dim_stl) norm_face
Definition: stl_mod.f:22
Definition: run_mod.f:13
integer function kofpos(fpos)
Definition: desgrid_mod.f:372
double precision minvel_mag
Definition: pic_bc_mod.f:63
integer dg_iend2
Definition: desgrid_mod.f:45
Definition: usr_mod.f:1
double precision, dimension(3) minvel
Definition: pic_bc_mod.f:63
logical do_k
Definition: geometry_mod.f:30
integer dg_istart2
Definition: desgrid_mod.f:45
integer function dg_funijk(fi, fj, fk)
Definition: desgrid_mod.f:141
integer function jofpos(fpos)
Definition: desgrid_mod.f:360
integer dg_jend2
Definition: desgrid_mod.f:49
double precision mppic_coeff_en_wall
Definition: mfix_pic_mod.f:43
subroutine pic_reflect_part(LL, WALL_NORM)
double precision, parameter zero
Definition: param1_mod.f:27
subroutine out_this_stl(LC)