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 "refineBoundaryLayers.H"
29 #include "meshSurfaceEngine.H"
30 #include "helperFunctions.H"
31 #include "demandDrivenData.H"
35 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
40 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
42 void refineBoundaryLayers::generateNewCellsPrism
45 DynList<DynList<DynList<label, 8>, 10>, 64>& cellsFromCell
48 cellsFromCell.clear();
50 const cell& c = mesh_.cells()[cellI];
51 const labelList& owner = mesh_.owner();
54 Pout << "New cells from cell " << cellI << endl;
57 const label startBoundary = mesh_.boundaries()[0].patchStart();
59 //- find the number of lyers for this cell
60 label nLayers(1), baseFace(-1);
63 const label bfI = c[fI] - startBoundary;
65 if( (bfI < 0) || (bfI >= nLayersAtBndFace_.size()) )
68 if( nLayersAtBndFace_[bfI] < 2 )
72 Pout << "Boundary face " << bfI << endl;
75 nLayers = nLayersAtBndFace_[bfI];
80 Pout << "Number of layers " << nLayers << endl;
81 Pout << "Base face " << baseFace << " has points "
82 << mesh_.faces()[c[baseFace]] << endl;
85 Pout << "Faces from face " << fI << " are "
86 << facesFromFace_[c[fI]] << endl;
88 forAllRow(facesFromFace_, c[fI], i)
89 Pout << "Face " << facesFromFace_(c[fI], i)
90 << " is " << newFaces_[facesFromFace_(c[fI], i)] << endl;
94 //- set the number of layers
95 cellsFromCell.setSize(nLayers);
97 //- distribute existing faces into new cells
98 label otherBaseFace(-1);
103 const label faceI = facesFromFace_(c[fI], 0);
105 f = newFaces_[faceI];
106 cellsFromCell[nLayers-1].append(f);
108 else if( facesFromFace_.sizeOfRow(c[fI]) == 1 )
110 const label faceI = facesFromFace_(c[fI], 0);
113 f = newFaces_[faceI];
114 cellsFromCell[0].append(f);
118 forAllRow(facesFromFace_, c[fI], cfI)
120 const label nfI = facesFromFace_(c[fI], cfI);
122 DynList<label, 8> cf;
125 if( owner[c[fI]] != cellI )
126 cf = help::reverseFace(cf);
128 cellsFromCell[Foam::max(nLayers-1-cfI, 0)].append(cf);
133 //- generate missing faces
134 const faceListPMG& faces = mesh_.faces();
135 const face& bf = faces[c[baseFace]];
136 const face& obf = faces[c[otherBaseFace]];
137 for(label layerI=1;layerI<nLayers;++layerI)
139 //- create new face from points at the same height
140 DynList<label, 8> cf;
143 const label pointI = bf[pI];
146 Pout << "Split edges at point " << pointI << " are "
147 << splitEdgesAtPoint_[pointI] << endl;
151 if( splitEdgesAtPoint_.sizeOfRow(pointI) == 1 )
153 seI = splitEdgesAtPoint_(pointI, 0);
157 forAllRow(splitEdgesAtPoint_, pointI, sepI)
159 const label seJ = splitEdgesAtPoint_(pointI, sepI);
160 const edge& se = splitEdges_[seJ];
162 if( obf.which(se.end()) >= 0 || obf.which(se.start()) >= 0 )
170 cf.append(newVerticesForSplitEdge_(seI, layerI));
173 //- add faces to cells
174 cellsFromCell[nLayers-layerI].append(cf);
175 cellsFromCell[nLayers-1-layerI].append(cf);
179 Pout << "New cells from cell " << cellI << " are " << cellsFromCell << endl;
182 Pout << "1. Newly generated cells " << cellsFromCell << endl;
184 //- check if all generated cells are topologically closed
185 forAll(cellsFromCell, cI)
187 const DynList<DynList<label, 8>, 10>& cellFaces = cellsFromCell[cI];
189 DynList<edge, 12> edges;
190 DynList<label, 12> nAppearances;
192 forAll(cellFaces, fI)
194 const DynList<label, 8>& f = cellFaces[fI];
198 const edge e(f[eI], f.fcElement(eI));
200 const label pos = edges.containsAtPosition(e);
205 nAppearances.append(1);
214 forAll(nAppearances, eI)
215 if( nAppearances[eI] != 2 )
217 Pout << "Prism cell " << cI << " edge " << edges[eI]
218 << " is present " << nAppearances[eI] << " times!" << endl;
225 void refineBoundaryLayers::storeFacesIntoCells
228 const bool reverseOrientation,
229 const label normalDirection,
230 const bool maxCoordinate,
231 const label nLayersI,
232 const label nLayersJ,
233 const label nLayersK,
234 DynList<DynList<DynList<label, 4>, 6>, 256>& cellsFromCell
237 DynList<DynList<label> > faceFaces;
238 sortFaceFaces(faceI, faceFaces, reverseOrientation);
240 const label maxI = nLayersI - 1;
241 const label maxJ = nLayersJ - 1;
242 const label maxK = nLayersK - 1;
245 Pout << "Storing new faces from face " << faceI
246 << " reverseOrientation = " << reverseOrientation
247 << " normal direction " << normalDirection
248 << " maxCoordinate " << maxCoordinate << endl;
249 Pout << "faceFaces " << faceFaces << endl;
252 label i(-1), j(-1), k(-1);
254 forAll(faceFaces, nI)
256 forAll(faceFaces[nI], nJ)
258 const label nfI = faceFaces[nI][nJ];
261 Pout << "nI = " << nI << " nJ = " << nJ << endl;
264 if( normalDirection == 0 )
267 i = Foam::min(nI, maxI);
268 j = Foam::min(nJ, maxJ);
269 k = maxCoordinate?maxK:0;
271 else if( normalDirection == 1 )
274 i = Foam::min(nJ, maxI);
275 j = maxCoordinate?maxJ:0;
276 k = Foam::min(nI, maxK);
278 else if( normalDirection == 2 )
281 i = maxCoordinate?maxI:0;
282 j = Foam::min(nI, maxJ);
283 k = Foam::min(nJ, maxK);
286 //- store the face into a new cell
290 k * nLayersI * nLayersJ +
295 Pout << "Storing face " << newFaces_[nfI]
296 << " i = " << i << " j = " << j << " k = " << k
297 << "\n cell label " << cI << endl;
300 cellsFromCell[cI].append(newFaces_[nfI]);
305 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
307 void refineBoundaryLayers::refineEdgeHexCell::determineFacesInDirections()
309 const labelList& nLayersAtBndFace = bndLayers_.nLayersAtBndFace_;
310 const polyMeshGen& mesh = bndLayers_.mesh_;
311 const faceListPMG& faces = mesh.faces();
312 const cell& c = mesh.cells()[cellI_];
315 Pout << "Generating new cells from edge cell " << cellI_ << endl;
318 const PtrList<boundaryPatch>& bnd = mesh.boundaries();
319 const label startBoundary = bnd[0].patchStart();
321 //- find the number of layers for this cell
322 FixedList<label, 2> layersInDirection(-1), dirFace;
325 FixedList<bool, 6> determinedFace(false);
329 const label bfI = c[fI] - startBoundary;
331 if( (bfI < 0) || (bfI >= nLayersAtBndFace.size()) )
335 Pout << "Boundary face " << bfI << endl;
338 if( nLayersAtBndFace[bfI] < 2 )
341 layersInDirection[currDir] = nLayersAtBndFace[bfI];
342 dirFace[currDir] = fI;
346 //- set the number of newly create cells
347 nLayersI_ = layersInDirection[0];
348 nLayersJ_ = layersInDirection[1];
349 cellsFromCell_.setSize(nLayersI_ * nLayersJ_);
351 //- find the shared edge between the boundary faces
352 const edge commonEdge =
353 help::sharedEdge(faces[c[dirFace[0]]], faces[c[dirFace[1]]]);
355 //- faces at i = const in the local coordinate system
356 faceInDirection_[4] = dirFace[0];
357 determinedFace[dirFace[0]] = true;
360 if( determinedFace[fI] )
363 if( !help::shareAnEdge(faces[c[dirFace[0]]], faces[c[fI]]) )
365 faceInDirection_[5] = fI;
366 determinedFace[fI] = true;
371 //- faces k = const in the local coordinate system
372 faceInDirection_[2] = dirFace[1];
373 determinedFace[dirFace[1]] = true;
376 if( determinedFace[fI] )
379 if( !help::shareAnEdge(faces[c[dirFace[1]]], faces[c[fI]]) )
381 faceInDirection_[3] = fI;
382 determinedFace[fI] = true;
388 Pout << "Common edge " << commonEdge << endl;
389 Pout << "Donor face " << dirFace[0] << endl;
390 Pout << "Donor face points " << faces[c[dirFace[0]]] << endl;
393 //- find the face attached to the starting point of the edge and
394 //- the face attached to the end point of the edge
397 if( determinedFace[fI] )
401 (faces[c[fI]].which(commonEdge.start()) >= 0) &&
402 (help::positionOfEdgeInFace(commonEdge, faces[c[fI]]) < 0)
404 faceInDirection_[0] = fI;
407 (faces[c[fI]].which(commonEdge.end()) >= 0) &&
408 (help::positionOfEdgeInFace(commonEdge, faces[c[fI]]) < 0)
410 faceInDirection_[1] = fI;
413 //- check the orientation of faces
414 const labelList& owner = mesh.owner();
416 //- checking face at direction k = 0
417 faceOrientation_[0] = owner[c[faceInDirection_[0]]] == cellI_?true:false;
419 //- checking face in direction k = 1
420 faceOrientation_[1] = owner[c[faceInDirection_[1]]] == cellI_?false:true;
422 //- set orientation flag for face in direction j = 0
423 faceOrientation_[2] = true;
425 //- checking face in direction j = nLayersJ_
426 faceOrientation_[3] = owner[c[faceInDirection_[3]]] == cellI_?false:true;
428 //- set orientation flag for face in direction i = 0
429 faceOrientation_[4] = true;
431 //- checking face in direction i = nLayersI_
432 faceOrientation_[5] = owner[c[faceInDirection_[5]]] == cellI_?false:true;
435 Pout << "Face at start " << faces[c[faceInDirection_[0]]] << endl;
436 Pout << "Face at end " << faces[c[faceInDirection_[1]]] << endl;
437 forAll(faceInDirection_, i)
438 Pout << "Face in direction " << i << " is "
439 << faces[c[faceInDirection_[i]]]
440 << " orientation " << faceOrientation_[i] << endl;
444 void refineBoundaryLayers::refineEdgeHexCell::populateExistingFaces()
446 const cell& c = bndLayers_.mesh_.cells()[cellI_];
447 const VRWGraph& facesFromFace = bndLayers_.facesFromFace_;
448 const VRWGraph& newFaces = bndLayers_.newFaces_;
450 cellsFromCell_.setSize(nLayersI_ * nLayersJ_);
451 forAll(cellsFromCell_, cI)
452 cellsFromCell_[cI].clear();
454 //- store new faces at k = 0
455 bndLayers_.storeFacesIntoCells
457 c[faceInDirection_[0]], faceOrientation_[0],
459 nLayersI_, nLayersJ_, 1,
463 //- store new faces at k = 1
464 bndLayers_.storeFacesIntoCells
466 c[faceInDirection_[1]], faceOrientation_[1],
468 nLayersI_, nLayersJ_, 1,
472 //- store new faces at j = 0
473 forAllRow(facesFromFace, c[faceInDirection_[2]], i)
475 const label faceI = facesFromFace(c[faceInDirection_[2]], i);
476 cellsFromCell_[i].append(newFaces[faceI]);
479 //- store faces at j = nLayersJ
480 const label maxJ = nLayersJ_ - 1;
481 forAllRow(facesFromFace, c[faceInDirection_[3]], i)
483 const label faceI = facesFromFace(c[faceInDirection_[3]], i);
484 cellsFromCell_[i + maxJ * nLayersI_].append(newFaces[faceI]);
487 //- store new faces at i = 0
488 forAllRow(facesFromFace, c[faceInDirection_[4]], j)
490 const label faceI = facesFromFace(c[faceInDirection_[4]], j);
491 cellsFromCell_[j * nLayersI_].append(newFaces[faceI]);
494 //- store new faces at i = nLayersI
495 const label maxI = nLayersI_ - 1;
496 forAllRow(facesFromFace, c[faceInDirection_[5]], j)
498 const label faceI = facesFromFace(c[faceInDirection_[5]], j);
499 cellsFromCell_[j * nLayersI_ + maxI].append(newFaces[faceI]);
503 Pout << "New cells after populating existing faces "
504 << cellsFromCell_ << endl;
508 void refineBoundaryLayers::refineEdgeHexCell::generateMissingFaces()
510 const cell& c = bndLayers_.mesh_.cells()[cellI_];
512 //- fill up the matrix of points for this cell
513 //- the matrix is used for generation of new cells
514 FixedList<DynList<DynList<label> >, 2> cellPoints;
516 //- fill in the data for a cross-split faces
517 bndLayers_.sortFacePoints
519 c[faceInDirection_[0]],
523 bndLayers_.sortFacePoints
525 c[faceInDirection_[1]],
530 //- generate new internal faces for this cell
531 //- generate faces with normal in the i direction
532 const label maxI = nLayersI_ - 1;
533 const label maxJ = nLayersJ_ - 1;
535 for(label i=1;i<nLayersI_;++i)
537 for(label j=0;j<nLayersJ_;++j)
539 const label own = j * nLayersI_ + i - 1;
540 const label nei = own + 1;
544 //- generate a quad face
545 FixedList<label, 4> mf;
547 //- populate the points form cellPoints
548 mf[0] = cellPoints[0][i][j];
549 mf[1] = cellPoints[0][i][j+1];
550 mf[2] = cellPoints[1][i][j+1];
551 mf[3] = cellPoints[1][i][j];
554 Pout << "1. Adding missing face " << mf
555 << " to cells " << own << " and " << nei << endl;
558 cellsFromCell_[own].append(mf);
559 cellsFromCell_[nei].append(help::reverseFace(mf));
564 for(label index=j;index<cellPoints[0][i].size();++index)
565 mf.append(cellPoints[0][i][index]);
566 for(label index=cellPoints[1][i].size()-1;index>=j;--index)
567 mf.append(cellPoints[1][i][index]);
570 Pout << "2. Adding missing face " << mf
571 << " to cells " << own << " and " << nei << endl;
574 cellsFromCell_[own].append(mf);
575 cellsFromCell_[nei].append(help::reverseFace(mf));
580 //- generate faces with the normal in j direction
581 for(label i=0;i<nLayersI_;++i)
583 for(label j=1;j<nLayersJ_;++j)
585 const label nei = j * nLayersI_ + i;
586 const label own = (j - 1) * nLayersI_ + i;
590 //- generate a quad face
591 FixedList<label, 4> mf;
593 //- populate the points form cellPoints
594 mf[0] = cellPoints[0][i][j];
595 mf[1] = cellPoints[1][i][j];
596 mf[2] = cellPoints[1][i+1][j];
597 mf[3] = cellPoints[0][i+1][j];
600 Pout << "3. Adding missing face " << mf
601 << " to cells " << own << " and " << nei << endl;
604 cellsFromCell_[own].append(mf);
605 cellsFromCell_[nei].append(help::reverseFace(mf));
610 for(label index=i;index<cellPoints[1].size();++index)
611 mf.append(cellPoints[1][index][j]);
612 for(label index=cellPoints[0].size()-1;index>=i;--index)
613 mf.append(cellPoints[0][index][j]);
616 Pout << "4. Adding missing face " << mf
617 << " to cells " << own << " and " << nei << endl;
620 cellsFromCell_[own].append(mf);
621 cellsFromCell_[nei].append(help::reverseFace(mf));
627 Pout << "Cell " << cellI_ << " new cells are " << cellsFromCell_ << endl;
632 refineBoundaryLayers::refineEdgeHexCell::refineEdgeHexCell
635 const refineBoundaryLayers& ref
647 determineFacesInDirections();
649 populateExistingFaces();
651 generateMissingFaces();
654 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
656 void refineBoundaryLayers::refineCornerHexCell::determineFacesInDirections()
658 const polyMeshGen& mesh = bndLayers_.mesh_;
659 const cell& c = mesh.cells()[cellI_];
660 const faceListPMG& faces = mesh.faces();
661 const labelList& nLayersAtBndFace = bndLayers_.nLayersAtBndFace_;
664 Pout << "Generating new cells from corner hex cell " << cellI_ << endl;
665 Pout << "Cell faces " << c << endl;
668 const label startBoundary = mesh.boundaries()[0].patchStart();
670 //- find the number of layers for this cell
671 FixedList<label, 3> layersInDirection(-1), dirFace;
672 FixedList<bool, 6> usedDirection(false);
677 const label bfI = c[fI] - startBoundary;
679 if( (bfI < 0) || (bfI >= nLayersAtBndFace.size()) )
683 Pout << "Boundary face " << bfI << endl;
686 if( nLayersAtBndFace[bfI] < 2 )
689 usedDirection[fI] = true;
690 layersInDirection[currDir] = nLayersAtBndFace[bfI];
691 dirFace[currDir] = fI;
695 //- find a common point for all three boundary faces
696 FixedList<DynList<label, 4>, 3> bndFaces;
699 bndFaces[i] = faces[c[dirFace[i]]];
702 const label commonPoint = help::sharedVertex(bndFaces);
705 Pout << "Used directions " << usedDirection << endl;
706 Pout << "Layers in direction " << layersInDirection << endl;
707 Pout << "dirFace " << dirFace << endl;
708 Pout << "Common point " << commonPoint << endl;
711 Pout << "bnd face " << i << " is " << faces[c[dirFace[i]]] << endl;
714 //- find the position of the common point in each boundary face
715 const edgeLongList& splitEdges = bndLayers_.splitEdges_;
716 const VRWGraph& splitEdgesAtPoint = bndLayers_.splitEdgesAtPoint_;
718 const face& baseFace = faces[c[dirFace[0]]];
719 const label posInBndFace = baseFace.which(commonPoint);
721 //- find split edges starting at the commonPoints
722 forAllRow(splitEdgesAtPoint, commonPoint, i)
724 const edge& se = splitEdges[splitEdgesAtPoint(commonPoint, i)];
726 if( se == baseFace.faceEdge(posInBndFace) )
728 //- this edge is in j direction
729 splitEdgeInDirection_[1] = splitEdgesAtPoint(commonPoint, i);
731 else if( se == baseFace.faceEdge(baseFace.rcIndex(posInBndFace)) )
733 //- this edge is in i diretion
734 splitEdgeInDirection_[0] = splitEdgesAtPoint(commonPoint, i);
736 else if( splitEdgesAtPoint.sizeOfRow(commonPoint) == 3 )
738 //- this point is in k direction
739 splitEdgeInDirection_[2] = splitEdgesAtPoint(commonPoint, i);
743 //- this situation is not allowed
746 "void refineBoundaryLayers::refineCornerHexCell::"
747 "determineFacesInDirections()"
748 ) << "Cannot refine layer for cell " << cellI_ << abort(FatalError);
753 const VRWGraph& newVerticesForSplitEdge =
754 bndLayers_.newVerticesForSplitEdge_;
755 forAll(splitEdgeInDirection_, i)
756 Pout << "Split edge in direction " << i << " has nodes "
757 << splitEdges[splitEdgeInDirection_[i]]
758 << " number of points on split edge "
759 << newVerticesForSplitEdge.sizeOfRow(splitEdgeInDirection_[i])
763 //- find the direction od other boundary faces
764 //- in the local coordinate system
765 FixedList<label, 3> permutation;
768 label helper = help::positionOfEdgeInFace
770 baseFace.faceEdge(baseFace.rcIndex(posInBndFace)),
785 //- find the number of layers and a split in each direction
786 nLayersI_ = layersInDirection[permutation[2]];
787 nLayersJ_ = layersInDirection[permutation[1]];
788 nLayersK_ = layersInDirection[permutation[0]];
790 //- determine the directions of cell faces
791 //- store boundary faces first. Their normals point in the wrong direction
793 faceInDirection_[0] = dirFace[permutation[0]];
794 faceOrientation_[0] = true;
796 faceInDirection_[2] = dirFace[permutation[1]];
797 faceOrientation_[2] = true;
799 faceInDirection_[4] = dirFace[permutation[2]];
800 faceOrientation_[4] = true;
802 //- find directions of other faces and thrie orientation
803 const labelList& owner = mesh.owner();
806 if( usedDirection[fI] )
809 const bool orientation = owner[c[fI]]==cellI_?false:true;
811 if( !help::shareAnEdge(faces[c[fI]], faces[c[faceInDirection_[0]]]) )
813 //- face at k = nLayersK_
814 faceInDirection_[1] = fI;
815 faceOrientation_[1] = orientation;
819 !help::shareAnEdge(faces[c[fI]], faces[c[faceInDirection_[2]]])
822 //- face at j = nLayersJ_
823 faceInDirection_[3] = fI;
824 faceOrientation_[3] = orientation;
828 !help::shareAnEdge(faces[c[fI]], faces[c[faceInDirection_[4]]])
831 //- face at i = nLayersI_
832 faceInDirection_[5] = fI;
833 faceOrientation_[5] = orientation;
838 forAll(faceInDirection_, i)
839 Pout << "Face in direction " << i
840 << " is " << faces[c[faceInDirection_[i]]]
841 << " orientation " << faceOrientation_[i] << endl;
842 Pout << "nLayersI = " << nLayersI_
843 << " nLayersJ = " << nLayersJ_
844 << " nLayersK = " << nLayersK_ << endl;
848 void refineBoundaryLayers::refineCornerHexCell::populateExistingFaces()
850 const cell& c = bndLayers_.mesh_.cells()[cellI_];
852 //- set the number of cells
853 cellsFromCell_.setSize(nLayersI_ * nLayersJ_ * nLayersK_);
854 forAll(cellsFromCell_, i)
855 cellsFromCell_[i].clear();
857 //- add new faces from existing faces into new cells
858 forAll(faceInDirection_, dirI)
860 bndLayers_.storeFacesIntoCells
862 c[faceInDirection_[dirI]], faceOrientation_[dirI],
864 nLayersI_, nLayersJ_, nLayersK_,
870 Pout << "cellsFromCell_ before new faces " << cellsFromCell_ << endl;
875 void refineBoundaryLayers::refineCornerHexCell::generateNewPoints()
877 const cell& c = bndLayers_.mesh_.cells()[cellI_];
879 //- allocate space for points generated inside the cell
880 cellPoints_.setSize(nLayersI_+1);
881 forAll(cellPoints_, i)
883 cellPoints_[i].setSize(nLayersJ_+1);
885 forAll(cellPoints_[i], j)
887 cellPoints_[i][j].setSize(nLayersK_+1);
888 cellPoints_[i][j] = -1;
892 //- collect information about points generated on faces of the cell
893 forAll(faceInDirection_, dirI)
895 bndLayers_.sortFacePoints
897 c[faceInDirection_[dirI]],
899 faceOrientation_[dirI]
904 Pout << "Face points " << facePoints_ << endl;
907 //- fill in cellPoints at the boundary
908 forAll(cellPoints_, i)
910 forAll(cellPoints_[i], j)
912 cellPoints_[i][j][0] = facePoints_[0][i][j];
913 cellPoints_[i][j][nLayersK_] = facePoints_[1][i][j];
917 forAll(cellPoints_, i)
919 forAll(cellPoints_[i][0], k)
921 cellPoints_[i][0][k] = facePoints_[2][k][i];
922 cellPoints_[i][nLayersJ_][k] = facePoints_[3][k][i];
926 forAll(cellPoints_[0], j)
928 forAll(cellPoints_[0][j], k)
930 cellPoints_[0][j][k] = facePoints_[4][j][k];
931 cellPoints_[nLayersI_][j][k] = facePoints_[5][j][k];
935 //- useful data for generating missing points
936 const edgeLongList& splitEdges = bndLayers_.splitEdges_;
937 const edge& seDirI = splitEdges[splitEdgeInDirection_[0]];
938 const edge& seDirJ = splitEdges[splitEdgeInDirection_[1]];
939 const edge& seDirK = splitEdges[splitEdgeInDirection_[2]];
940 const VRWGraph& ptsAtEdge = bndLayers_.newVerticesForSplitEdge_;
942 //- const references to vertices of the cell ordered in a local
943 //- i, j, k coordinate system
944 pointFieldPMG& points = bndLayers_.mesh_.points();
945 const point v000 = points[seDirI.start()];
946 const point v100 = points[seDirI.end()];
947 const point v110 = points[facePoints_[0].lastElement().lastElement()];
948 const point v010 = points[seDirJ.end()];
949 const point v001 = points[seDirK.end()];
950 const point v101 = points[facePoints_[1].lastElement()[0]];
951 const point v111 = points[facePoints_[1].lastElement().lastElement()];
952 const point v011 = points[facePoints_[1][0].lastElement()];
954 for(label i=1;i<nLayersI_;++i)
960 points[ptsAtEdge(splitEdgeInDirection_[0], i)] -
961 points[seDirI.start()]
966 for(label j=1;j<nLayersJ_;++j)
972 points[ptsAtEdge(splitEdgeInDirection_[1], j)] -
973 points[seDirJ.start()]
978 for(label k=1;k<nLayersK_;++k)
984 points[ptsAtEdge(splitEdgeInDirection_[2], k)] -
985 points[seDirK.start()]
991 Pout << "Generating point in corner cell local coordinates "
992 << "u = " << u << " v = " << v << " w = " << w << endl;
995 //- calculate coordinates of the new vertex
997 (1.0 - u) * (1.0 - v) * (1.0 - w) * v000 +
998 u * (1.0 - v) * (1.0 - w) * v100 +
999 u * v * (1.0 - w) * v110 +
1000 (1.0 - u) * v * (1.0 - w) * v010 +
1001 (1.0 - u) * (1.0 - v) * w * v001 +
1002 u * (1.0 - v) * w * v101 +
1004 (1.0 - u) * v * w * v011;
1007 Pout << "New point " << points.size() << " in corner hex "
1008 << "has coordinates " << newP << endl;
1011 //- add the point to the mesh
1012 cellPoints_[i][j][k] = points.size();
1013 points.append(newP);
1019 Pout << "New cell points " << cellPoints_ << endl;
1024 void refineBoundaryLayers::refineCornerHexCell::generateMissingFaces()
1026 //- generate face in direction i
1027 for(label i=1;i<nLayersI_;++i)
1029 //- generate quad faces
1030 for(label j=0;j<nLayersJ_;++j)
1032 for(label k=0;k<nLayersK_;++k)
1034 //- skip generating last face because it might not be a quad
1035 if( (j == (nLayersJ_-1)) && (k == (nLayersK_-1)) )
1040 k * nLayersI_ * nLayersJ_ +
1044 const label nei = own + 1;
1046 FixedList<label, 4> mf;
1048 mf[0] = cellPoints_[i][j][k];
1049 mf[1] = cellPoints_[i][j+1][k];
1050 mf[2] = cellPoints_[i][j+1][k+1];
1051 mf[3] = cellPoints_[i][j][k+1];
1053 cellsFromCell_[own].append(mf);
1054 cellsFromCell_[nei].append(help::reverseFace(mf));
1058 //- generate faces which might not be a quads
1061 mf.append(cellPoints_[i][nLayersJ_-1][nLayersK_-1]);
1063 //- this face might not be a quad
1064 //- add points fom the last face in direction j
1065 const DynList<DynList<label> >& f3 = facePoints_[3];
1066 for(label index=nLayersK_-1;index<f3.size()-1;++index)
1067 mf.append(f3[index][i]);
1069 //- add points from the last face in direction k
1070 const DynList<DynList<label> >& f1 = facePoints_[1];
1071 for(label index=f1[i].size()-1;index>=nLayersJ_-1;--index)
1072 mf.append(f1[i][index]);
1076 (nLayersK_-1) * nLayersI_ * nLayersJ_ +
1077 (nLayersJ_-1) * nLayersI_ +
1081 const label nei = own + 1;
1084 Pout << "Additional face in direction i = " << i
1085 << " j = " << (nLayersJ_-1)
1086 << " has owner " << own
1087 << " neighbour " << nei << " with nodes " << mf << endl;
1090 cellsFromCell_[own].append(mf);
1091 cellsFromCell_[nei].append(help::reverseFace(mf));
1094 //- generate faces in direction j
1095 for(label j=1;j<nLayersJ_;++j)
1097 //- generate quad faces
1098 for(label i=0;i<nLayersI_;++i)
1100 for(label k=0;k<nLayersK_;++k)
1102 //- skip generating late face because it might not be a quad
1103 if( (i == (nLayersI_-1)) && (k == (nLayersK_-1)) )
1108 k * nLayersI_ * nLayersJ_ +
1115 k * nLayersI_ * nLayersJ_ +
1120 FixedList<label, 4> mf;
1122 mf[0] = cellPoints_[i][j][k];
1123 mf[1] = cellPoints_[i][j][k+1];
1124 mf[2] = cellPoints_[i+1][j][k+1];
1125 mf[3] = cellPoints_[i+1][j][k];
1127 cellsFromCell_[own].append(mf);
1128 cellsFromCell_[nei].append(help::reverseFace(mf));
1132 //- generate a face which might not be a quad
1135 mf.append(cellPoints_[nLayersI_-1][j][nLayersK_-1]);
1137 //- add points from the last face in direction k
1138 const DynList<DynList<label> >& fp1 = facePoints_[1];
1139 for(label index=nLayersI_-1;index<fp1.size()-1;++index)
1140 mf.append(fp1[index][j]);
1142 //- add points from the last face in direction i
1143 const DynList<DynList<label> >& fp5 = facePoints_[5];
1144 for(label index=fp5[j].size()-1;index>=nLayersK_-1;--index)
1145 mf.append(fp5[j][index]);
1149 (nLayersK_-1) * nLayersI_ * nLayersJ_ +
1156 (nLayersK_-1) * nLayersI_ * nLayersJ_ +
1162 Pout << "Additional face at i = " << (nLayersI_-1)
1163 << " j = " << j << " k = " << (nLayersK_-1)
1164 << " has owner " << own
1165 << " neighbour " << nei << " with nodes " << mf << endl;
1168 cellsFromCell_[own].append(mf);
1169 cellsFromCell_[nei].append(help::reverseFace(mf));
1172 //- generate faces in direction k
1173 for(label k=1;k<nLayersK_;++k)
1175 //- generate quad faces
1176 for(label i=0;i<nLayersI_;++i)
1178 for(label j=0;j<nLayersJ_;++j)
1180 //- skip the last face because it might not be a quad
1181 if( (i == (nLayersI_-1)) && (j == (nLayersJ_-1)) )
1186 (k-1) * nLayersI_ * nLayersJ_ +
1193 k * nLayersI_ * nLayersJ_ +
1198 FixedList<label, 4> mf;
1200 mf[0] = cellPoints_[i][j][k];
1201 mf[1] = cellPoints_[i+1][j][k];
1202 mf[2] = cellPoints_[i+1][j+1][k];
1203 mf[3] = cellPoints_[i][j+1][k];
1205 cellsFromCell_[own].append(mf);
1206 cellsFromCell_[nei].append(help::reverseFace(mf));
1210 //- generate a face which might not be a quad
1213 mf.append(cellPoints_[nLayersI_-1][nLayersJ_-1][k]);
1215 //- this face might not be a quad
1216 //- add points from the last face in direction i
1217 const DynList<DynList<label> >& fp5 = facePoints_[5];
1218 for(label index=nLayersJ_-1;index<fp5.size()-1;++index)
1219 mf.append(fp5[index][k]);
1221 //- add points from the last face in direction j
1222 const DynList<DynList<label> >& fp3 = facePoints_[3];
1223 for(label index=fp3[k].size()-1;index>=nLayersI_-1;--index)
1224 mf.append(fp3[k][index]);
1228 (k-1) * nLayersI_ * nLayersJ_ +
1229 (nLayersJ_-1) * nLayersI_ +
1235 k * nLayersI_ * nLayersJ_ +
1236 (nLayersJ_-1) * nLayersI_ +
1241 Pout << "Additional face at position i = " << (nLayersI_-1)
1242 << " j = " << (nLayersJ_-1) << " k = " << k
1243 << " has owner " << own
1244 << " neighbour " << nei << " with nodes " << mf << endl;
1247 cellsFromCell_[own].append(mf);
1248 cellsFromCell_[nei].append(help::reverseFace(mf));
1252 Pout << "Generated cells " << cellsFromCell_ << endl;
1254 forAll(cellsFromCell_, cI)
1256 const DynList<DynList<label, 4>, 6>& cellFaces = cellsFromCell_[cI];
1258 DynList<edge, 12> edges;
1259 DynList<label, 12> nAppearances;
1261 forAll(cellFaces, fI)
1263 const DynList<label, 4>& f = cellFaces[fI];
1267 const edge e(f[eI], f.fcElement(eI));
1269 const label pos = edges.containsAtPosition(e);
1274 nAppearances.append(1);
1278 ++nAppearances[pos];
1283 forAll(nAppearances, eI)
1284 if( nAppearances[eI] != 2 )
1286 Pout << "Edge hex cell " << cI << " edge " << edges[eI]
1287 << " is present " << nAppearances[eI] << " times!" << endl;
1296 refineBoundaryLayers::refineCornerHexCell::refineCornerHexCell
1299 const refineBoundaryLayers& ref
1306 splitEdgeInDirection_(),
1314 determineFacesInDirections();
1316 populateExistingFaces();
1318 generateNewPoints();
1320 generateMissingFaces();
1323 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
1325 void refineBoundaryLayers::generateNewCells()
1327 labelList nCellsFromCell(mesh_.cells().size(), 1);
1328 labelList refType(mesh_.cells().size(), 0);
1330 const meshSurfaceEngine& mse = surfaceEngine();
1331 const labelList& faceOwners = mse.faceOwners();
1333 //- calculate the number new cells generated from a cell
1334 forAll(faceOwners, bfI)
1336 const label cellI = faceOwners[bfI];
1338 nCellsFromCell[cellI] *= nLayersAtBndFace_[bfI];
1340 if( nLayersAtBndFace_[bfI] > 1 )
1344 //- add cells which shall be refined in a subset
1345 if( cellSubsetName_ != "" )
1347 label subsetI = mesh_.cellSubsetIndex(cellSubsetName_);
1349 Warning << "The subset with name " << cellSubsetName_
1350 << " already exists. Skipping generation of a new subset"
1353 subsetI = mesh_.addCellSubset(cellSubsetName_);
1355 forAll(nCellsFromCell, cI)
1356 if( nCellsFromCell[cI] > 1 )
1357 mesh_.addCellToSubset(subsetI, cI);
1360 //- check the number of cells which will be generated
1362 forAll(nCellsFromCell, cellI)
1363 nNewCells += (nCellsFromCell[cellI] - 1);
1366 forAll(nCellsFromCell, cellI)
1368 Pout << "\nCell " << cellI << endl;
1369 Pout << "nCellsFromCell " << nCellsFromCell[cellI] << endl;
1370 Pout << "Ref type " << refType[cellI] << endl;
1374 const label totalNumNewCells = returnReduce(nNewCells, sumOp<label>());
1375 Info << "Number of newly generated cells " << totalNumNewCells << endl;
1377 //- create mesh modifier
1378 polyMeshGenModifier meshModifier(mesh_);
1379 faceListPMG& faces = meshModifier.facesAccess();
1381 const label numFacesBefore = newFaces_.size();
1383 //- set the number of cells to the new value
1384 cellListPMG& cells = meshModifier.cellsAccess();
1385 label nCells = cells.size();
1386 cells.setSize(nCells+nNewCells);
1388 //- start creating new cells
1389 //- store the information which new cells were generated from
1390 //- an existing cell
1391 VRWGraph newCellsFromCell(refType.size());
1393 VRWGraph pointNewFaces;
1394 pointNewFaces.reverseAddressing(newFaces_);
1396 forAll(nCellsFromCell, cellI)
1398 if( refType[cellI] == 0 )
1400 //- this cell is not refined
1401 //- update face labels
1402 newCellsFromCell.append(cellI, cellI);
1404 cell& c = cells[cellI];
1406 //- copy the new faces of this cell
1407 DynList<label, 64> newC;
1410 forAllRow(facesFromFace_, c[fI], cfI)
1411 newC.append(facesFromFace_(c[fI], cfI));
1415 c.setSize(newC.size());
1419 else if( refType[cellI] == 1 )
1421 //- generate new cells from this prism refined in one direction
1422 DynList<DynList<DynList<label, 8>, 10>, 64> cellsFromCell;
1423 generateNewCellsPrism(cellI, cellsFromCell);
1425 forAll(cellsFromCell, cI)
1427 const DynList<DynList<label, 8>, 10>& nc = cellsFromCell[cI];
1429 const label newCellI = cI==0?cellI:nCells++;
1431 newCellsFromCell.append(cellI, newCellI);
1433 cell& c = cells[newCellI];
1434 c.setSize(nc.size());
1436 //- find face labels for this cell
1439 const DynList<label, 8>& nf = nc[fI];
1441 label faceLabel(-1);
1442 forAllRow(pointNewFaces, nf[0], pfI)
1444 const label nfI = pointNewFaces(nf[0], pfI);
1446 if( help::areFacesEqual(nf, newFaces_[nfI]) )
1457 pointNewFaces.append(nf[pI], newFaces_.size());
1458 c[fI] = newFaces_.size();
1459 newFaces_.appendList(nf);
1464 else if( refType[cellI] == 2 )
1466 //- generate new cell from a hex cell where two layers intersect
1467 //- generate mostly hex cells;
1468 refineEdgeHexCell refEdgeHex(cellI, *this);
1469 const DynList<DynList<DynList<label, 4>, 6>, 256>& cellsFromCell =
1470 refEdgeHex.newCells();
1472 forAll(cellsFromCell, cI)
1474 const DynList<DynList<label, 4>, 6>& nc = cellsFromCell[cI];
1477 Pout << "Adding cell " << (cI==0?cellI:nCells)
1478 << " originating from cell " << cellI << endl;
1481 const label newCellI = cI==0?cellI:nCells++;
1483 newCellsFromCell.append(cellI, newCellI);
1485 cell& c = cells[newCellI];
1486 c.setSize(nc.size());
1488 //- find face labels for this cell
1491 const DynList<label, 4>& nf = nc[fI];
1493 label faceLabel(-1);
1494 forAllRow(pointNewFaces, nf[0], pfI)
1496 const label nfI = pointNewFaces(nf[0], pfI);
1498 if( help::areFacesEqual(nf, newFaces_[nfI]) )
1509 pointNewFaces.append(nf[pI], newFaces_.size());
1510 c[fI] = newFaces_.size();
1511 newFaces_.appendList(nf);
1516 else if( refType[cellI] == 3 )
1518 //- generate new cells from a hex at a corner where three
1519 //- layers intersect
1520 //- generate mostly hex cells
1521 refineCornerHexCell refCell(cellI, *this);
1522 const DynList<DynList<DynList<label, 4>, 6>, 256>& cellsFromCell =
1525 //- new points have been generated
1526 pointNewFaces.setSize(mesh_.points().size());
1528 //- recognise face cells in the graph of new faces
1529 forAll(cellsFromCell, cI)
1531 const DynList<DynList<label, 4>, 6>& nc = cellsFromCell[cI];
1533 const label newCellI = cI==0?cellI:nCells++;
1535 newCellsFromCell.append(cellI, newCellI);
1537 cell& c = cells[newCellI];
1538 c.setSize(nc.size());
1540 //- find face labels for this cell
1543 const DynList<label, 4>& nf = nc[fI];
1545 label faceLabel(-1);
1546 forAllRow(pointNewFaces, nf[0], pfI)
1548 const label nfI = pointNewFaces(nf[0], pfI);
1550 if( help::areFacesEqual(nf, newFaces_[nfI]) )
1561 pointNewFaces.append(nf[pI], newFaces_.size());
1562 c[fI] = newFaces_.size();
1563 newFaces_.appendList(nf);
1572 "void refineBoundaryLayers::generateNewCells()"
1573 ) << "Cannot refine boundary layer for cell "
1574 << cellI << abort(FatalError);
1578 //- check the orientation of new faces, because owner and neighbour cells
1579 //- may require a face to be flipped
1580 const label nOrigInternalFaces = mesh_.nInternalFaces();
1583 # pragma omp parallel
1586 const labelList& owner = mesh_.owner();
1587 const labelList& neighbour = mesh_.neighbour();
1590 # pragma omp for schedule(dynamic, 40)
1592 for(label fI=0;fI<nOrigInternalFaces;++fI)
1594 const label own = owner[fI];
1595 const label nei = neighbour[fI];
1597 if( facesFromFace_.sizeOfRow(fI) == 1 )
1600 forAllRow(facesFromFace_, fI, cfI)
1602 const label nfI = facesFromFace_(fI, cfI);
1604 //- find the new owner and neighbour cells of the new face
1605 label newOwner(-1), newNeighbour(-1);
1606 forAllRow(newCellsFromCell, own, cI)
1608 const cell& cOwn = cells[newCellsFromCell(own, cI)];
1610 const label pos = help::positionInList(nfI, cOwn);
1614 newOwner = newCellsFromCell(own, cI);
1619 forAllRow(newCellsFromCell, nei, cI)
1621 const cell& cNei = cells[newCellsFromCell(nei, cI)];
1623 const label pos = help::positionInList(nfI, cNei);
1627 newNeighbour = newCellsFromCell(nei, cI);
1632 if( newOwner > newNeighbour )
1635 rf.setSize(newFaces_.sizeOfRow(nfI));
1638 rf[i] = newFaces_(nfI, i);
1640 rf = help::reverseFace(rf);
1642 newFaces_.setRow(nfI, rf);
1648 //- update cell sets
1649 mesh_.updateCellSubsets(newCellsFromCell);
1650 newCellsFromCell.setSize(0);
1652 //- point-faces addressing is not needed any more
1653 pointNewFaces.setSize(0);
1655 //- copy newFaces to the mesh
1657 Pout << "Copying internal faces " << endl;
1658 Pout << "Original number of internal faces " << nOrigInternalFaces << endl;
1661 //- store internal faces originating from existing faces
1662 labelLongList newFaceLabel(newFaces_.size());
1663 faces.setSize(newFaces_.size());
1666 for(label faceI=0;faceI<nOrigInternalFaces;++faceI)
1668 forAllRow(facesFromFace_, faceI, ffI)
1670 face& f = faces[currFace];
1671 newFaceLabel[currFace] = currFace;
1674 const label newFaceI = facesFromFace_(faceI, ffI);
1676 f.setSize(newFaces_.sizeOfRow(newFaceI));
1679 f[pI] = newFaces_(newFaceI, pI);
1683 //- store newly-generated internal faces
1685 Pout << "Copying newly generated internal faces" << endl;
1686 Pout << "nNewInternalFaces " << currFace << endl;
1687 Pout << "numFacesBefore " << numFacesBefore << endl;
1688 Pout << "Total number of faces " << newFaces_.size() << endl;
1691 for(label faceI=numFacesBefore;faceI<newFaces_.size();++faceI)
1693 newFaceLabel[faceI] = currFace;
1694 face& f = faces[currFace];
1697 f.setSize(newFaces_.sizeOfRow(faceI));
1700 f[pI] = newFaces_(faceI, pI);
1703 //- store new boundary faces
1705 Pout << "Copying boundary faces " << endl;
1706 Pout << "currFace " << currFace << endl;
1707 Pout << "Faces size " << faces.size() << endl;
1708 Pout << "Initial number of faces " << facesFromFace_.size() << endl;
1711 PtrList<boundaryPatch>& boundaries = meshModifier.boundariesAccess();
1712 forAll(boundaries, patchI)
1714 const label start = boundaries[patchI].patchStart();
1715 const label size = boundaries[patchI].patchSize();
1717 const label newStart = currFace;
1718 label nNewFacesInPatch(0);
1719 for(label fI=0;fI<size;++fI)
1721 const label faceI = start + fI;
1723 forAllRow(facesFromFace_, faceI, nfI)
1725 face& f = faces[currFace];
1727 //- update the new label
1728 const label origFaceI = facesFromFace_(faceI, nfI);
1729 newFaceLabel[origFaceI] = currFace;
1730 facesFromFace_(faceI, nfI) = currFace;
1733 //- copy the face into the mesh
1734 f.setSize(newFaces_.sizeOfRow(origFaceI));
1736 f[pI] = newFaces_(origFaceI, pI);
1743 boundaries[patchI].patchStart() = newStart;
1744 boundaries[patchI].patchSize() = nNewFacesInPatch;
1747 if( Pstream::parRun() )
1750 Pout << "Copying processor faces" << endl;
1753 //- copy faces at inter-processor boundaries
1754 PtrList<processorBoundaryPatch>& procBoundaries =
1755 meshModifier.procBoundariesAccess();
1757 forAll(procBoundaries, patchI)
1759 const label start = procBoundaries[patchI].patchStart();
1760 const label size = procBoundaries[patchI].patchSize();
1762 const label newStart = currFace;
1763 label nNewFacesInPatch(0);
1764 for(label fI=0;fI<size;++fI)
1766 const label faceI = start + fI;
1767 forAllRow(facesFromFace_, faceI, nfI)
1769 face& f = faces[currFace];
1771 //- update the new label
1772 const label origFaceI = facesFromFace_(faceI, nfI);
1773 newFaceLabel[origFaceI] = currFace;
1774 facesFromFace_(faceI, nfI) = currFace;
1777 //- copy the face into the mesh
1778 f.setSize(newFaces_.sizeOfRow(origFaceI));
1780 f[pI] = newFaces_(origFaceI, pI);
1787 procBoundaries[patchI].patchStart() = newStart;
1788 procBoundaries[patchI].patchSize() = nNewFacesInPatch;
1793 Pout << "Faces after refinement " << faces << endl;
1794 Pout << "newFaceLabel " << newFaceLabel << endl;
1797 //- update face subsets
1798 mesh_.updateFaceSubsets(facesFromFace_);
1799 facesFromFace_.setSize(0);
1800 newFaces_.setSize(0);
1802 //- update cells to match the faces
1804 Pout << "Updating cells to match new faces" << endl;
1807 forAll(cells, cellI)
1809 cell& c = cells[cellI];
1812 c[fI] = newFaceLabel[c[fI]];
1816 Pout << "Cleaning mesh " << endl;
1819 //- delete all adressing which is no longer up-to-date
1820 meshModifier.clearAll();
1821 deleteDemandDrivenData(msePtr_);
1824 for(label procI=0;procI<Pstream::nProcs();++procI)
1826 if( procI == Pstream::myProcNo() )
1828 forAll(cells, cellI)
1830 const cell& c = cells[cellI];
1832 DynList<edge> edges;
1833 DynList<label> nAppearances;
1836 const face& f = faces[c[fI]];
1840 const edge e = f.faceEdge(eI);
1842 const label pos = edges.containsAtPosition(e);
1847 nAppearances.append(1);
1851 ++nAppearances[pos];
1856 bool badCell(false);
1857 forAll(nAppearances, i)
1858 if( nAppearances[i] != 2 )
1867 Pout << "Cell " << cellI
1868 << " is not topologically closed" << endl;
1871 Pout << "Face " << c[fI] << " with points "
1872 << faces[c[fI]] << endl;
1873 Pout << "Cell edges " << edges << endl;
1874 Pout << "nAppearances " << nAppearances << endl;
1880 returnReduce(1, sumOp<label>());
1883 const labelList& owner = mesh_.owner();
1884 const labelList& neighbour = mesh_.neighbour();
1885 const label nInternalFaces = mesh_.nInternalFaces();
1887 for(label procI=0;procI<Pstream::nProcs();++procI)
1889 if( procI == Pstream::myProcNo() )
1891 forAll(faces, faceI)
1893 if( faceI < nInternalFaces && neighbour[faceI] < 0 )
1895 Pout << "Num interface faces " << nInternalFaces
1896 << " current face " << faceI
1897 << " face points " << faces[faceI] << endl;
1900 Pout << "Face " << faceI << " owner " << owner[faceI]
1901 << " neighbour " << neighbour[faceI]
1902 << " face points " << faces[faceI] << endl;
1905 forAll(cells, cellI)
1906 Pout << "Cell " << cellI << " has faces "
1907 << cells[cellI] << endl;
1910 returnReduce(procI, maxOp<label>());
1914 Info << "Finished generating new cells " << endl;
1917 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
1919 } // End namespace Foam
1921 // ************************************************************************* //