1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | foam-extend: Open Source CFD
4 \\ / O peration | Version: 3.2
5 \\ / A nd | Web: http://www.foam-extend.org
6 \\/ M anipulation | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
9 This file is part of foam-extend.
11 foam-extend is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation, either version 3 of the License, or (at your
14 option) any later version.
16 foam-extend is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with foam-extend. If not, see <http://www.gnu.org/licenses/>.
28 Class for convexSetAlgorithms pertaining to cells
32 University of Massachusetts Amherst
35 \*---------------------------------------------------------------------------*/
37 #include "cellSetAlgorithm.H"
42 #include "tetIntersection.H"
44 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
49 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
51 // Construct from components
52 cellSetAlgorithm::cellSetAlgorithm
55 const pointField& newPoints,
56 const UList<edge>& newEdges,
57 const UList<face>& newFaces,
58 const UList<cell>& newCells,
59 const UList<label>& newOwner,
60 const UList<label>& newNeighbour
76 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
78 void cellSetAlgorithm::computeNormFactor(const label index) const
80 // Clear existing fields
86 // Compute volume / centre (using refNorm_ as centre)
87 meshOps::cellCentreAndVolume
98 // Compute a bounding box around the cell
99 box_ = boundBox(newCells_[index].points(newFaces_, newPoints_), false);
101 vector minToXb = (box_.min() - box_.midpoint());
102 vector maxToXb = (box_.max() - box_.midpoint());
105 box_.min() += (1.5 * minToXb);
106 box_.max() += (1.5 * maxToXb);
110 // Check whether the bounding box contains the entity
111 bool cellSetAlgorithm::contains(const label index) const
114 const labelListList& cellPoints = mesh_.cellPoints();
115 const labelList& checkCell = cellPoints[index];
117 // Check if the bounding box contains any of the supplied points
118 forAll(checkCell, pointI)
120 if (box_.contains(mesh_.points()[checkCell[pointI]]))
130 // Compute intersection
131 bool cellSetAlgorithm::computeIntersection
133 const label newIndex,
134 const label oldIndex,
139 bool intersects = false;
141 const pointField& newPoints = newPoints_;
142 const pointField& oldPoints = mesh_.points();
144 const cell& newCell = newCells_[newIndex];
145 const cell& oldCell = mesh_.cells()[oldIndex];
147 // Check if decomposition is necessary
148 if (oldCell.size() > 4 || newCell.size() > 4)
150 // Decompose new / old cells
151 DynamicList<FixedList<point, 4> > clippingTets(15);
152 DynamicList<FixedList<point, 4> > subjectTets(15);
154 label ntOld = 0, ntNew = 0;
155 vector oldCentre = vector::zero, newCentre = vector::zero;
157 // Configure tets from oldCell
158 forAll(oldCell, faceI)
160 const face& oldFace = mesh_.faces()[oldCell[faceI]];
162 vector fCentre = oldFace.centre(oldPoints);
164 if (oldFace.size() == 3)
167 subjectTets.append(FixedList<point, 4>(vector::zero));
169 subjectTets[ntOld][0] = oldPoints[oldFace[0]];
170 subjectTets[ntOld][1] = oldPoints[oldFace[1]];
171 subjectTets[ntOld][2] = oldPoints[oldFace[2]];
180 subjectTets.append(FixedList<point, 4>(vector::zero));
182 subjectTets[ntOld][0] = oldPoints[oldFace[pI]];
183 subjectTets[ntOld][1] = oldPoints[oldFace.nextLabel(pI)];
184 subjectTets[ntOld][2] = fCentre;
190 oldCentre += fCentre;
193 // Configure tets from newCell
194 forAll(newCell, faceI)
196 const face& newFace = newFaces_[newCell[faceI]];
198 vector fCentre = newFace.centre(newPoints);
200 if (newFace.size() == 3)
203 clippingTets.append(FixedList<point, 4>(vector::zero));
205 clippingTets[ntNew][0] = newPoints[newFace[0]];
206 clippingTets[ntNew][1] = newPoints[newFace[1]];
207 clippingTets[ntNew][2] = newPoints[newFace[2]];
216 clippingTets.append(FixedList<point, 4>(vector::zero));
218 clippingTets[ntNew][0] = newPoints[newFace[pI]];
219 clippingTets[ntNew][1] = newPoints[newFace.nextLabel(pI)];
220 clippingTets[ntNew][2] = fCentre;
226 newCentre += fCentre;
229 oldCentre /= oldCell.size();
230 newCentre /= newCell.size();
232 // Fill-in last points for all tets
233 forAll(subjectTets, i)
235 subjectTets[i][3] = oldCentre;
238 forAll(clippingTets, i)
240 clippingTets[i][3] = newCentre;
243 // Accumulate volume / centroid over all intersections
244 bool foundIntersect = false;
246 scalar totalVolume = 0.0;
247 vector totalCentre = vector::zero;
249 // Loop through all clipping tets
250 forAll(clippingTets, i)
252 // Initialize the intersector
253 tetIntersection intersector(clippingTets[i]);
255 // Test for intersection and evaluate
256 // against all subject tets
257 forAll(subjectTets, j)
259 intersects = intersector.evaluate(subjectTets[j]);
264 vector centre = vector::zero;
266 // Fetch volume and centre
267 intersector.getVolumeAndCentre(volume, centre);
269 // Accumulate volume / centroid
270 totalVolume += volume;
271 totalCentre += (volume * centre);
273 foundIntersect = true;
279 "polyhedronIntersect_"
280 + Foam::name(newIndex)
282 + Foam::name(oldIndex)
283 + '_' + Foam::name(i)
284 + '_' + Foam::name(j),
285 intersector.getIntersection()
292 // Size-up the internal lists
293 if (foundIntersect && !output)
296 totalCentre /= totalVolume + VSMALL;
298 // Normalize and check if this is worth it
299 if (mag(totalVolume/normFactor_) > SMALL)
301 // Size-up the internal lists
302 meshOps::sizeUpList((oldIndex - offset), parents_);
303 meshOps::sizeUpList(totalVolume, weights_);
304 meshOps::sizeUpList(totalCentre, centres_);
316 // Configure points for clipping tetrahedron
317 FixedList<point, 4> clippingTet(vector::zero);
319 // Configure the clipping tetrahedron.
320 const face& firstNewFace = newFaces_[newCell[0]];
321 const face& secondNewFace = newFaces_[newCell[1]];
323 // Find the isolated point
324 label fourthNewPoint =
326 meshOps::findIsolatedPoint
334 clippingTet[0] = newPoints[firstNewFace[0]];
335 clippingTet[1] = newPoints[firstNewFace[1]];
336 clippingTet[2] = newPoints[firstNewFace[2]];
337 clippingTet[3] = newPoints[fourthNewPoint];
339 // Configure points for subject tetrahedron
340 FixedList<point, 4> subjectTet(vector::zero);
342 // Configure the subject tetrahedron.
343 const face& firstOldFace = mesh_.faces()[oldCell[0]];
344 const face& secondOldFace = mesh_.faces()[oldCell[1]];
346 // Find the isolated point
347 label fourthOldPoint =
349 meshOps::findIsolatedPoint
357 subjectTet[0] = oldPoints[firstOldFace[0]];
358 subjectTet[1] = oldPoints[firstOldFace[1]];
359 subjectTet[2] = oldPoints[firstOldFace[2]];
360 subjectTet[3] = oldPoints[fourthOldPoint];
362 // Initialize the intersector
363 tetIntersection intersector(clippingTet);
365 // Test for intersection and evaluate
366 intersects = intersector.evaluate(subjectTet);
371 vector centre = vector::zero;
373 // Fetch volume and centre
374 intersector.getVolumeAndCentre(volume, centre);
376 // Normalize and check if this is worth it
377 if (mag(volume/normFactor_) > SMALL)
384 + Foam::name(newIndex),
385 List<FixedList<point, 4> >(1, clippingTet)
391 + Foam::name(newIndex)
393 + Foam::name(oldIndex),
394 List<FixedList<point, 4> >(1, subjectTet)
400 + Foam::name(newIndex)
402 + Foam::name(oldIndex),
403 intersector.getIntersection()
407 // Size-up the internal lists
408 meshOps::sizeUpList((oldIndex - offset), parents_);
409 meshOps::sizeUpList(volume, weights_);
410 meshOps::sizeUpList(centre, centres_);
423 //- Write out tets as a VTK
424 void cellSetAlgorithm::writeVTK
427 const List<FixedList<point, 4> >& tetList
430 // Fill up all points
433 List<cell> allTets(tetList.size(), cell(4));
434 pointField allPoints(4 * tetList.size());
436 forAll(tetList, tetI)
438 allTets[tetI][0] = pI;
439 allPoints[pI++] = tetList[tetI][0];
441 allTets[tetI][1] = pI;
442 allPoints[pI++] = tetList[tetI][1];
444 allTets[tetI][2] = pI;
445 allPoints[pI++] = tetList[tetI][2];
447 allTets[tetI][3] = pI;
448 allPoints[pI++] = tetList[tetI][3];
451 // Write out in cell-to-node addressing
456 identity(tetList.size()),
467 } // End namespace Foam
469 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //