1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | cfMesh: A library for mesh generation
5 \\ / A nd | Author: Franjo Juretic (franjo.juretic@c-fields.com)
6 \\/ M anipulation | Copyright (C) Creative Fields, Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of cfMesh.
11 cfMesh 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 cfMesh 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 cfMesh. If not, see <http://www.gnu.org/licenses/>.
26 \*---------------------------------------------------------------------------*/
28 #include "extrudeLayer.H"
29 #include "helperFunctions.H"
30 #include "polyMeshGenAddressing.H"
31 #include "meshSurfaceEngine.H"
32 #include "meshSurfacePartitioner.H"
33 #include "labelledPointScalar.H"
39 #ifdef DEBUGExtrudeLayer
40 #include "polyMeshGenChecks.H"
43 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
48 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
49 // Nested class definition
51 extrudeLayer::addressingCalculator::addressingCalculator
53 const faceListPMG& faces,
54 const LongList<labelPair>& extrudedFaces,
55 const LongList<bool>& pairOrientation,
56 const VRWGraph& pointExtruded
60 extrudedFaces_(extrudedFaces),
61 pairOrientation_(pairOrientation),
62 pointExtruded_(pointExtruded)
65 extrudeLayer::addressingCalculator::~addressingCalculator()
68 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
70 void extrudeLayer::createDuplicateFrontFaces(const LongList<labelPair>& front)
72 polyMeshGenModifier meshModifier(mesh_);
74 const labelList& owner = mesh_.owner();
75 const labelList& neighbour = mesh_.neighbour();
76 faceListPMG& faces = meshModifier.facesAccess();
77 cellListPMG& cells = meshModifier.cellsAccess();
79 labelList faceInFront(faces.size(), -1);
80 LongList<labelPair> newFaceLabels;
84 const labelPair& lp = front[ffI];
86 if( faceInFront[lp.first()] == -1 )
88 faceInFront[lp.first()] = newFaceLabels.size();
89 newFaceLabels.append(labelPair(-1, -1));
92 labelPair& cf = newFaceLabels[faceInFront[lp.first()]];
94 if( (lp.second() == owner[lp.first()]) && (cf.first() == -1) )
99 else if( (lp.second() == neighbour[lp.first()]) && (cf.second() == -1) )
101 cf.second() = counter;
106 //- create a copy of the faces in the extrusion front
107 //- to create space for the layer
108 faces.setSize(nOrigFaces_+counter);
109 extrudedFaces_.setSize(counter);
110 pairOrientation_.setSize(counter);
113 # pragma omp parallel for if( faceInFront.size() > 100 ) schedule(guided)
115 forAll(faceInFront, faceI)
117 if( faceInFront[faceI] < 0 )
120 const label fOwn = newFaceLabels[faceInFront[faceI]].first();
121 const label fNei = newFaceLabels[faceInFront[faceI]].second();
123 if( neighbour[faceI] < 0 )
128 faces[nOrigFaces_+fOwn] = faces[faceI];
129 extrudedFaces_[fOwn] = labelPair(nOrigFaces_+fOwn, faceI);
130 pairOrientation_[fOwn] = true;
136 if( fOwn != -1 && fNei != -1 )
140 faces[nOrigFaces_+fOwn] = faces[faceI];
141 extrudedFaces_[fOwn] = labelPair(nOrigFaces_+fOwn, faceI);
142 pairOrientation_[fOwn] = true;
144 faces[nOrigFaces_+fNei] = faces[faceI].reverseFace();
145 extrudedFaces_[fNei] = labelPair(nOrigFaces_+fNei, faceI);
146 pairOrientation_[fNei] = false;
150 faces[nOrigFaces_+fOwn].transfer(faces[faceI]);
151 extrudedFaces_[fOwn] = labelPair(nOrigFaces_+fOwn, faceI);
152 pairOrientation_[fOwn] = false;
154 faces[faceI] = faces[nOrigFaces_+fOwn].reverseFace();
156 faces[nOrigFaces_+fNei] = faces[faceI];
157 extrudedFaces_[fNei] = labelPair(nOrigFaces_+fNei, faceI);
158 pairOrientation_[fNei] = true;
161 else if( fOwn != -1 )
163 faces[nOrigFaces_+fOwn].transfer(faces[faceI]);
164 faces[faceI] = faces[nOrigFaces_+fOwn].reverseFace();
165 extrudedFaces_[fOwn] = labelPair(nOrigFaces_+fOwn, faceI);
166 pairOrientation_[fOwn] = false;
168 else if( fNei != -1 )
170 faces[nOrigFaces_+fNei] = faces[faceI].reverseFace();
171 extrudedFaces_[fNei] = labelPair(nOrigFaces_+fNei, faceI);
172 pairOrientation_[fNei] = false;
177 //- renumber the cells
179 # pragma omp parallel for if( faceInFront.size() > 100 ) schedule(guided)
181 forAll(faceInFront, faceI)
183 if( faceInFront[faceI] < 0 )
186 const labelPair& lp = newFaceLabels[faceInFront[faceI]];
188 if( lp.first() != -1 )
190 cell& c = cells[owner[faceI]];
194 c[fI] = nOrigFaces_ + lp.first();
196 if( lp.second() != -1 )
198 cell& c = cells[neighbour[faceI]];
202 c[fI] = nOrigFaces_ + lp.second();
206 meshModifier.clearAll();
209 void extrudeLayer::createNewVertices()
211 polyMeshGenModifier meshModifier(mesh_);
212 meshModifier.clearAll();
213 pointFieldPMG& points = meshModifier.pointsAccess();
214 faceListPMG& faces = meshModifier.facesAccess();
216 const labelList& owner = mesh_.owner();
217 const labelList& neighbour = mesh_.neighbour();
219 //- find the points in the marked front
220 List<direction> frontPoints(points.size(), NONE);
223 # pragma omp parallel for if( points.size() > 1000 ) schedule(guided)
225 forAll(extrudedFaces_, efI)
227 const face& f = faces[extrudedFaces_[efI].first()];
230 frontPoints[f[pI]] |= FRONTVERTEX;
233 //- propagate this information to other processors in case of a parallel run
234 if( Pstream::parRun() )
236 const polyMeshGenAddressing& addr = mesh_.addressingData();
237 const VRWGraph& pAtProcs = addr.pointAtProcs();
238 const Map<label>& globalToLocal = addr.globalToLocalPointAddressing();
239 const DynList<label>& pProcs = addr.pointNeiProcs();
242 std::map<label, labelLongList> exchangeData;
244 exchangeData.insert(std::make_pair(pProcs[i], labelLongList()));
246 //- collect the information about markes points at processor boundaries
247 forAllConstIter(Map<label>, globalToLocal, it)
248 if( frontPoints[it()] & FRONTVERTEX )
250 //- mark points at processor boundaries
251 frontPoints[it()] |= FRONTVERTEXPROCBND;
253 forAllRow(pAtProcs, it(), i)
255 const label neiProc = pAtProcs(it(), i);
257 if( neiProc == Pstream::myProcNo() )
260 exchangeData[neiProc].append(it.key());
264 LongList<label> receivedData;
265 help::exchangeMap(exchangeData, receivedData);
268 # pragma omp parallel for if( receivedData.size() > 1000 ) \
271 forAll(receivedData, i)
273 frontPoints[globalToLocal[receivedData[i]]] =
274 FRONTVERTEX+FRONTVERTEXPROCBND;
278 //- create a new vertex for each group of faces
279 //- faces are grouped such that the faces belonging to the same group
280 //- can be visited over cells without crossing any front faces
282 pointFaces.reverseAddressing(points.size(), faces);
284 if( Pstream::parRun() )
286 Pout << "Creating new points at processor boundaries" << endl;
287 for(label procI=0;procI<Pstream::nProcs();++procI)
289 if( Pstream::myProcNo() == procI )
291 Pout << "Front points are " << frontPoints << endl;
294 returnReduce(1, sumOp<label>());
297 //- create new vertices at processor boundaries
298 const PtrList<processorBoundaryPatch>& procBoundaries =
299 mesh_.procBoundaries();
300 const polyMeshGenAddressing& addr = mesh_.addressingData();
301 const VRWGraph& pAtProcs = addr.pointAtProcs();
302 const labelLongList& globalPointLabel = addr.globalPointLabel();
303 const Map<label>& globalToLocal = addr.globalToLocalPointAddressing();
304 const DynList<label>& pProcs = addr.pointNeiProcs();
305 const labelLongList& globalCellLabel = addr.globalCellLabel();
307 //- create the information which faces are attached to points
308 //- at parallel boundaries in dual form where each edge represents
309 //- global labels of cells sharing a face
310 typedef std::map<label, DynList<edge> > dualEdgesMap;
311 dualEdgesMap procPointsDual;
313 //- fill in local data
314 forAllConstIter(Map<label>, globalToLocal, it)
316 if( frontPoints[it()] & FRONTVERTEXPROCBND )
318 const label pointI = it();
319 DynList<edge>& pEdges = procPointsDual[pointI];
321 forAllRow(pointFaces, pointI, pfI)
323 const label faceI = pointFaces(pointI, pfI);
325 //- do not store faces at processor boundaries
326 //- and newly created faces
327 if( (neighbour[faceI] < 0) || (owner[faceI] < 0) )
332 globalCellLabel[owner[faceI]],
333 globalCellLabel[neighbour[faceI]]
341 for(label procI=0;procI<Pstream::nProcs();++procI)
343 if( Pstream::myProcNo() == procI )
345 forAllConstIter(dualEdgesMap, procPointsDual, it)
346 Pout << "Point " << it->first << " local dual edges " << it->second << endl;
349 returnReduce(1, sumOp<label>());
352 //- fill-in with data at processor boundaries. Store edges
353 //- on the processor with the lower label not to duplicate the data
354 returnReduce(1, sumOp<label>());
355 Pout << "Adding data from processor boundaries" << endl;
356 forAll(procBoundaries, patchI)
358 if( procBoundaries[patchI].owner() )
361 const label start = procBoundaries[patchI].patchStart();
362 labelList globalLabels(procBoundaries[patchI].patchSize());
363 forAll(globalLabels, fI)
365 if( owner[start+fI] < 0 )
367 globalLabels[fI] = -1;
371 globalLabels[fI] = globalCellLabel[owner[start+fI]];
378 procBoundaries[patchI].neiProcNo(),
379 globalLabels.byteSize()
382 toOtherProc << globalLabels;
385 forAll(procBoundaries, patchI)
387 if( !procBoundaries[patchI].owner() )
390 labelList receivedData;
391 IPstream fromOtherProc
394 procBoundaries[patchI].neiProcNo()
397 fromOtherProc >> receivedData;
399 const label start = procBoundaries[patchI].patchStart();
401 forAll(receivedData, i)
403 if( owner[start+i] < 0 )
406 const face& f = faces[start+i];
410 if( frontPoints[f[pI]] & FRONTVERTEXPROCBND )
412 dualEdgesMap::iterator dIter =
413 procPointsDual.find(f[pI]);
414 const label cOwn = globalCellLabel[owner[start+i]];
415 const label cNei = receivedData[i];
416 dIter->second.append(edge(cOwn, cNei));
422 //- exchange this information with neighbouring processors
423 returnReduce(1, sumOp<label>());
424 Pout << "Exchanging data with other processors" << endl;
426 std::map<label, labelLongList> exchangeData;
428 exchangeData.insert(std::make_pair(pProcs[i], labelLongList()));
430 //- fill in the exchangeData map
431 forAllConstIter(dualEdgesMap, procPointsDual, dIter)
433 const label pointI = dIter->first;
435 forAllRow(pAtProcs, pointI, i)
437 const label neiProc = pAtProcs(pointI, i);
439 if( neiProc == Pstream::myProcNo() )
442 labelLongList& dts = exchangeData[neiProc];
444 dts.append(globalPointLabel[pointI]);
446 const DynList<edge>& dualEdges = dIter->second;
447 dts.append(dualEdges.size());
448 forAll(dualEdges, edgeI)
450 const edge& e = dualEdges[edgeI];
451 dts.append(e.start());
457 //- exchange data with other processors
458 labelLongList receivedData;
459 help::exchangeMap(exchangeData, receivedData);
461 //- update local data
463 while( counter < receivedData.size() )
465 const label pointI = globalToLocal[receivedData[counter++]];
467 DynList<edge>& dualEdges = procPointsDual[pointI];
469 const label nDualEdges = receivedData[counter++];
470 for(label eI=0;eI<nDualEdges;++eI)
473 e.start() = receivedData[counter++];
474 e.end() = receivedData[counter++];
480 for(label procI=0;procI<Pstream::nProcs();++procI)
482 if( Pstream::myProcNo() == procI )
484 forAllConstIter(dualEdgesMap, procPointsDual, it)
485 Pout << "Point " << it->first << " dual edges " << it->second << endl;
488 returnReduce(1, sumOp<label>());
491 //- Finally, find groups of faces and create new vertices
492 returnReduce(1, sumOp<label>());
493 Pout << "Finding groups of edges at vertex" << endl;
494 forAllConstIter(dualEdgesMap, procPointsDual, dIter)
496 const label pointI = dIter->first;
497 const DynList<edge>& dEdges = dIter->second;
499 DynList<label> edgeGroup;
500 edgeGroup.setSize(dEdges.size());
503 //- check edge connections and store all edges which can be reached
504 //- over other edges into the same group
509 if( edgeGroup[eI] != -1 )
512 edgeGroup[eI] = group;
513 DynList<label> front;
516 while( front.size() != 0 )
518 const label eLabel = front.removeLastElement();
522 if( edgeGroup[eJ] != -1 )
527 if( dEdges[eLabel].commonVertex(dEdges[eJ]) != -1 )
530 edgeGroup[eJ] = group;
538 //- find face groups from the groups assigned to dual edges
539 DynList<label> faceGroups;
540 faceGroups.setSize(pointFaces.sizeOfRow(pointI));
543 forAllRow(pointFaces, pointI, pfI)
545 const label faceI = pointFaces(pointI, pfI);
547 if( owner[faceI] < 0 )
550 const label own = globalCellLabel[owner[faceI]];
554 const edge& dualEdge = dEdges[eI];
556 if( (own == dualEdge.start()) || (own == dualEdge.end()) )
558 faceGroups[pfI] = edgeGroup[eI];
564 Info << "Edge groups for point " << pointI << " are " << edgeGroup << endl;
565 Info << "Face groups at point " << pointI << " are " << faceGroups
566 << " point faces " << pointFaces[pointI] << endl;
568 //- stop in case there is only one group
569 //- of faces attached to this point
573 forAll(faceGroups, i)
574 if( faceGroups[i] != 0 )
581 FatalErrorIn("void extrudeLayer::createNewVertices()")
582 << "Front is not defined at point " << pointI
583 << ". Cannot continue.." << exit(FatalError);
586 //- create new vertices
587 const label currentNumPoints = points.size();
588 for(label i=0;i<group;++i)
590 const point p = points[pointI];
591 origPointLabel_.append(pointI);
596 forAllRow(pointFaces, pointI, pfI)
598 if( faceGroups[pfI] == -1 )
601 face& f = faces[pointFaces(pointI, pfI)];
603 const label pos = f.which(pointI);
604 f[pos] = currentNumPoints + faceGroups[pfI];
608 Pout << "Finishing creating new vertices at paralle boundaries" << endl;
609 returnReduce(1, sumOp<label>());
612 //- treat local points
613 forAll(pointFaces, pointI)
615 if( frontPoints[pointI] != FRONTVERTEX )
618 //- assign groups to faces and cells
619 DynList<label> faceGroup;
620 faceGroup.setSize(pointFaces.sizeOfRow(pointI));
625 forAllRow(pointFaces, pointI, pfI)
627 if( pointFaces(pointI, pfI) < nOrigFaces_ )
629 if( faceGroup[pfI] != -1 )
632 DynList<label> front;
634 faceGroup[pfI] = group;
636 while( front.size() )
638 const label fLabel = front.removeLastElement();
640 const label own = owner[pointFaces(pointI, fLabel)];
641 const label nei = neighbour[pointFaces(pointI, fLabel)];
643 forAllRow(pointFaces, pointI, pfJ)
645 if( faceGroup[pfJ] != -1 )
648 const label faceJ = pointFaces(pointI, pfJ);
650 if( owner[faceJ] < 0 )
653 if( owner[faceJ] == own || owner[faceJ] == nei )
655 faceGroup[pfJ] = group;
659 if( neighbour[faceJ] < 0 )
662 if( neighbour[faceJ] == own || neighbour[faceJ] == nei )
664 faceGroup[pfJ] = group;
673 //- stop in case there is only one group of faces attached to this point
678 if( faceGroup[i] != 0 )
685 FatalErrorIn("void extrudeLayer::createNewVertices()")
686 << "Front is not defined at point " << pointI
687 << ". Cannot continue.." << exit(FatalError);
690 //- create new vertices
691 const label currentNumPoints = points.size();
692 for(label i=0;i<group;++i)
694 const point p = points[pointI];
695 origPointLabel_.append(pointI);
700 forAllRow(pointFaces, pointI, pfI)
702 if( faceGroup[pfI] == -1 )
705 face& f = faces[pointFaces(pointI, pfI)];
707 const label pos = f.which(pointI);
708 f[pos] = currentNumPoints + faceGroup[pfI];
712 polyMeshGenModifier(mesh_).clearOut();
714 # ifdef DEBUGExtrudeLayer
715 const label procID = mesh_.addPointSubset("parPoints");
716 const label frontID = mesh_.addPointSubset("frontPoints");
717 forAll(frontPoints, pI)
719 if( frontPoints[pI] & FRONTVERTEXPROCBND )
720 mesh_.addPointToSubset(procID, pI);
721 if( frontPoints[pI] & FRONTVERTEX )
722 mesh_.addPointToSubset(frontID, pI);
725 returnReduce(1, sumOp<label>());
730 void extrudeLayer::movePoints()
732 pointFieldPMG& points = mesh_.points();
733 const faceListPMG& faces = mesh_.faces();
735 vectorField displacements(points.size()-nOrigPoints_);
736 boolList pointAtProcBnd(displacements.size(), false);
739 pointFaces.reverseAddressing(points.size(), mesh_.faces());
741 if( Pstream::parRun() )
743 const polyMeshGenAddressing& addr = mesh_.addressingData();
744 const Map<label>& globalToLocal = addr.globalToLocalPointAddressing();
745 const VRWGraph& pAtProcs = addr.pointAtProcs();
746 const DynList<label>& pProcs = addr.pointNeiProcs();
748 std::map<label, vector> normals;
749 std::map<label, scalar> distances;
751 //- create a map for exchanging data
752 std::map<label, LongList<labelledPointScalar> > exchangeData;
756 std::make_pair(pProcs[i], LongList<labelledPointScalar>())
759 //- create displacements from local data
760 forAllConstIter(Map<label>, globalToLocal, it)
762 if( it() >= nOrigPoints_ )
764 const label pointI = it();
766 pointAtProcBnd[pointI-nOrigPoints_] = true;
768 //- create local part of the displacement vector
769 labelledPointScalar lps;
770 lps.pointLabel() = it.key();
771 lps.coordinates() = vector::zero;
772 lps.scalarValue() = VGREAT;
774 forAllRow(pointFaces, pointI, pfI)
776 const label faceI = pointFaces(pointI, pfI);
778 if( faceI >= nOrigFaces_ )
780 const face& f = faces[faceI];
782 lps.coordinates() -= f.normal(points);
784 if( thickness_ < 0.0 )
786 const vector c = f.centre(points);
790 d = Foam::min(d, Foam::mag(points[f[pI]] - c));
793 lps.scalarValue() = Foam::min(lps.scalarValue(), d);
797 lps.scalarValue() = thickness_;
802 normals[pointI] = lps.coordinates();
803 distances[pointI] = lps.scalarValue();
805 //- store data in the exchangeData map
806 forAllRow(pAtProcs, pointI, i)
808 const label neiProc = pAtProcs(pointI, i);
810 if( neiProc == Pstream::myProcNo() )
813 exchangeData[neiProc].append(lps);
818 LongList<labelledPointScalar> receivedData;
819 help::exchangeMap(exchangeData, receivedData);
821 forAll(receivedData, i)
823 const labelledPointScalar& lps = receivedData[i];
824 const label pointI = globalToLocal[lps.pointLabel()];
826 normals[pointI] += lps.coordinates();
827 scalar& d = distances[pointI];
828 d = Foam::min(d, lps.scalarValue());
831 //- calculate displacements of vertices at processor boundaries
834 std::map<label, vector>::const_iterator it=normals.begin();
839 vector n = it->second;
840 if( mag(n) > VSMALL )
842 displacements[it->first-nOrigPoints_] = n * distances[it->first];
847 # pragma omp parallel if( displacements.size() > 100 )
850 //- find displacement vectors
852 # pragma omp for schedule(guided)
854 forAll(displacements, pI)
856 if( pointAtProcBnd[pI] )
859 const label pointI = nOrigPoints_ + pI;
861 vector normal(vector::zero);
862 scalar thickness(VGREAT);
864 forAllRow(pointFaces, pointI, pfI)
866 const label faceI = pointFaces(pointI, pfI);
868 if( faceI >= nOrigFaces_ )
870 const face& f = faces[faceI];
872 normal -= f.normal(points);
874 if( thickness_ < 0.0 )
876 const vector c = f.centre(points);
880 d = Foam::min(d, Foam::mag(points[f[pI]] - c));
882 thickness = Foam::min(thickness, d);
887 if( thickness_ >= 0.0 )
889 thickness = thickness_;
896 const scalar d = mag(normal);
900 displacements[pI] = normal * thickness;
908 # pragma omp for schedule(guided)
910 forAll(displacements, pI)
911 points[nOrigPoints_+pI] += displacements[pI];
914 # ifdef DEBUGExtrudeLayer
916 returnReduce(1, sumOp<label>());
921 void extrudeLayer::createNewFacesParallel()
923 if( !Pstream::parRun() )
926 VRWGraph newProcFaces;
927 labelLongList faceProcPatch;
929 //- add faces into the mesh
930 polyMeshGenModifier(mesh_).addProcessorFaces(newProcFaces, faceProcPatch);
933 void extrudeLayer::createLayerCells()
935 const faceListPMG& faces = mesh_.faces();
937 VRWGraphList newCells;
939 //- create cells from corners and edges
940 faceList::subList newFaces(faces, faces.size()-nOrigFaces_, nOrigFaces_);
942 pointFaces.reverseAddressing(mesh_.points().size(), newFaces);
944 //- create new cells extruded from the faces in the selected front
945 forAll(extrudedFaces_, extrudedI)
947 const face& f = faces[extrudedFaces_[extrudedI].first()];
948 const face& of = faces[extrudedFaces_[extrudedI].second()];
950 //- create new cell from the front pair
951 DynList<DynList<label, 4> > newCell;
952 newCell.setSize(f.size()+2);
957 if( pairOrientation_[extrudedI] )
959 //- create a new cell. Faces are of the same orientation
962 DynList<label, 4>& ef = newCell[pI+2];
966 ef[1] = f.nextLabel(pI);
967 ef[2] = of[f.fcIndex(pI)];
973 //- create a new cell. Faces are of the opposite orientation
976 DynList<label, 4>& ef = newCell[pI+2];
980 ef[1] = f.nextLabel(pI);
981 ef[2] = of[(f.size()-f.fcIndex(pI))%f.size()];
982 ef[3] = of[(f.size()-pI)%f.size()];
986 newCells.appendGraph(newCell);
989 addressingCalculator adc
997 //- create cells created as a consequence of self-intersection
998 //- over edges. And edge is transformed into a hex cell
999 forAll(extrudedFaces_, extrudedI)
1001 const face& f = faces[extrudedFaces_[extrudedI].first()];
1005 const label pointI = f[eI];
1006 if( pointFaces.sizeOfRow(pointI) == 0 )
1008 const label nextI = f.nextLabel(eI);
1009 if( pointFaces.sizeOfRow(nextI) == 0 )
1011 if( pointI < nextI )
1014 //- find point labels of the edge which is the origin
1015 //- of the edge (pointI, nextI) with respect to face extrudedI
1016 const label origFacePointI = adc.origPoint(extrudedI, pointI);
1017 const label origFaceNextI = adc.origPoint(extrudedI, nextI);
1019 //- points of the current edge and of the original edge must have
1020 //- the same point as their origin
1021 if( origPointLabel_[pointI] != origPointLabel_[origFacePointI] )
1023 if( origPointLabel_[nextI] != origPointLabel_[origFaceNextI] )
1026 //- Finally, start creating a cell from this edge
1027 //- find the other extruded face which shares this edge
1028 const label otherExtI = adc.faceSharingEdge(extrudedI, eI);
1030 //- find point labels of the edge which is the origin
1031 //- of the edge (pointI, nextI)
1032 //- with respect to face otherExtrudedFace
1033 const label otherOrigFacePointI = adc.origPoint(otherExtI, pointI);
1034 const label otherOrigFaceNextI = adc.origPoint(otherExtI, nextI);
1036 //- find points of the edge opposite to the edge (pointI, nextI)
1037 //- these points make the original edge which is blown into
1039 label origPointI(-1), origNextI(-1);
1042 (origFacePointI >= nOrigPoints_) &&
1043 (origFaceNextI >= nOrigPoints_)
1046 //- find an extruded face attached to edge
1047 //- (origFacePointI, origFaceNextI). The must exist only one
1050 adc.facesSharingEdge(origFacePointI, origFaceNextI, fc);
1052 if( fc.size() != 1 )
1053 FatalErrorIn("void extrudeLayer::createLayerCells()")
1054 << "Cannot find searched face" << abort(FatalError);
1056 origPointI = adc.origPoint(fc[0], origFacePointI);
1057 origNextI = adc.origPoint(fc[0], origFaceNextI);
1061 FatalErrorIn("void extrudeLayer::createLayerCells()")
1062 << "Cannot find points" << abort(FatalError);
1065 //- create new cell and add it to the list
1066 FixedList<FixedList<label, 4>, 6> newCell;
1069 newCell[0][0] = pointI;
1070 newCell[0][1] = origFacePointI;
1071 newCell[0][2] = origFaceNextI;
1072 newCell[0][3] = nextI;
1075 newCell[1][0] = pointI;
1076 newCell[1][1] = nextI;
1077 newCell[1][2] = otherOrigFaceNextI;
1078 newCell[1][3] = otherOrigFacePointI;
1081 newCell[2][0] = otherOrigFacePointI;
1082 newCell[2][1] = otherOrigFaceNextI;
1083 newCell[2][2] = origNextI;
1084 newCell[2][3] = origPointI;
1087 newCell[3][0] = origFacePointI;
1088 newCell[3][1] = origPointI;
1089 newCell[3][2] = origNextI;
1090 newCell[3][3] = origFaceNextI;
1093 newCell[4][0] = pointI;
1094 newCell[4][1] = otherOrigFacePointI;
1095 newCell[4][2] = origPointI;
1096 newCell[4][3] = origFacePointI;
1099 newCell[5][0] = nextI;
1100 newCell[5][1] = origFaceNextI;
1101 newCell[5][2] = origNextI;
1102 newCell[5][3] = otherOrigFaceNextI;
1104 newCells.appendGraph(newCell);
1108 //- create cells at points where three or more self-intersecting layers meet
1109 forAll(pointFaces, pointI)
1111 if( pointFaces.sizeOfRow(pointI) < 3 )
1114 //- find labels of points
1115 DynList<label> origFacePoints;
1116 origFacePoints.setSize(pointFaces.sizeOfRow(pointI));
1117 origFacePoints = -1;
1119 forAllRow(pointFaces, pointI, pfI)
1121 const label extI = pointFaces(pointI, pfI);
1123 origFacePoints[pfI] = adc.origPoint(extI, pointI);
1126 //- cell shall be created only if all points are different
1127 bool createCell(true);
1128 for(label i=origFacePoints.size()-1;i>0;--i)
1130 for(label j=i-1;j>=0;--j)
1131 if( origFacePoints[i] == origFacePoints[j] )
1144 DynList<FixedList<label, 4>, 6> newCell;
1145 newCell.setSize(2*origFacePoints.size());
1147 //- start creating faces attached to the pointI
1148 //- this is performed by finding original points with respect to
1149 //- the face extI and the face which shares edge eI of the face extI
1150 //- this is needed to ensure correct normal orientation
1151 forAllRow(pointFaces, pointI, pfI)
1153 const label extI = pointFaces(pointI, pfI);
1155 //- find original labels of points making a forward circular edge
1156 //- with respect to pointI
1157 const face& f = faces[extrudedFaces_[extI].first()];
1158 const label eI = f.which(pointI);
1159 const label origFacePointI = origFacePoints[pfI];
1160 const label origFaceNextI = adc.origPointLabel(extI, f.fcIndex(eI));
1162 //- find another face attached to the edge eI
1163 const label fFace = adc.faceSharingEdge(extI, eI);
1164 const label pos = pointFaces.containsAtPosition(pointI, fFace);
1166 //- find an extrusion face attached to the edge consisting of points
1167 //- origFacePointI and origFaceNextI
1169 adc.facesSharingEdge(origFacePointI, origFaceNextI, fe);
1170 const label origPointI = adc.origPoint(fe[0], origFacePointI);
1172 //- create a face attached to pointI
1173 FixedList<label, 4>& cf = newCell[pfI];
1175 cf[1] = origFacePoints[pfI];
1177 cf[3] = origFacePoints[pos];
1180 //- close the cell by creating new faces from the existing
1181 //- faces which obey pre-determined order. If a face contains
1182 //- a point in the origFacePoints list at the second position, then
1183 //- the point after shall be the previous point of the face. If a face
1184 //- contains such point at the last position then the point before it
1185 //- shall be the next point in the face. The last point of the face
1186 //- is the original points from which all these points were generated.
1187 forAll(origFacePoints, opI)
1189 FixedList<label, 4>& cf = newCell[opI+origFacePoints.size()];
1191 //- find previous and next point
1192 label prev(-1), next(-1);
1193 forAll(origFacePoints, fJ)
1195 if( newCell[fJ][1] == origFacePoints[opI] )
1196 prev = newCell[fJ][2];
1197 if( newCell[fJ][3] == origFacePoints[opI] )
1198 next = newCell[fJ][2];
1201 if( (prev < 0) || (next < 0) )
1202 FatalErrorIn("void extrudeLayer::createLayerCells()")
1203 << "Corner cell is invalid" << abort(FatalError);
1206 cf[1] = origFacePoints[opI];
1208 cf[3] = origPointLabel_[pointI];
1211 newCells.appendGraph(newCell);
1214 //- create new faces at parallel boundaries
1215 createNewFacesParallel();
1217 //- add cells into the mesh
1218 polyMeshGenModifier(mesh_).addCells(newCells);
1221 void extrudeLayer::updateBoundary()
1223 wordList patchNames(mesh_.boundaries().size());
1224 wordList patchTypes(mesh_.boundaries().size());
1225 forAll(patchNames, patchI)
1227 patchNames[patchI] = mesh_.boundaries()[patchI].patchName();
1228 patchTypes[patchI] = mesh_.boundaries()[patchI].patchType();
1231 VRWGraph newBoundaryFaces;
1232 labelLongList newBoundaryOwners;
1233 labelLongList newBoundaryPatches;
1235 meshSurfaceEngine mse(mesh_);
1236 const faceList::subList& bFaces = mse.boundaryFaces();
1237 const labelList& bfOwner = mse.faceOwners();
1238 const labelList& facePatch = mse.boundaryFacePatches();
1239 const labelList& bp = mse.bp();
1241 meshSurfacePartitioner mPart(mse);
1242 const VRWGraph& pointPatches = mPart.pointPatches();
1244 //- store existing boundary faces. They remain in the mesh
1247 newBoundaryFaces.appendList(bFaces[bfI]);
1248 newBoundaryOwners.append(bfOwner[bfI]);
1249 newBoundaryPatches.append(facePatch[bfI]);
1252 //- find and store boundary faces which have been generated as a consequence
1253 //- of layer insertion
1254 const faceListPMG& faces = mesh_.faces();
1255 const labelList& owner = mesh_.owner();
1256 const labelList& neighbour = mesh_.neighbour();
1258 for(label faceI=nOrigFaces_;faceI<faces.size();++faceI)
1260 if( neighbour[faceI] >= 0 )
1263 const face& f = faces[faceI];
1268 DynList<label> origPts, newPts;
1270 if( origPointLabel_[f[pI]] < 0 )
1272 origPts.appendIfNotIn(f[pI]);
1276 origPts.appendIfNotIn(origPointLabel_[f[pI]]);
1277 newPts.append(f[pI]);
1280 if( origPts.size() > 2 )
1282 if( newPts.size() == 0 )
1285 //- this face belongs to the extruded layer
1286 //- find patches of boundary faces attached to the newly created points
1287 DynList<label> patches;
1288 DynList<label> nAppearances;
1291 const label bpI = bp[newPts[npI]];
1296 forAllRow(pointPatches, bpI, ppI)
1298 const label patchI = pointPatches(bpI, ppI);
1299 if( patches.contains(patchI) )
1301 ++nAppearances[patches.containsAtPosition(patchI)];
1305 patches.append(patchI);
1306 nAppearances.append(1);
1315 if( nAppearances[i] == newPts.size() )
1318 FatalErrorIn("void extrudeLayer::updateBoundary()")
1319 << "Found more than one patch!" << abort(FatalError);
1327 //- append boundary face
1328 newBoundaryFaces.appendList(f);
1329 newBoundaryOwners.append(owner[faceI]);
1330 newBoundaryPatches.append(patch);
1334 polyMeshGenModifier meshModifier(mesh_);
1335 meshModifier.reorderBoundaryFaces();
1336 meshModifier.replaceBoundary
1344 PtrList<boundaryPatch>& boundaries = meshModifier.boundariesAccess();
1345 forAll(boundaries, patchI)
1346 boundaries[patchI].patchType() = patchTypes[patchI];
1348 meshModifier.clearAll();
1351 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
1353 // Construct from mesh reference
1354 extrudeLayer::extrudeLayer
1357 const LongList<labelPair>& extrusionFront,
1358 const scalar thickness
1362 thickness_(thickness),
1363 nOrigPoints_(mesh.points().size()),
1364 nOrigFaces_(mesh.faces().size()),
1365 nOrigCells_(mesh.cells().size()),
1368 origPointLabel_(nOrigPoints_, -1)
1370 createDuplicateFrontFaces(extrusionFront);
1372 createNewVertices();
1380 mesh_.clearAddressingData();
1382 # ifdef DEBUGExtrudeLayer
1383 polyMeshGenChecks::checkMesh(mesh_, true);
1387 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
1389 extrudeLayer::~extrudeLayer()
1391 mesh_.clearAddressingData();
1394 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
1396 } // End namespace Foam
1398 // ************************************************************************* //