1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright held by original author
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
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 the
13 Free Software Foundation; either version 2 of the License, or (at your
14 option) any later version.
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
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM; if not, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
29 Various utility functions that perform mesh-related operations.
33 University of Massachusetts Amherst
36 \*---------------------------------------------------------------------------*/
42 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
50 // Utility method to find the common edge between two faces.
51 inline bool findCommonEdge
55 const UList<labelList>& faceEdges,
61 const labelList& fEi = faceEdges[first];
62 const labelList& fEj = faceEdges[second];
68 if (fEi[edgeI] == fEj[edgeJ])
87 // Utility method to find the interior (quad) / boundary (tri) faces
88 // for an input quad-face and adjacent triangle-prism cell.
89 inline void findPrismFaces
93 const UList<face>& faces,
94 const UList<cell>& cells,
95 const UList<label>& neighbour,
96 FixedList<face,2>& bdyf,
97 FixedList<label,2>& bidx,
98 FixedList<face,2>& intf,
99 FixedList<label,2>& iidx
102 label indexO = 0, indexI = 0;
104 const cell& c = cells[cIndex];
108 label faceIndex = c[i];
110 // Don't count the face under consideration
111 if (faceIndex != fIndex)
113 const face& fi = faces[faceIndex];
115 if (neighbour[faceIndex] == -1)
119 // Triangular face on the boundary
120 bidx[indexO] = faceIndex;
125 // This seems to be a non-triangular face on the boundary
126 // Consider this as "interior" and move on
127 iidx[indexI] = faceIndex;
133 // Face on the interior
134 iidx[indexI] = faceIndex;
142 // Utility method to find the isolated point given two triangular faces.
143 // - Returns the point on checkFace that does not belong to baseFace.
144 inline label findIsolatedPoint
146 const face& baseFace,
147 const face& checkFace
150 // Get the fourth point
151 forAll(checkFace, pointI)
155 checkFace[pointI] != baseFace[0] &&
156 checkFace[pointI] != baseFace[1] &&
157 checkFace[pointI] != baseFace[2]
160 return checkFace[pointI];
168 // Utility method to find the isolated point on a triangular face
169 // that doesn't lie on the specified edge. Also returns the point next to it.
170 inline void findIsolatedPoint
178 // Check the first point
179 if ( f[0] != e.start() && f[0] != e.end() )
186 // Check the second point
187 if ( f[1] != e.start() && f[1] != e.end() )
194 // Check the third point
195 if ( f[2] != e.start() && f[2] != e.end() )
202 // This bit should never happen.
205 "inline void meshOps::findIsolatedPoint"
206 "(const face&, const edge&, label&, label&)"
208 << "Cannot find isolated point in face " << f << endl
209 << " Using edge: " << e
210 << abort(FatalError);
214 // Given a face and cell index, find the apex point for a tet cell.
215 inline label tetApexPoint
219 const UList<face>& faces,
220 const UList<cell>& cells
223 label apexPoint = -1;
224 bool foundApex = false;
226 const cell& cellToCheck = cells[cIndex];
227 const face& baseFace = faces[fIndex];
229 forAll(cellToCheck, faceI)
231 const face& faceToCheck = faces[cellToCheck[faceI]];
233 apexPoint = findIsolatedPoint(baseFace, faceToCheck);
244 Pout<< "fIndex: " << fIndex << ":: " << faces[fIndex] << endl;
245 Pout<< "cIndex: " << cIndex << ":: " << cellToCheck << endl;
247 forAll(cellToCheck, faceI)
249 Pout<< '\t' << cellToCheck[faceI] << ":: "
250 << faces[cellToCheck[faceI]] << endl;
256 "inline label meshOps::tetApexPoint\n"
258 " const label cIndex,\n"
259 " const label fIndex,\n"
260 " const UList<face>& faces,\n"
261 " const UList<cell>& cells\n"
264 << "Could not find an apex point in cell: " << cIndex
265 << " given face: " << fIndex
266 << abort(FatalError);
273 // Given a cell index, find the centroid / volume of a cell.
274 // - If checking is enabled, return whether the cell is closed
275 inline void cellCentreAndVolume
278 const vectorField& points,
279 const UList<face>& faces,
280 const UList<cell>& cells,
281 const UList<label>& owner,
288 centre = vector::zero;
290 const cell& cellToCheck = cells[cIndex];
292 // Average face-centres to get an estimate centroid
293 vector cEst(vector::zero), fCentre(vector::zero);
295 forAll(cellToCheck, faceI)
297 const face& checkFace = faces[cellToCheck[faceI]];
299 cEst += checkFace.centre(points);
302 cEst /= cellToCheck.size();
304 forAll(cellToCheck, faceI)
306 const face& checkFace = faces[cellToCheck[faceI]];
308 if (checkFace.size() == 3)
312 points[checkFace[2]],
313 points[checkFace[1]],
314 points[checkFace[0]],
318 scalar tetVol = tpr.mag();
321 if (owner[cellToCheck[faceI]] != cIndex)
326 // Accumulate volume-weighted tet centre
327 centre += tetVol*tpr.centre();
329 // Accumulate tet volume
334 forAll(checkFace, pI)
338 points[checkFace[pI]],
339 points[checkFace.prevLabel(pI)],
340 checkFace.centre(points),
344 scalar tetVol = tpr.mag();
347 if (owner[cellToCheck[faceI]] != cIndex)
352 // Accumulate volume-weighted tet centre
353 centre += tetVol*tpr.centre();
355 // Accumulate tet volume
361 centre /= volume + VSMALL;
365 // Determine whether a segment intersects a triangular face
366 inline bool segmentTriFaceIntersection
368 const triPointRef& faceToCheck,
369 const linePointRef& edgeToCheck,
374 const vector& p1 = edgeToCheck.start();
375 const vector& p2 = edgeToCheck.end();
377 // Define face-normal
378 vector n = faceToCheck.normal();
379 n /= mag(n) + VSMALL;
382 scalar numerator = n & (faceToCheck.a() - p1);
383 scalar denominator = n & (p2 - p1);
385 // Check if the edge is parallel to the face
386 if (mag(denominator) < VSMALL)
391 scalar u = (numerator / denominator);
393 // Check for intersection along line.
394 if ((u >= 0.0) && (u <= 1.0))
396 // Compute point of intersection
397 intPoint = p1 + u*(p2 - p1);
399 // Also make sure that intPoint lies within the face
400 if (pointInTriFace(faceToCheck, intPoint, false))
406 // Failed to fall within edge-bounds, or within face
411 // Determine whether the particular point lies
412 // inside the given triangular face
413 inline bool pointInTriFace
415 const triPointRef& faceToCheck,
421 const vector& a = faceToCheck.a();
422 const vector& b = faceToCheck.b();
423 const vector& c = faceToCheck.c();
425 // Compute the normal
426 vector nf = faceToCheck.normal();
428 if ( ((0.5 * ((b - a)^(cP - a))) & nf) < 0.0)
433 if ( ((0.5 * ((c - b)^(cP - b))) & nf) < 0.0)
438 if ( ((0.5 * ((a - c)^(cP - c))) & nf) < 0.0)
448 nf /= mag(nf) + VSMALL;
449 ftp /= mag(ftp) + VSMALL;
451 if (mag(ftp & nf) > VSMALL)
457 // Passed test with all edges
462 // Parallel blocking send
473 reinterpret_cast<const char*>(&data),
479 // Parallel blocking receive
490 reinterpret_cast<char*>(&data),
496 inline void waitForBuffers()
498 if (Pstream::parRun())
500 OPstream::waitRequests();
501 IPstream::waitRequests();
506 // Method to insert a label between two labels in a list
507 // Assumes that all labels are unique.
508 inline void insertLabel
510 const label newLabel,
518 label origSize = list.size();
519 labelList newList(origSize + 1);
521 label index = 0, nextI = -1;
523 // Start a linear search
526 newList[index++] = list[itemI];
528 nextI = list.fcIndex(itemI);
533 (list[itemI] == labelA && list[nextI] == labelB) ||
534 (list[itemI] == labelB && list[nextI] == labelA)
540 newList[index++] = newLabel;
548 "inline void meshOps::insertLabel"
549 "(const label, const label, const label, labelList&)"
550 ) << nl << "Cannot insert " << newLabel
551 << " in list: " << list << nl
553 << labelA << " and " << labelB
554 << " were not found in sequence."
555 << abort(FatalError);
559 list.transfer(newList);
563 // Utility method to replace a label in a given list
564 inline void replaceLabel
566 const label original,
567 const label replacement,
573 if ((index = findIndex(list, original)) > -1)
575 list[index] = replacement;
581 "inline void label meshOps::replaceLabel"
582 "(const label, const label, labelList&)"
583 ) << nl << "Cannot find " << original
584 << " in list: " << list << nl
585 << " Label: " << replacement
586 << " was not used in replacement."
587 << abort(FatalError);
592 } // End namespace meshOps
595 } // End namespace Foam
597 // ************************************************************************* //