cutTemplates.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 | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2017 OpenFOAM Foundation
9  Copyright (C) 2021 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "cut.H"
30 
31 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
32 
33 template<class AboveOp, class BelowOp>
35 (
36  const FixedList<point, 3>& tri,
37  const FixedList<scalar, 3>& level,
38  const AboveOp& aboveOp,
39  const BelowOp& belowOp
40 )
41 {
42  // If everything is positive or negative, then process the triangle as a
43  // whole, and do a quick return
44  if (level[0] >= 0 && level[1] >= 0 && level[2] >= 0)
45  {
46  return aboveOp(tri) + belowOp();
47  }
48  if (level[0] <= 0 && level[1] <= 0 && level[2] <= 0)
49  {
50  return aboveOp() + belowOp(tri);
51  }
52 
53  // There will be just one edge without a sign change. Find it, and put it
54  // opposite the first vertex. This may change the sign of the tri.
55  FixedList<label, 3> indices({0, 1, 2});
56  label i;
57  for (i = 0; i < 3; ++i)
58  {
59  if (level[(i + 1)%3]*level[(i + 2)%3] >= 0)
60  {
61  std::swap(indices[0], indices[i]);
62  break;
63  }
64  }
65  if (i == 3)
66  {
68  << "The number of tri vertices above the level set should always "
69  << "be 1" << exit(FatalError);
70  }
71 
72  // Correct the sign
73  if (indices[0] != 0)
74  {
75  std::swap(indices[1], indices[2]);
76  }
77 
78  // Permute the data
79  const FixedList<point, 3> p = triReorder(tri, indices);
80  const FixedList<scalar, 3> l = triReorder(level, indices);
81  AboveOp a = triReorder(aboveOp, indices);
82  BelowOp b = triReorder(belowOp, indices);
83 
84  // Slice off one corner to form a tri and a quad
85  Pair<scalar> f;
86  for (label i = 0; i < 2; ++i)
87  {
88  f[i] = l[0]/(l[0] - l[i+1]);
89  }
90  if (l[0] > 0)
91  {
92  return triCutTri(a, p, f) + triCutQuad(b, p, f);
93  }
94  else
95  {
96  return triCutQuad(a, p, f) + triCutTri(b, p, f);
97  }
98 }
99 
100 
101 template<class AboveOp, class BelowOp>
103 (
104  const FixedList<point, 3>& tri,
105  const plane& pln,
106  const AboveOp& aboveOp,
107  const BelowOp& belowOp
108 )
109 {
110  // Set the level set to the signed distance from the plane
111  FixedList<scalar, 3> level;
112  for (label i = 0; i < 3; ++i)
113  {
114  level[i] = pln.signedDistance(tri[i]);
115  }
116 
117  // Run the level set function
118  return triCut(tri, level, aboveOp, belowOp);
119 }
120 
121 
122 template<class AboveOp, class BelowOp>
124 (
125  const FixedList<point, 4>& tet,
126  const FixedList<scalar, 4>& level,
127  const AboveOp& aboveOp,
128  const BelowOp& belowOp
129 )
130 {
131  // Get the min and max over all four vertices and quick return if there is
132  // no change of sign
133  scalar levelMin = VGREAT, levelMax = - VGREAT;
134  for (label i = 0; i < 4; ++i)
135  {
136  levelMin = min(levelMin, level[i]);
137  levelMax = max(levelMax, level[i]);
138  }
139  if (levelMin >= 0)
140  {
141  return aboveOp(tet) + belowOp();
142  }
143  if (levelMax <= 0)
144  {
145  return aboveOp() + belowOp(tet);
146  }
147 
148  // Partition the level so that positive values are at the start. This is
149  // like a single iteration of quick-sort, except that the pivot is a hard-
150  // coded zero, rather than an element of the array. This can change the sign
151  // of the tet.
152  FixedList<label, 4> indices({0, 1, 2, 3});
153  bool signChange = false;
154  label i = 0, j = 3;
155  while (true)
156  {
157  while (i < j && level[indices[i]] > 0)
158  {
159  i ++;
160  }
161  while (j > i && level[indices[j]] <= 0)
162  {
163  j --;
164  }
165  if (i == j)
166  {
167  break;
168  }
169  std::swap(indices[i], indices[j]);
170  signChange = !signChange;
171  }
172 
173  // The number of vertices above the slice
174  label n = i;
175 
176  // If there are more positives than negatives then reverse the order so that
177  // the negatives are at the start
178  if (n > 2)
179  {
180  n = 4 - n;
181  for (label i = 0; i < 2; ++i)
182  {
183  std::swap(indices[i], indices[3-i]);
184  }
185  }
186 
187  // Correct the sign
188  if (signChange)
189  {
190  std::swap(indices[2], indices[3]);
191  }
192 
193  // Permute the data
194  const FixedList<point, 4> p = tetReorder(tet, indices);
195  const FixedList<scalar, 4> l = tetReorder(level, indices);
196  AboveOp a = tetReorder(aboveOp, indices);
197  BelowOp b = tetReorder(belowOp, indices);
198 
199  // Calculate the integrals above and below the level set
200  if (n == 1)
201  {
202  // Slice off one corner to form a tet and a prism
203  FixedList<scalar, 3> f;
204  for (label i = 0; i < 3; ++i)
205  {
206  f[i] = l[0]/(l[0] - l[i+1]);
207  }
208  if (l[0] > 0)
209  {
210  return tetCutTet(a, p, f) + tetCutPrism0(b, p, f);
211  }
212  else
213  {
214  return tetCutPrism0(a, p, f) + tetCutTet(b, p, f);
215  }
216  }
217  else if (n == 2)
218  {
219  // Slice off two corners to form two prisms
220  FixedList<scalar, 4> f;
221  for (label i = 0; i < 2; ++i)
222  {
223  for (label j = 0; j < 2; ++j)
224  {
225  f[2*i+j] = l[i]/(l[i] - l[j+2]);
226  }
227  }
228  if (l[0] > 0)
229  {
230  return tetCutPrism01(a, p, f) + tetCutPrism23(b, p, f);
231  }
232  else
233  {
234  return tetCutPrism23(a, p, f) + tetCutPrism01(b, p, f);
235  }
236  }
237 
239  << "The number of tet vertices above the level set should always be "
240  << "either 1 or 2" << exit(FatalError);
241 
242  return aboveOp() + belowOp();
243 }
244 
245 
246 template<class AboveOp, class BelowOp>
248 (
249  const FixedList<point, 4>& tet,
250  const plane& pln,
251  const AboveOp& aboveOp,
252  const BelowOp& belowOp
253 )
254 {
255  // Set the level set to the signed distance from the plane
256  FixedList<scalar, 4> level;
257  for (label i = 0; i < 4; ++i)
258  {
259  level[i] = pln.signedDistance(tet[i]);
260  }
261 
262  // Run the level set function
263  return tetCut(tet, level, aboveOp, belowOp);
264 }
265 
266 // ************************************************************************* //
Foam::triCutTri
const cut::uniformOp< Type > & triCutTri(const cut::uniformOp< Type > &x, const Pair< scalar > &)
Modify a uniform operation for cutting a tri from a tri (does nothing)
Definition: cutI.H:52
p
volScalarField & p
Definition: createFieldRefs.H:8
Foam::tetCutTet
const cut::uniformOp< Type > & tetCutTet(const cut::uniformOp< Type > &x, const FixedList< scalar, 3 > &)
Modify a uniform operation for cutting a tet from a tet (does nothing)
Definition: cutI.H:88
Foam::tetCutPrism23
const cut::uniformOp< Type > & tetCutPrism23(const cut::uniformOp< Type > &x, const FixedList< scalar, 4 > &)
Modify a uniform operation for cutting prism23 from a tet (does nothing)
Definition: cutI.H:124
Foam::cut::opAddResult
Trait to determine the result of the addition of two operations.
Definition: cut.H:437
Foam::min
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:33
Foam::tetReorder
const cut::uniformOp< Type > & tetReorder(const cut::uniformOp< Type > &x, const FixedList< label, 4 > &)
Modify a uniform operation for reordering a tet (does nothing)
Definition: cutI.H:76
n
label n
Definition: TABSMDCalcMethod2.H:31
Foam::tetCutPrism01
const cut::uniformOp< Type > & tetCutPrism01(const cut::uniformOp< Type > &x, const FixedList< scalar, 4 > &)
Modify a uniform operation for cutting prism01 from a tet (does nothing)
Definition: cutI.H:112
Foam::constant::physicoChemical::b
const dimensionedScalar b
Wien displacement law constant: default SI units: [m.K].
Definition: createFields.H:27
cut.H
Functions for cutting triangles and tetrahedra. Generic operations are applied to each half of a cut.
Foam::tetCutPrism0
const cut::uniformOp< Type > & tetCutPrism0(const cut::uniformOp< Type > &x, const FixedList< scalar, 3 > &)
Modify a uniform operation for cutting prism0 from a tet (does nothing)
Definition: cutI.H:100
Foam::max
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
Foam::FatalError
error FatalError
Foam::triReorder
const cut::uniformOp< Type > & triReorder(const cut::uniformOp< Type > &x, const FixedList< label, 3 > &)
Modify a uniform operation for reordering a tri (does nothing)
Definition: cutI.H:40
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::triCutQuad
const cut::uniformOp< Type > & triCutQuad(const cut::uniformOp< Type > &x, const Pair< scalar > &)
Modify a uniform operation for cutting a quad from a tri (does nothing)
Definition: cutI.H:64
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
Foam::tetCut
cut::opAddResult< AboveOp, BelowOp >::type tetCut(const FixedList< point, 4 > &tet, const FixedList< scalar, 4 > &level, const AboveOp &aboveOp, const BelowOp &belowOp)
As triCut, but for a tetrahedron.
f
labelList f(nPoints)
Foam::triCut
cut::opAddResult< AboveOp, BelowOp >::type triCut(const FixedList< point, 3 > &tri, const FixedList< scalar, 3 > &level, const AboveOp &aboveOp, const BelowOp &belowOp)
Cut a triangle along the zero plane defined by the given levels.