MFIX  2016-1
stl_functions_des_mod.f
Go to the documentation of this file.
1 !vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv!
2 ! !
3 ! Module name: stl_functions_des !
4 ! Author: Rahul Garg Date: 24-Oct-13 !
5 ! !
6 ! Purpose: This module containd routines for geometric interaction !
7 ! required for STL files. !
8 ! !
9 !^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^!
11 
12  IMPLICIT NONE
13 
14 ! Use this module only to define functions and subroutines.
15  CONTAINS
16 
17 !vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv!
18 ! !
19 ! Subroutine: ClosestPtPointTriangle !
20 ! Author: Rahul Garg Date: 24-Oct-13 !
21 ! !
22 ! Purpose: !
23 ! !
24 !^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^!
25  Subroutine closestptpointtriangle(pointp, points, closest_point)
26  USE param1, only: zero, one
27  USE discretelement, only: dimn
28 
29  IMPLICIT NONE
30 
31 ! points are the three nodes of the triangle
32 ! point p is the sphere center
33  double precision, intent(in), dimension(3,3) :: points
34  double precision, intent(in), dimension(dimn) :: pointp
35  double precision, intent(out), dimension(dimn) :: closest_point
36 ! Local variables
37  double precision, dimension(3) :: pointa, pointb, pointc
38  double precision, dimension(dimn) :: ab, ac, ap, bp,cp
39  double precision :: d1, d2, d3, d4, vc, v, d5, d6, vb, w, va, denom
40 
41  pointa = points(1,:)
42  pointb = points(2,:)
43  pointc = points(3,:)
44 
45  ab = pointb - pointa
46  ac = pointc - pointa
47  ap = pointp - pointa
48  d1 = dot_product(ab, ap)
49  d2 = dot_product(ac, ap)
50 
51  IF(d1 <= zero .AND. d2 <= zero) then
52  closest_point = pointa
53  return
54  end if
55 
56 ! Check if P in vertex region outside B
57  bp = pointp - pointb
58  d3 = dot_product(ab, bp);
59  d4 = dot_product(ac, bp);
60  if (d3 >= zero .and. d4 <= d3) then
61  closest_point = pointb
62  return
63  endif
64 
65 ! Check if P in edge region of AB, if so return projection of P onto AB
66  vc = d1*d4 - d3*d2;
67  if (vc <= zero .and. d1 >= zero .and. d3 <= zero) then
68  v = d1 / (d1 - d3);
69  closest_point = pointa + v * ab;
70  return
71  end if
72 
73 ! Check if P in vertex region outside C
74  cp = pointp - pointc
75  d5 = dot_product(ab, cp)
76  d6 = dot_product(ac, cp)
77  if (d6 >= zero .and. d5 <= d6) then
78  closest_point = pointc
79  return
80  endif
81 
82 ! Check if P in edge region of AC, if so return projection of P onto AC
83  vb = d5*d2 - d1*d6
84 
85  if (vb <= zero .and. d2 >= zero .and. d6 <= zero) then
86  w = d2 / (d2 - d6)
87  closest_point = pointa + w * ac
88  return
89  end if
90 
91 ! Check if P in edge region of BC, if so return projection of P onto BC
92  va = d3*d6 - d5*d4
93  if (va <= zero .and.(d4 - d3) >= zero .and. (d5 - d6) >= zero) then
94  w = (d4 - d3) / ((d4 - d3) + (d5 - d6))
95  closest_point = pointb + w * (pointc - pointb)
96  return
97  end if
98 
99 
100 ! P inside face region. Compute Q through its barycentric coordinates (u,v,w)
101  denom = one / (va + vb + vc)
102  v = vb * denom
103  w = vc * denom
104  closest_point = pointa + ab * v + ac * w;
105  return
106  end Subroutine closestptpointtriangle
107 
108 
109 
110 !vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv!
111 ! !
112 ! Subroutine: intersectLnPlane !
113 ! Author: Rahul Garg Date: 24-Oct-13 !
114 ! !
115 ! Purpose: !
116 ! !
117 !^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^!
118  Subroutine intersectlnplane(ref_line, dir_line, ref_plane, &
119  norm_plane, line_param)
121  USE discretelement, only: dimn
122  USE param1, only: zero
123 
124  IMPLICIT NONE
125 
126 ! Reference point and direction of the line
127  DOUBLE PRECISION, INTENT(IN) :: REF_LINE(3), DIR_LINE(3)
128 ! reference point and normal of the plane
129  DOUBLE PRECISION, INTENT(IN) :: REF_PLANE(3), NORM_PLANE(3)
130 
131 ! line is parameterized as p = p_ref + t * dir_line, t is line_param
132  double precision, intent(out) :: line_param
133 
134  !local vars
135  double precision :: denom
136 
137  denom = dot_product(dir_line, norm_plane)
138 
139  if(denom*denom.gt.zero) then
140  line_param = dot_product(ref_plane-ref_line, norm_plane)
141  line_param = line_param/denom
142  endif
143 
144  return
145  end subroutine intersectlnplane
146 
147 !......................................................................!
148 ! Subroutine TRI_BOX_OVERLAP !
149 ! Author: J.Musser Date: 10-22-2015 !
150 ! !
151 ! Purpose: Determine if a box (DES grid cell) intersects the triangle !
152 ! (SLT). Note that the DES grid size is slightly increased to !
153 ! capture STLs near the boarder of the cell. Otherwise, some !
154 ! collisions could ve over looked. !
155 ! !
156 ! Author: Tomas Akenine-Moller Accessed: 10-22-2015 !
157 ! REF: http://fileadmin.cs.lth.se/cs/Personal/Tomas_Akenine-Moller/ !
158 ! code/tribox2.txt !
159 !......................................................................!
160  SUBROUTINE tri_box_overlap(pCENTER, pHALFSIZE, pVERTS, pOVERLAP)
162  IMPLICIT NONE
163 
164  DOUBLE PRECISION, INTENT(IN) :: pCENTER(3), pHALFSIZE(3)
165  DOUBLE PRECISION, INTENT(IN) :: pVERTS(3,3)
166  LOGICAL, INTENT(OUT) :: pOVERLAP
167 
168  DOUBLE PRECISION :: v0(3), v1(3), v2(3)
169  DOUBLE PRECISION :: fex, fey, fez
170  DOUBLE PRECISION :: normal(3), e0(3), e1(3), e2(3)
171 
172  poverlap = .false.
173 
174  v0 = pverts(1,:) - pcenter
175  v1 = pverts(2,:) - pcenter
176  v2 = pverts(3,:) - pcenter
177 
178  e0 = v1-v0
179  e1 = v2-v1
180  e2 = v0-v2
181 
182  fex = abs(e0(1))
183  fey = abs(e0(2))
184  fez = abs(e0(3))
185 
186  if(atest_x01(e0(3),e0(2),fez,fey)) return
187  if(atest_y02(e0(3),e0(1),fez,fex)) return
188  if(atest_z12(e0(2),e0(1),fey,fex)) return
189 
190  fex = abs(e1(1))
191  fey = abs(e1(2))
192  fez = abs(e1(3))
193 
194  if(atest_x01(e1(3),e1(2),fez,fey)) return
195  if(atest_y02(e1(3),e1(1),fez,fex)) return
196  if(atest_z0(e1(2),e1(1),fey,fex)) return
197 
198  fex = abs(e2(1))
199  fey = abs(e2(2))
200  fez = abs(e2(3))
201 
202  if(atest_x2(e2(3),e2(2),fez,fey)) return
203  if(atest_y1(e2(3),e2(1),fez,fex)) return
204  if(atest_z12(e2(2),e2(1),fey,fex)) return
205 
206  if(findmin(v0(1),v1(1),v2(1)) > phalfsize(1) .OR. &
207  findmax(v0(1),v1(1),v2(1)) <-phalfsize(1)) return
208 
209  if(findmin(v0(2),v1(2),v2(2)) > phalfsize(2) .OR. &
210  findmax(v0(2),v1(2),v2(2)) <-phalfsize(2)) return
211 
212  if(findmin(v0(3),v1(3),v2(3)) > phalfsize(3) .OR. &
213  findmax(v0(3),v1(3),v2(3)) <-phalfsize(3)) return
214 
215 
216  normal(1) = e0(2)*e1(3)-e0(3)*e1(2)
217  normal(2) = e0(3)*e1(1)-e0(1)*e1(3)
218  normal(3) = e0(1)*e1(2)-e0(2)*e1(1)
219 
220  if(.NOT.planeboxoverlap(normal,v0,phalfsize)) return
221 
222  poverlap = .true.
223 
224  RETURN
225 
226  CONTAINS
227 
228 !``````````````````````````````````````````````````````````````````````!
229 ! Function: planeBoxOverlap !
230 ! Support function for TRI_BOX_OVERLAP !
231 !``````````````````````````````````````````````````````````````````````!
232  LOGICAL FUNCTION planeboxoverlap(norm, vert, maxbox)
234  double precision :: norm(3), vert(3), maxbox(3)
235 
236  integer :: lc
237  double precision :: vmin(3), vmax(3), v
238 
239  do lc=1,3
240  v=vert(lc)
241  if(norm(lc) > 0.0d0) then
242  vmin(lc) = -maxbox(lc) - v
243  vmax(lc) = maxbox(lc) - v
244  else
245  vmin(lc) = maxbox(lc) - v
246  vmax(lc) =-maxbox(lc) - v
247  endif
248  enddo
249 
250  if(dot_product(norm,vmin) > 0.0d0) then
251  planeboxoverlap = .false.
252  return
253  elseif(dot_product(norm,vmax) >= 0.0d0) then
254  planeboxoverlap = .true.
255  return
256  endif
257 
258  planeboxoverlap = .false.
259  return
260 
261  RETURN
262  END FUNCTION planeboxoverlap
263 
264 !``````````````````````````````````````````````````````````````````````!
265 ! Function: findMin !
266 ! Support function for TRI_BOX_OVERLAP !
267 !``````````````````````````````````````````````````````````````````````!
268  DOUBLE PRECISION FUNCTION findmin(x0,x1,x2)
270  double precision :: x0,x1,x2
271 
272  findmin = x0
273 
274  if(x1<findmin) findmin=x1
275  if(x2<findmin) findmin=x2
276 
277  RETURN
278  END FUNCTION findmin
279 
280 !``````````````````````````````````````````````````````````````````````!
281 ! Function: findMax !
282 ! Support function for TRI_BOX_OVERLAP !
283 !``````````````````````````````````````````````````````````````````````!
284  DOUBLE PRECISION FUNCTION findmax(x0,x1,x2)
286  double precision :: x0,x1,x2
287 
288  findmax = x0
289 
290  if(x1>findmax) findmax=x1
291  if(x2>findmax) findmax=x2
292 
293  RETURN
294  END FUNCTION findmax
295 
296 !``````````````````````````````````````````````````````````````````````!
297 ! Function: ATEST_X01 !
298 ! Support function for TRI_BOX_OVERLAP !
299 !``````````````````````````````````````````````````````````````````````!
300  LOGICAL FUNCTION atest_x01(a,b,fa,fb)
302  double precision :: a, b, fa, fb
303  double precision :: lMin, lMax, p0, p2, rad
304 
305  p0 = a*v0(2) - b*v0(3)
306  p2 = a*v2(2) - b*v2(3)
307 
308  if(p0<p2) then; lmin=p0; lmax=p2
309  else; lmin=p2; lmax=p0; endif
310 
311  rad=fa*phalfsize(2) + fb*phalfsize(3)
312  atest_x01=(lmin>rad .OR. lmax<-rad)
313 
314  END FUNCTION atest_x01
315 
316 !``````````````````````````````````````````````````````````````````````!
317 ! Function: ATEST_X2 !
318 ! Support function for TRI_BOX_OVERLAP !
319 !``````````````````````````````````````````````````````````````````````!
320  LOGICAL FUNCTION atest_x2(a,b,fa,fb)
322  double precision :: a, b, fa, fb
323  double precision :: lMin, lMax, p0, p1, rad
324 
325  p0 = a*v0(2) - b*v0(3)
326  p1 = a*v1(2) - b*v1(3)
327 
328  if(p0<p1) then; lmin=p0; lmax=p1
329  else; lmin=p1; lmax=p0; endif
330 
331  rad=fa*phalfsize(2) + fb*phalfsize(3)
332  atest_x2=(lmin>rad .OR. lmax<-rad)
333 
334  END FUNCTION atest_x2
335 
336 !``````````````````````````````````````````````````````````````````````!
337 ! Function: ATEST_Y02 !
338 ! Support function for TRI_BOX_OVERLAP !
339 !``````````````````````````````````````````````````````````````````````!
340  LOGICAL FUNCTION atest_y02(a,b,fa,fb)
342  double precision :: a, b, fa, fb
343  double precision :: lMin, lMax, p0, p2, rad
344 
345  p0 = -a*v0(1) + b*v0(3)
346  p2 = -a*v2(1) + b*v2(3)
347 
348  if(p0<p2) then; lmin=p0; lmax=p2
349  else; lmin=p2; lmax=p0; endif
350 
351  rad=fa*phalfsize(1) + fb*phalfsize(3)
352  atest_y02=(lmin>rad .OR. lmax<-rad)
353 
354  END FUNCTION atest_y02
355 
356 !``````````````````````````````````````````````````````````````````````!
357 ! Function: ATEST_Y1 !
358 ! Support function for TRI_BOX_OVERLAP !
359 !``````````````````````````````````````````````````````````````````````!
360  LOGICAL FUNCTION atest_y1(a,b,fa,fb)
362  double precision :: a, b, fa, fb
363  double precision :: lMin, lMax, p0, p1, rad
364 
365  p0 = -a*v0(1) + b*v0(3)
366  p1 = -a*v1(1) + b*v1(3)
367 
368  if(p0<p1) then; lmin=p0; lmax=p1
369  else; lmin=p1; lmax=p0; endif
370 
371  rad=fa*phalfsize(1) + fb*phalfsize(3)
372  atest_y1=(lmin>rad .OR. lmax<-rad)
373 
374  END FUNCTION atest_y1
375 
376 !``````````````````````````````````````````````````````````````````````!
377 ! Function: ATEST_Z12 !
378 ! Support function for TRI_BOX_OVERLAP !
379 !``````````````````````````````````````````````````````````````````````!
380  LOGICAL FUNCTION atest_z12(a,b,fa,fb)
382  double precision :: a, b, fa, fb
383  double precision :: lMin, lMax, p1, p2, rad
384 
385  p1 = a*v1(1) - b*v1(2)
386  p2 = a*v2(1) - b*v2(2)
387 
388  if(p2<p1) then; lmin=p2; lmax=p1
389  else; lmin=p1; lmax=p2; endif
390 
391  rad=fa*phalfsize(1) + fb*phalfsize(2)
392  atest_z12=(lmin>rad .OR. lmax<-rad)
393 
394  END FUNCTION atest_z12
395 
396 !``````````````````````````````````````````````````````````````````````!
397 ! Function: ATEST_Z0 !
398 ! Support function for TRI_BOX_OVERLAP !
399 !``````````````````````````````````````````````````````````````````````!
400  LOGICAL FUNCTION atest_z0(a,b,fa,fb)
402  double precision :: a, b, fa, fb
403  double precision :: lMin, lMax, p0, p1, rad
404 
405  p0 = a*v0(1) - b*v0(2)
406  p1 = a*v1(1) - b*v1(2)
407 
408  if(p0<p1) then; lmin=p0; lmax=p1
409  else; lmin=p1; lmax=p0; endif
410 
411  rad=fa*phalfsize(1) + fb*phalfsize(2)
412  atest_z0=(lmin>rad .OR. lmax<-rad)
413 
414  END FUNCTION atest_z0
415 
416  END SUBROUTINE tri_box_overlap
417 
418 
419 !vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv!
420 ! !
421 ! SUBROUTINE: CHECK_IF_PARTICLE_OVERLAPS_STL !
422 ! Authors: Rahul Garg Date: 21-Mar-2014 !
423 ! !
424 ! Purpose: This subroutine is special written to check if a particle !
425 ! overlaps any of the STL faces. The routine exits on !
426 ! detecting an overlap. It is called after initial !
427 ! generation of lattice configuration to remove out of domain !
428 ! particles !
429 ! !
430 !^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^!
431  SUBROUTINE check_if_particle_overlaps_stl(POS, fI, fJ, fK, REMOVE)
433  USE compar
434  USE constant
435  USE cutcell
436  USE desgrid
437  USE discretelement, ONLY: dimn, xe, yn, zt, max_radius
438  USE functions
439  USE geometry
440  USE indices
441  USE param1
442  USE run
443  USE stl
444 
445  Implicit none
446 
447  DOUBLE PRECISION, INTENT(IN) :: POS(dimn)
448  INTEGER, INTENT(IN) :: fI, fJ, fK
449  LOGICAL, INTENT(OUT) :: REMOVE
450 
451 ! Integers mapping the fluid cell corners to DES Grid indices.
452  INTEGER :: I1, I2, J1, J2, K1, K2
453 
454  INTEGER I, J, K, IJK, NF, LC
455 
456  DOUBLE PRECISION :: LINE_T
457  DOUBLE PRECISION :: RADSQ, DIST(3)
458 
459  double precision :: vv(3)
460 
461  remove = .true.
462 
463  i1 = iofpos(xe(fi-1))
464  i2 = iofpos(xe( fi ))
465 
466  j1 = jofpos(yn(fj-1))
467  j2 = jofpos(yn( fj ))
468 
469  k1 = kofpos(zt(fk-1))
470  k2 = kofpos(zt( fk ))
471 
472  radsq = (1.05d0*max_radius)**2
473 
474  DO k = k1, k2
475  DO j = j1, j2
476  DO i = i1, i2
477 
478  IF(.NOT.dg_is_on_mype_plus1layers(i,j,k)) cycle
479 
480  ijk = dg_funijk(i,j,k)
481 
482 ! The point is on the non-fluid side of the plane if t>0
483  DO lc = 1, facets_at_dg(ijk)%COUNT
484  nf = facets_at_dg(ijk)%ID(lc)
485 
486  vv = vertex(1,:,nf)
487  CALL intersectlnplane(pos, norm_face(:,nf), &
488  vv, norm_face(:,nf), line_t)
489 
490 ! Orthogonal projection puts the point outside of the domain or less than
491 ! one particle radius to the facet.
492  dist = line_t*norm_face(:,nf)
493  IF(line_t > zero .OR. dot_product(dist,dist)<=radsq) RETURN
494 
495  ENDDO
496  ENDDO
497  ENDDO
498  ENDDO
499 
500  remove = .false.
501 
502  RETURN
503  END SUBROUTINE check_if_particle_overlaps_stl
504 
505  END MODULE stl_functions_des
logical function planeboxoverlap(norm, vert, maxbox)
subroutine tri_box_overlap(pCENTER, pHALFSIZE, pVERTS, pOVERLAP)
type(facets_to_dg), dimension(:), allocatable facets_at_dg
Definition: stl_mod.f:76
logical function atest_y02(a, b, fa, fb)
subroutine closestptpointtriangle(pointp, points, closest_point)
logical function dg_is_on_mype_plus1layers(lI, lJ, lK)
Definition: desgrid_mod.f:403
double precision, parameter one
Definition: param1_mod.f:29
subroutine check_if_particle_overlaps_stl(POS, fI, fJ, fK, REMOVE)
logical function atest_x2(a, b, fa, fb)
double precision, dimension(3, 3, dim_stl) vertex
Definition: stl_mod.f:20
subroutine intersectlnplane(ref_line, dir_line, ref_plane, norm_plane, line_param)
logical function atest_z12(a, b, fa, fb)
logical function atest_z0(a, b, fa, fb)
integer function iofpos(fpos)
Definition: desgrid_mod.f:348
Definition: stl_mod.f:1
double precision, dimension(3, dim_stl) norm_face
Definition: stl_mod.f:22
double precision function findmin(x0, x1, x2)
Definition: run_mod.f:13
integer function kofpos(fpos)
Definition: desgrid_mod.f:372
integer function dg_funijk(fi, fj, fk)
Definition: desgrid_mod.f:141
integer function jofpos(fpos)
Definition: desgrid_mod.f:360
logical function atest_x01(a, b, fa, fb)
double precision function findmax(x0, x1, x2)
double precision, parameter zero
Definition: param1_mod.f:27
logical function atest_y1(a, b, fa, fb)