Merge branch 'master' of ssh://git.code.sf.net/p/foam-extend/foam-extend-3.2
[foam-extend-3.2.git] / src / dynamicMesh / dynamicTopoFvMesh / meshOpsI.H
blob0af163f0efbf3a57ace6c904f2506e9e6e2d03d8
1 /*---------------------------------------------------------------------------*\
2   =========                 |
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 -------------------------------------------------------------------------------
8 License
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/>.
24 Class
25     meshOps
27 Description
28     Various utility functions that perform mesh-related operations.
30 Author
31     Sandeep Menon
32     University of Massachusetts Amherst
33     All rights reserved
35 \*---------------------------------------------------------------------------*/
37 #include "Pair.H"
38 #include "meshOps.H"
39 #include "ListOps.H"
41 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
43 namespace Foam
46 namespace meshOps
49 // Utility method to find the common edge between two faces.
50 inline bool findCommonEdge
52     const label first,
53     const label second,
54     const UList<labelList>& faceEdges,
55     label& common
58     bool found = false;
60     const labelList& fEi = faceEdges[first];
61     const labelList& fEj = faceEdges[second];
63     forAll(fEi, edgeI)
64     {
65         forAll(fEj, edgeJ)
66         {
67             if (fEi[edgeI] == fEj[edgeJ])
68             {
69                 common = fEi[edgeI];
71                 found = true;
72                 break;
73             }
74         }
76         if (found)
77         {
78             break;
79         }
80     }
82     return found;
86 // Utility method to find the interior (quad) / boundary (tri) faces
87 // for an input quad-face and adjacent triangle-prism cell.
88 inline void findPrismFaces
90     const label fIndex,
91     const label cIndex,
92     const UList<face>& faces,
93     const UList<cell>& cells,
94     const UList<label>& neighbour,
95     FixedList<face,2>& bdyf,
96     FixedList<label,2>& bidx,
97     FixedList<face,2>& intf,
98     FixedList<label,2>& iidx
101     label indexO = 0, indexI = 0;
103     const cell& c = cells[cIndex];
105     forAll(c, i)
106     {
107         label faceIndex = c[i];
109         // Don't count the face under consideration
110         if (faceIndex != fIndex)
111         {
112             const face& fi = faces[faceIndex];
114             if (neighbour[faceIndex] == -1)
115             {
116                 if (fi.size() == 3)
117                 {
118                     // Triangular face on the boundary
119                     bidx[indexO] = faceIndex;
120                     bdyf[indexO++] = fi;
121                 }
122                 else
123                 {
124                     // This seems to be a non-triangular face on the boundary
125                     // Consider this as "interior" and move on
126                     iidx[indexI] = faceIndex;
127                     intf[indexI++] = fi;
128                 }
129             }
130             else
131             {
132                 // Face on the interior
133                 iidx[indexI] = faceIndex;
134                 intf[indexI++] = fi;
135             }
136         }
137     }
141 // Utility method to find the isolated point given two triangular faces.
142 //  - Returns the point on checkFace that does not belong to baseFace.
143 inline label findIsolatedPoint
145     const face& baseFace,
146     const face& checkFace
149     // Get the fourth point
150     forAll(checkFace, pointI)
151     {
152         if
153         (
154             checkFace[pointI] != baseFace[0] &&
155             checkFace[pointI] != baseFace[1] &&
156             checkFace[pointI] != baseFace[2]
157         )
158         {
159             return checkFace[pointI];
160         }
161     }
163     return -1;
167 // Utility method to find the isolated point on a triangular face
168 // that doesn't lie on the specified edge. Also returns the point next to it.
169 inline void findIsolatedPoint
171     const face& f,
172     const edge& e,
173     label& ptIndex,
174     label& nextPtIndex
177     // Check the first point
178     if ( f[0] != e.start() && f[0] != e.end() )
179     {
180         ptIndex = f[0];
181         nextPtIndex = f[1];
182         return;
183     }
185     // Check the second point
186     if ( f[1] != e.start() && f[1] != e.end() )
187     {
188         ptIndex = f[1];
189         nextPtIndex = f[2];
190         return;
191     }
193     // Check the third point
194     if ( f[2] != e.start() && f[2] != e.end() )
195     {
196         ptIndex = f[2];
197         nextPtIndex = f[0];
198         return;
199     }
201     // This bit should never happen.
202     FatalErrorIn
203     (
204         "inline void meshOps::findIsolatedPoint"
205         "(const face&, const edge&, label&, label&)"
206     )
207         << "Cannot find isolated point in face " << f << endl
208         << " Using edge: " << e
209         << abort(FatalError);
213 // Given a face and cell index, find the apex point for a tet cell.
214 inline label tetApexPoint
216     const label cIndex,
217     const label fIndex,
218     const UList<face>& faces,
219     const UList<cell>& cells
222     label apexPoint = -1;
223     bool foundApex = false;
225     const cell& cellToCheck = cells[cIndex];
226     const face& baseFace = faces[fIndex];
228     forAll(cellToCheck, faceI)
229     {
230         const face& faceToCheck = faces[cellToCheck[faceI]];
232         apexPoint = findIsolatedPoint(baseFace, faceToCheck);
234         if (apexPoint > -1)
235         {
236             foundApex = true;
237             break;
238         }
239     }
241     if (!foundApex)
242     {
243         Pout<< "fIndex: " << fIndex << ":: " << faces[fIndex] << endl;
244         Pout<< "cIndex: " << cIndex << ":: " << cellToCheck << endl;
246         forAll(cellToCheck, faceI)
247         {
248             Pout<< '\t' << cellToCheck[faceI] << ":: "
249                 << faces[cellToCheck[faceI]] << endl;
250         }
252         FatalErrorIn
253         (
254             "\n\n"
255             "inline label meshOps::tetApexPoint\n"
256             "(\n"
257             "    const label cIndex,\n"
258             "    const label fIndex,\n"
259             "    const UList<face>& faces,\n"
260             "    const UList<cell>& cells\n"
261             ")\n"
262         )
263             << "Could not find an apex point in cell: " << cIndex
264             << " given face: " << fIndex
265             << abort(FatalError);
266     }
268     return apexPoint;
272 // Given a cell index, find the centroid / volume of a cell.
273 //  - If checking is enabled, return whether the cell is closed
274 inline void cellCentreAndVolume
276     const label cIndex,
277     const vectorField& points,
278     const UList<face>& faces,
279     const UList<cell>& cells,
280     const UList<label>& owner,
281     vector& centre,
282     scalar& volume
285     // Reset inputs
286     volume = 0.0;
287     centre = vector::zero;
289     const cell& cellToCheck = cells[cIndex];
291     // Average face-centres to get an estimate centroid
292     vector cEst(vector::zero), fCentre(vector::zero);
294     forAll(cellToCheck, faceI)
295     {
296         const face& checkFace = faces[cellToCheck[faceI]];
298         cEst += checkFace.centre(points);
299     }
301     cEst /= cellToCheck.size();
303     forAll(cellToCheck, faceI)
304     {
305         const face& checkFace = faces[cellToCheck[faceI]];
307         if (checkFace.size() == 3)
308         {
309             tetPointRef tpr
310             (
311                 points[checkFace[2]],
312                 points[checkFace[1]],
313                 points[checkFace[0]],
314                 cEst
315             );
317             scalar tetVol = tpr.mag();
319             // Flip if necessary
320             if (owner[cellToCheck[faceI]] != cIndex)
321             {
322                 tetVol *= -1.0;
323             }
325             // Accumulate volume-weighted tet centre
326             centre += tetVol*tpr.centre();
328             // Accumulate tet volume
329             volume += tetVol;
330         }
331         else
332         {
333             forAll(checkFace, pI)
334             {
335                 tetPointRef tpr
336                 (
337                     points[checkFace[pI]],
338                     points[checkFace.prevLabel(pI)],
339                     checkFace.centre(points),
340                     cEst
341                 );
343                 scalar tetVol = tpr.mag();
345                 // Flip if necessary
346                 if (owner[cellToCheck[faceI]] != cIndex)
347                 {
348                     tetVol *= -1.0;
349                 }
351                 // Accumulate volume-weighted tet centre
352                 centre += tetVol*tpr.centre();
354                 // Accumulate tet volume
355                 volume += tetVol;
356             }
357         }
358     }
360     centre /= volume + VSMALL;
364 // Determine whether a segment intersects a triangular face
365 inline bool segmentTriFaceIntersection
367     const triPointRef& faceToCheck,
368     const linePointRef& edgeToCheck,
369     vector& intPoint
372     // Fetch references
373     const vector& p1 = edgeToCheck.start();
374     const vector& p2 = edgeToCheck.end();
376     // Define face-normal
377     vector n = faceToCheck.normal();
378     n /= mag(n) + VSMALL;
380     // Compute uValue
381     scalar numerator = n & (faceToCheck.a() - p1);
382     scalar denominator = n & (p2 - p1);
384     // Check if the edge is parallel to the face
385     if (mag(denominator) < VSMALL)
386     {
387         return false;
388     }
390     scalar u = (numerator / denominator);
392     // Check for intersection along line.
393     if ((u >= 0.0) && (u <= 1.0))
394     {
395         // Compute point of intersection
396         intPoint = p1 + u*(p2 - p1);
398         // Also make sure that intPoint lies within the face
399         if (pointInTriFace(faceToCheck, intPoint, false))
400         {
401             return true;
402         }
403     }
405     // Failed to fall within edge-bounds, or within face
406     return false;
410 // Determine whether the particular point lies
411 // inside the given triangular face
412 inline bool pointInTriFace
414     const triPointRef& faceToCheck,
415     const vector& cP,
416     bool testCoplanarity
419     // Copy inputs
420     const vector& a = faceToCheck.a();
421     const vector& b = faceToCheck.b();
422     const vector& c = faceToCheck.c();
424     // Compute the normal
425     vector nf = faceToCheck.normal();
427     if ( ((0.5 * ((b - a)^(cP - a))) & nf) < 0.0)
428     {
429         return false;
430     }
432     if ( ((0.5 * ((c - b)^(cP - b))) & nf) < 0.0)
433     {
434         return false;
435     }
437     if ( ((0.5 * ((a - c)^(cP - c))) & nf) < 0.0)
438     {
439         return false;
440     }
442     if (testCoplanarity)
443     {
444         vector ftp(a - cP);
446         // Normalize vectors
447         nf /= mag(nf) + VSMALL;
448         ftp /= mag(ftp) + VSMALL;
450         if (mag(ftp & nf) > VSMALL)
451         {
452             return false;
453         }
454     }
456     // Passed test with all edges
457     return true;
461 // Parallel blocking send
462 inline void pWrite
464     const label toID,
465     const label& data,
466     bool blocking
469     OPstream::write
470     (
471         (blocking ? Pstream::blocking : Pstream::nonBlocking),
472         toID,
473         reinterpret_cast<const char*>(&data),
474         sizeof(label)
475     );
479 // Parallel blocking receive
480 inline void pRead
482     const label fromID,
483     label& data,
484     bool blocking
487     IPstream::read
488     (
489         (blocking ? Pstream::blocking : Pstream::nonBlocking),
490         fromID,
491         reinterpret_cast<char*>(&data),
492         sizeof(label)
493     );
497 // Parallel non-blocking send for fixed lists
498 template <class Type, unsigned Size>
499 inline void pWrite
501     const label toID,
502     const FixedList<Type, Size>& data
505     OPstream::write
506     (
507         Pstream::blocking,
508         toID,
509         reinterpret_cast<const char*>(&data[0]),
510         Size*sizeof(Type)
511     );
515 // Parallel non-blocking receive for fixed lists
516 template <class Type, unsigned Size>
517 inline void pRead
519     const label fromID,
520     FixedList<Type, Size>& data
523     IPstream::read
524     (
525         Pstream::blocking,
526         fromID,
527         reinterpret_cast<char*>(data.begin()),
528         Size*sizeof(Type)
529     );
533 // Parallel non-blocking send for lists
534 template <class Type>
535 inline void pWrite
537     const label toID,
538     const UList<Type>& data
541     OPstream::write
542     (
543         Pstream::nonBlocking,
544         toID,
545         reinterpret_cast<const char*>(&data[0]),
546         data.size()*sizeof(Type)
547     );
551 // Parallel non-blocking receive for lists
552 template <class Type>
553 inline void pRead
555     const label fromID,
556     UList<Type>& data
559     IPstream::read
560     (
561         Pstream::nonBlocking,
562         fromID,
563         reinterpret_cast<char*>(&data[0]),
564         data.size()*sizeof(Type)
565     );
569 // Wait for buffer transfer completion.
570 inline void waitForBuffers()
572     if (Pstream::parRun())
573     {
574         OPstream::waitRequests();
575         IPstream::waitRequests();
576     }
580 // Method to insert a label between two labels in a list
581 // Assumes that all labels are unique.
582 inline void insertLabel
584     const label newLabel,
585     const label labelA,
586     const label labelB,
587     labelList& list
590     // Create a new list
591     bool found = false;
592     label origSize = list.size();
593     labelList newList(origSize + 1);
595     label index = 0, nextI = -1;
597     // Start a linear search
598     forAll(list, itemI)
599     {
600         newList[index++] = list[itemI];
602         nextI = list.fcIndex(itemI);
604         if
605         (
606             (
607                 (list[itemI] == labelA && list[nextI] == labelB) ||
608                 (list[itemI] == labelB && list[nextI] == labelA)
609             ) &&
610            !found
611         )
612         {
613             found = true;
614             newList[index++] = newLabel;
615         }
616     }
618     if (!found)
619     {
620         FatalErrorIn
621         (
622             "inline void meshOps::insertLabel"
623             "(const label, const label, const label, labelList&)"
624         )   << nl << "Cannot insert " << newLabel
625             << " in list: " << list << nl
626             << " Labels: "
627             << labelA << " and " << labelB
628             << " were not found in sequence."
629             << abort(FatalError);
630     }
632     // Transfer the list
633     list.transfer(newList);
637 // Utility method to replace a label in a given list
638 inline void replaceLabel
640      const label original,
641      const label replacement,
642      labelList& list
645     label index = -1;
647     if ((index = findIndex(list, original)) > -1)
648     {
649         list[index] = replacement;
650     }
651     else
652     {
653         FatalErrorIn
654         (
655             "inline void label meshOps::replaceLabel"
656             "(const label, const label, labelList&)"
657         )   << nl << "Cannot find " << original
658             << " in list: " << list << nl
659             << " Label: " << replacement
660             << " was not used in replacement."
661             << abort(FatalError);
662     }
666 // Utility method to size-up the list to include an item
667 template <class Type>
668 inline void sizeUpList
670     const Type& item,
671     List<Type>& list
674     list.setSize(list.size() + 1, item);
678 // Utility method to size-down the list to remove an item
679 template <class Type>
680 inline void sizeDownList
682     const Type& item,
683     List<Type>& list
686     label index = -1;
688     if ((index = findIndex(list, item)) > -1)
689     {
690         meshOps::removeIndex(index, list);
691     }
692     else
693     {
694         FatalErrorIn
695         (
696             "inline void meshOps::sizeDownList"
697             "(const Type& item, List<Type>& list)"
698         )
699             << nl << "Item: " << item
700             << " was not found in list. " << nl
701             << " List: " << nl << list
702             << abort(FatalError);
703     }
707 // Remove an item at a particular index in the list
708 template <class Type>
709 inline void removeIndex
711     const label index,
712     List<Type>& list
715     // Create a new list
716     List<Type> newList(list.size() - 1);
718     // Copy individual items
719     label n = 0;
721     forAll(list, itemI)
722     {
723         if (itemI == index)
724         {
725             continue;
726         }
728         newList[n++] = list[itemI];
729     }
731     // Overwrite
732     list.transfer(newList);
736 } // End namespace meshOps
739 } // End namespace Foam
741 // ************************************************************************* //