tetrahedron.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "tetrahedron.H"
27 #include "triPointRef.H"
28 #include "scalarField.H"
29 
30 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
31 
32 template<class Point, class PointRef>
34 (
35  const tetrahedron<Point, PointRef>& tetB,
36  tetIntersectionList& insideTets,
37  label& nInside,
38  tetIntersectionList& outsideTets,
39  label& nOutside
40 ) const
41 {
42  // Work storage
43  tetIntersectionList cutInsideTets;
44  label nCutInside = 0;
45 
46  nInside = 0;
47  storeOp inside(insideTets, nInside);
48  storeOp cutInside(cutInsideTets, nCutInside);
49 
50  nOutside = 0;
51  storeOp outside(outsideTets, nOutside);
52 
53 
54  // Cut tetA with all inwards pointing faces of tetB. Any tets remaining
55  // in aboveTets are inside tetB.
56 
57  {
58  // face0
59  plane pl0(tetB.b_, tetB.d_, tetB.c_);
60 
61  // Cut and insert subtets into cutInsideTets (either by getting
62  // an index from freeSlots or by appending to insideTets) or
63  // insert into outsideTets
64  sliceWithPlane(pl0, cutInside, outside);
65  }
66 
67  if (nCutInside == 0)
68  {
69  nInside = nCutInside;
70  return;
71  }
72 
73  {
74  // face1
75  plane pl1(tetB.a_, tetB.c_, tetB.d_);
76 
77  nInside = 0;
78 
79  for (label i = 0; i < nCutInside; i++)
80  {
81  cutInsideTets[i].tet().sliceWithPlane(pl1, inside, outside);
82  }
83 
84  if (nInside == 0)
85  {
86  return;
87  }
88  }
89 
90  {
91  // face2
92  plane pl2(tetB.a_, tetB.d_, tetB.b_);
93 
94  nCutInside = 0;
95 
96  for (label i = 0; i < nInside; i++)
97  {
98  insideTets[i].tet().sliceWithPlane(pl2, cutInside, outside);
99  }
100 
101  if (nCutInside == 0)
102  {
103  nInside = nCutInside;
104  return;
105  }
106  }
107 
108  {
109  // face3
110  plane pl3(tetB.a_, tetB.b_, tetB.c_);
111 
112  nInside = 0;
113 
114  for (label i = 0; i < nCutInside; i++)
115  {
116  cutInsideTets[i].tet().sliceWithPlane(pl3, inside, outside);
117  }
118  }
119 }
120 
121 
122 template<class Point, class PointRef>
124 (
125  const scalar tol
126 ) const
127 {
128  // (Probably very inefficient) minimum containment sphere calculation.
129  // From http://www.imr.sandia.gov/papers/imr11/shewchuk2.pdf:
130  // Sphere ctr is smallest one of
131  // - tet circumcentre
132  // - triangle circumcentre
133  // - edge mids
134 
135  const scalar fac = 1 + tol;
136 
137  // Halve order of tolerance for comparisons of sqr.
138  const scalar facSqr = Foam::sqrt(fac);
139 
140 
141  // 1. Circumcentre itself.
142 
143  pointHit pHit(circumCentre());
144  pHit.setHit();
145  scalar minRadiusSqr = magSqr(pHit.rawPoint() - a_);
146 
147 
148  // 2. Try circumcentre of tet triangles. Create circumcircle for triFace and
149  // check if 4th point is inside.
150 
151  {
152  point ctr = triPointRef(a_, b_, c_).circumCentre();
153  scalar radiusSqr = magSqr(ctr - a_);
154 
155  if
156  (
157  radiusSqr < minRadiusSqr
158  && Foam::magSqr(d_-ctr) <= facSqr*radiusSqr
159  )
160  {
161  pHit.setMiss(false);
162  pHit.setPoint(ctr);
163  minRadiusSqr = radiusSqr;
164  }
165  }
166  {
167  point ctr = triPointRef(a_, b_, d_).circumCentre();
168  scalar radiusSqr = magSqr(ctr - a_);
169 
170  if
171  (
172  radiusSqr < minRadiusSqr
173  && Foam::magSqr(c_-ctr) <= facSqr*radiusSqr
174  )
175  {
176  pHit.setMiss(false);
177  pHit.setPoint(ctr);
178  minRadiusSqr = radiusSqr;
179  }
180  }
181  {
182  point ctr = triPointRef(a_, c_, d_).circumCentre();
183  scalar radiusSqr = magSqr(ctr - a_);
184 
185  if
186  (
187  radiusSqr < minRadiusSqr
188  && Foam::magSqr(b_-ctr) <= facSqr*radiusSqr
189  )
190  {
191  pHit.setMiss(false);
192  pHit.setPoint(ctr);
193  minRadiusSqr = radiusSqr;
194  }
195  }
196  {
197  point ctr = triPointRef(b_, c_, d_).circumCentre();
198  scalar radiusSqr = magSqr(ctr - b_);
199 
200  if
201  (
202  radiusSqr < minRadiusSqr
203  && Foam::magSqr(a_-ctr) <= facSqr*radiusSqr
204  )
205  {
206  pHit.setMiss(false);
207  pHit.setPoint(ctr);
208  minRadiusSqr = radiusSqr;
209  }
210  }
211 
212 
213  // 3. Try midpoints of edges
214 
215  // mid of edge A-B
216  {
217  point ctr = 0.5*(a_ + b_);
218  scalar radiusSqr = magSqr(a_ - ctr);
219  scalar testRadSrq = facSqr*radiusSqr;
220 
221  if
222  (
223  radiusSqr < minRadiusSqr
224  && magSqr(c_-ctr) <= testRadSrq
225  && magSqr(d_-ctr) <= testRadSrq)
226  {
227  pHit.setMiss(false);
228  pHit.setPoint(ctr);
229  minRadiusSqr = radiusSqr;
230  }
231  }
232 
233  // mid of edge A-C
234  {
235  point ctr = 0.5*(a_ + c_);
236  scalar radiusSqr = magSqr(a_ - ctr);
237  scalar testRadSrq = facSqr*radiusSqr;
238 
239  if
240  (
241  radiusSqr < minRadiusSqr
242  && magSqr(b_-ctr) <= testRadSrq
243  && magSqr(d_-ctr) <= testRadSrq
244  )
245  {
246  pHit.setMiss(false);
247  pHit.setPoint(ctr);
248  minRadiusSqr = radiusSqr;
249  }
250  }
251 
252  // mid of edge A-D
253  {
254  point ctr = 0.5*(a_ + d_);
255  scalar radiusSqr = magSqr(a_ - ctr);
256  scalar testRadSrq = facSqr*radiusSqr;
257 
258  if
259  (
260  radiusSqr < minRadiusSqr
261  && magSqr(b_-ctr) <= testRadSrq
262  && magSqr(c_-ctr) <= testRadSrq
263  )
264  {
265  pHit.setMiss(false);
266  pHit.setPoint(ctr);
267  minRadiusSqr = radiusSqr;
268  }
269  }
270 
271  // mid of edge B-C
272  {
273  point ctr = 0.5*(b_ + c_);
274  scalar radiusSqr = magSqr(b_ - ctr);
275  scalar testRadSrq = facSqr*radiusSqr;
276 
277  if
278  (
279  radiusSqr < minRadiusSqr
280  && magSqr(a_-ctr) <= testRadSrq
281  && magSqr(d_-ctr) <= testRadSrq
282  )
283  {
284  pHit.setMiss(false);
285  pHit.setPoint(ctr);
286  minRadiusSqr = radiusSqr;
287  }
288  }
289 
290  // mid of edge B-D
291  {
292  point ctr = 0.5*(b_ + d_);
293  scalar radiusSqr = magSqr(b_ - ctr);
294  scalar testRadSrq = facSqr*radiusSqr;
295 
296  if
297  (
298  radiusSqr < minRadiusSqr
299  && magSqr(a_-ctr) <= testRadSrq
300  && magSqr(c_-ctr) <= testRadSrq)
301  {
302  pHit.setMiss(false);
303  pHit.setPoint(ctr);
304  minRadiusSqr = radiusSqr;
305  }
306  }
307 
308  // mid of edge C-D
309  {
310  point ctr = 0.5*(c_ + d_);
311  scalar radiusSqr = magSqr(c_ - ctr);
312  scalar testRadSrq = facSqr*radiusSqr;
313 
314  if
315  (
316  radiusSqr < minRadiusSqr
317  && magSqr(a_-ctr) <= testRadSrq
318  && magSqr(b_-ctr) <= testRadSrq
319  )
320  {
321  pHit.setMiss(false);
322  pHit.setPoint(ctr);
323  minRadiusSqr = radiusSqr;
324  }
325  }
326 
327 
328  pHit.setDistance(sqrt(minRadiusSqr));
329 
330  return pHit;
331 }
332 
333 
334 template<class Point, class PointRef>
336 (
337  scalarField& buffer
338 ) const
339 {
340  // Change of sign between face area vector and gradient
341  // does not matter because of square
342 
343  // Warning: Added a mag to produce positive coefficients even if
344  // the tetrahedron is twisted inside out. This is pretty
345  // dangerous, but essential for mesh motion.
346  scalar magVol = Foam::mag(mag());
347 
348  buffer[0] = (1.0/9.0)*magSqr(Sa())/magVol;
349  buffer[1] = (1.0/9.0)*magSqr(Sb())/magVol;
350  buffer[2] = (1.0/9.0)*magSqr(Sc())/magVol;
351  buffer[3] = (1.0/9.0)*magSqr(Sd())/magVol;
352 }
353 
354 
355 template<class Point, class PointRef>
357 (
358  scalarField& buffer
359 ) const
360 {
361  // Warning. Ordering of edges needs to be the same for a tetrahedron
362  // class, a tetrahedron cell shape model and a tetCell
363 
364  // Warning: Added a mag to produce positive coefficients even if
365  // the tetrahedron is twisted inside out. This is pretty
366  // dangerous, but essential for mesh motion.
367 
368  // Double change of sign between face area vector and gradient
369 
370  scalar magVol = Foam::mag(mag());
371  vector sa = Sa();
372  vector sb = Sb();
373  vector sc = Sc();
374  vector sd = Sd();
375 
376  buffer[0] = (1.0/9.0)*(sa & sb)/magVol;
377  buffer[1] = (1.0/9.0)*(sa & sc)/magVol;
378  buffer[2] = (1.0/9.0)*(sa & sd)/magVol;
379  buffer[3] = (1.0/9.0)*(sd & sb)/magVol;
380  buffer[4] = (1.0/9.0)*(sb & sc)/magVol;
381  buffer[5] = (1.0/9.0)*(sd & sc)/magVol;
382 }
383 
384 
385 template<class Point, class PointRef>
387 (
388  tensorField& buffer
389 ) const
390 {
391  // Change of sign between face area vector and gradient
392  // does not matter because of square
393 
394  scalar magVol = Foam::mag(mag());
395 
396  buffer[0] = (1.0/9.0)*sqr(Sa())/magVol;
397  buffer[1] = (1.0/9.0)*sqr(Sb())/magVol;
398  buffer[2] = (1.0/9.0)*sqr(Sc())/magVol;
399  buffer[3] = (1.0/9.0)*sqr(Sd())/magVol;
400 }
401 
402 
403 template<class Point, class PointRef>
405 (
406  tensorField& buffer
407 ) const
408 {
409  // Warning. Ordering of edges needs to be the same for a tetrahedron
410  // class, a tetrahedron cell shape model and a tetCell
411 
412  // Double change of sign between face area vector and gradient
413 
414  scalar magVol = Foam::mag(mag());
415  vector sa = Sa();
416  vector sb = Sb();
417  vector sc = Sc();
418  vector sd = Sd();
419 
420  buffer[0] = (1.0/9.0)*(sa * sb)/magVol;
421  buffer[1] = (1.0/9.0)*(sa * sc)/magVol;
422  buffer[2] = (1.0/9.0)*(sa * sd)/magVol;
423  buffer[3] = (1.0/9.0)*(sd * sb)/magVol;
424  buffer[4] = (1.0/9.0)*(sb * sc)/magVol;
425  buffer[5] = (1.0/9.0)*(sd * sc)/magVol;
426 }
427 
428 
429 // ************************************************************************* //
A tetrahedron primitive.
Definition: tetrahedron.H:62
Store resulting tets.
Definition: tetrahedron.H:118
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
void gradNiGradNj(tensorField &buffer) const
Definition: tetrahedron.C:405
A 1D vector of objects of type <T> with a fixed size <Size>.
Definition: FixedList.H:53
dimensionedSymmTensor sqr(const dimensionedVector &dv)
const Point & rawPoint() const
Return point with no checking.
Definition: PointHit.H:158
dimensionedScalar sqrt(const dimensionedScalar &ds)
Geometric class that creates a 2D plane and can return the intersection point between a line and the ...
Definition: plane.H:60
void gradNiSquared(scalarField &buffer) const
Fill buffer with shape function products.
Definition: tetrahedron.C:336
void setHit()
Definition: PointHit.H:169
void setDistance(const scalar d)
Definition: PointHit.H:186
void setMiss(const bool eligible)
Definition: PointHit.H:175
dimensioned< scalar > magSqr(const dimensioned< Type > &)
void gradNiGradNi(tensorField &buffer) const
Definition: tetrahedron.C:387
pointHit containmentSphere(const scalar tol) const
Return (min)containment sphere, i.e. the smallest sphere with.
Definition: tetrahedron.C:124
void tetOverlap(const tetrahedron< Point, PointRef > &tetB, tetIntersectionList &insideTets, label &nInside, tetIntersectionList &outsideTets, label &nOutside) const
Decompose tet into tets inside and outside other tet.
Definition: tetrahedron.C:34
triangle< point, const point & > triPointRef
Definition: triPointRef.H:44
dimensioned< scalar > mag(const dimensioned< Type > &)
void gradNiDotGradNj(scalarField &buffer) const
Definition: tetrahedron.C:357
void setPoint(const Point &p)
Definition: PointHit.H:181