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 "demandDrivenData.H"
31 #include "FixedList.H"
32 #include "helperFunctions.H"
40 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
45 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
47 void refineBoundaryLayers::refineFace
50 const FixedList<label, 2>& nLayersInDirection,
51 DynList<DynList<label, 4>, 128>& newFaces
54 //- this face must be a quad
59 "void refineBoundaryLayers::refineFace(const face&,"
60 " const FixedList<label, 2>&, DynList<DynList<label, 4> >&)"
61 ) << "Face " << f << " is not a quad" << endl;
65 //- direction 0 represents edges 0 and 2
66 //- direction 1 represents edges 1 and 3
67 if( (nLayersInDirection[0] <= 1) && (nLayersInDirection[1] <= 1) )
69 //- this face may comprise of some split edges
70 DynList<label, 64> newF;
73 const edge e = f.faceEdge(eI);
75 //- add the current point label
78 //- check if a split edge matches this face edge
79 forAllRow(splitEdgesAtPoint_, f[eI], peI)
81 const label seI = splitEdgesAtPoint_(f[eI], peI);
82 const edge& se = splitEdges_[seI];
86 //- check the orientation and add new vertices created
88 const label s = newVerticesForSplitEdge_.sizeOfRow(seI) - 1;
89 if( e.start() == se.start() )
91 for(label pI=1;pI<s;++pI)
92 newF.append(newVerticesForSplitEdge_(seI, pI));
96 for(label pI=s-1;pI>0;--pI)
97 newF.append(newVerticesForSplitEdge_(seI, pI));
108 //- check which face edge is a direction 0 and which one is a direction 1
109 label dir0(-1), dir1(-1);
110 labelPair dir0Edges(-1, -1), dir1Edges(-1, -1);
113 const edge e = f.faceEdge(eI);
115 label ses(-1), see(-1);
116 bool start(false), end(false);
117 forAllRow(splitEdgesAtPoint_, e.start(), i)
119 const edge& se = splitEdges_[splitEdgesAtPoint_(e.start(), i)];
121 if( (se.start() == e.start()) && (se.end() == f.prevLabel(eI)) )
123 ses = splitEdgesAtPoint_(e.start(), i);
129 forAllRow(splitEdgesAtPoint_, e.end(), i)
131 const edge& se = splitEdges_[splitEdgesAtPoint_(e.end(), i)];
133 if( (se.start() == e.end()) && (se.end() == f[(eI+2)%4]) )
135 see = splitEdgesAtPoint_(e.end(), i);
146 dir0Edges = labelPair(ses, see);
148 else if( dir1 == -1 )
151 dir1Edges = labelPair(ses, see);
157 "void refineBoundaryLayers::refineFace(const face&,"
158 " const FixedList<label, 2>&, DynList<DynList<label, 4> >&)"
159 ) << "More than two split directions for a face"
160 << abort(FatalError);
166 Pout << "Refining face " << f << endl;
167 Pout << "Splits in direction " << nLayersInDirection << endl;
168 Pout << "Here " << endl;
169 Pout << "Dir0 " << dir0 << endl;
170 Pout << "dir0Edges " << dir0Edges << endl;
171 Pout << "Dir1 " << dir1 << endl;
172 Pout << "dir1Edges " << dir1Edges << endl;
175 if( (dir0 < 0) && (dir1 < 0) )
177 Pout << "Refining face " << f << endl;
180 if( splitEdgesAtPoint_.size() >= f[pI] )
181 Pout << "Split edges at point " << f[pI]
182 << " are " << splitEdgesAtPoint_[f[pI]] << endl;
184 Pout << "Splits in direction " << nLayersInDirection << endl;
185 Pout << "Here " << endl;
186 Pout << "Dir0 " << dir0 << endl;
187 Pout << "dir0Edges " << dir0Edges << endl;
188 Pout << "Dir1 " << dir1 << endl;
189 Pout << "dir1Edges " << dir1Edges << endl;
193 "void refineBoundaryLayers::refineFace(const face&,"
194 " const FixedList<label, 2>&, DynList<DynList<label, 4> >&)"
195 ) << "Cannot find split edges for a face" << abort(FatalError);
198 //- in case of only one refinement direction, it must direction 0
199 if( (dir1 != -1) && (dir0 == -1) )
202 dir0Edges = dir1Edges;
205 else if( (dir0 != -1) && (dir1 != -1) && (dir1 != f.fcIndex(dir0)) )
207 //- alternate value to preserve correct face orientation
208 const label add = dir0;
212 const labelPair lpAdd = dir0Edges;
213 dir0Edges = dir1Edges;
217 //- permutate the number of refinements in each direction
218 const label nLayersDir0 = dir0>=0?nLayersInDirection[dir0%2]:1;
219 const label nLayersDir1 = dir1>=0?nLayersInDirection[dir1%2]:1;
222 Pout << "Face has points " << f << endl;
223 Pout << "dirEdges0 " << dir0Edges << endl;
224 Pout << "dir1Edges " << dir1Edges << endl;
227 Pout << "Points on edge " << dir0Edges.first() << " with nodes "
228 << splitEdges_[dir0Edges.first()]
229 << " are " << newVerticesForSplitEdge_[dir0Edges.first()] << endl;
230 Pout << "Points on edge " << dir0Edges.second() << " with nodes "
231 << splitEdges_[dir0Edges.second()]
232 << " are " << newVerticesForSplitEdge_[dir0Edges.second()] << endl;
236 Pout << "Points on edge " << dir1Edges.first() << " with nodes "
237 << splitEdges_[dir1Edges.first()]
238 << " are " << newVerticesForSplitEdge_[dir1Edges.first()] << endl;
239 Pout << "Points on edge " << dir1Edges.second() << " with nodes "
240 << splitEdges_[dir1Edges.second()]
241 << " are " << newVerticesForSplitEdge_[dir1Edges.second()] << endl;
243 Pout << "nLayersDir0 " << nLayersDir0 << endl;
244 Pout << "nLayersDir1 " << nLayersDir1 << endl;
247 //- map the face onto a matrix for easier orientation
248 DynList<DynList<label> > facePoints;
249 facePoints.setSize(nLayersDir0+1);
250 forAll(facePoints, i)
252 facePoints[i].setSize(nLayersDir1+1);
256 //- add points in the matrix
257 for(label i=0;i<nLayersDir0;++i)
259 facePoints[i][0] = newVerticesForSplitEdge_(dir0Edges.second(), i);
260 facePoints[i][nLayersDir1] =
261 newVerticesForSplitEdge_(dir0Edges.first(), i);
263 facePoints[nLayersDir0][0] = splitEdges_[dir0Edges.second()].end();
264 facePoints[nLayersDir0][nLayersDir1] = splitEdges_[dir0Edges.first()].end();
266 for(label i=1;i<nLayersDir1;++i)
268 facePoints[0][i] = newVerticesForSplitEdge_(dir1Edges.first(), i);
269 facePoints[nLayersDir0][i] =
270 newVerticesForSplitEdge_(dir1Edges.second(), i);
273 //- create missing vertices if there are any
274 pointFieldPMG& points = mesh_.points();
275 const point v00 = points[facePoints[0][0]];
276 const point v10 = points[facePoints[nLayersDir0][0]];
277 const point v01 = points[facePoints[0][nLayersDir1]];
278 const point v11 = points[facePoints[nLayersDir0][nLayersDir1]];
281 forAll(points, pointI)
282 Pout << "Point " << pointI << " coordinates " << points[pointI] << endl;
283 Pout << "v00 = " << v00 << endl;
284 Pout << "v10 = " << v10 << endl;
285 Pout << "v11 = " << v11 << endl;
286 Pout << "v01 = " << v01 << endl;
289 forAll(facePoints, i)
291 forAll(facePoints[i], j)
293 if( facePoints[i][j] < 0 )
296 Pout << "Determining u " << facePoints[0][0]
297 << " coordinates " << points[facePoints[0][0]] << endl;
298 Pout << "Other point " << facePoints[i][0]
299 << " coordinates " << points[facePoints[i][0]] << endl;
300 Pout << "Points at aplit edge "
301 << newVerticesForSplitEdge_[dir0Edges.second()] << endl;
306 Foam::mag(points[facePoints[i][0]] - v00) /
307 splitEdges_[dir0Edges.second()].mag(points)
311 Pout << "Determining v " << facePoints[0][0]
312 << " coordinates " << points[facePoints[0][0]] << endl;
313 Pout << "Other point " << facePoints[0][j]
314 << " coordinates " << points[facePoints[0][j]] << endl;
315 Pout << "Points at aplit edge "
316 << newVerticesForSplitEdge_[dir1Edges.first()] << endl;
321 Foam::mag(points[facePoints[0][j]] - v00) /
322 splitEdges_[dir1Edges.first()].mag(points)
326 Pout << "Generating point of face " << endl;
327 Pout << "u = " << u << endl;
328 Pout << "v = " << v << endl;
331 //- calculate the coordinates of the missing point via
332 //- transfinite interpolation
335 (1.0 - u) * (1.0 - v) * v00 +
336 u * (1.0 - v) * v10 +
342 Pout << "Point coordinate " << newP << endl;
345 //- add the vertex to the mesh
346 facePoints[i][j] = points.size();
353 Pout << "Face points after creating vertices " << facePoints << endl;
356 //- Finally, create the faces
357 for(label j=0;j<nLayersDir1;++j)
359 for(label i=0;i<nLayersDir0;++i)
364 f.append(facePoints[i][j]);
366 if( (i == (nLayersDir0 - 1)) && (j == 0) )
369 Pout << "1. Adding additional points on edge " << endl;
372 //- add additional points on edge
373 const label eLabel = dir0Edges.second();
375 newVerticesForSplitEdge_.sizeOfRow(eLabel) - 1;
377 for(label index=i+1;index<size;++index)
378 f.append(newVerticesForSplitEdge_(eLabel, index));
381 f.append(facePoints[i+1][j]);
385 (i == (nLayersDir0 - 1)) &&
386 (j == (nLayersDir1 - 1))
390 Pout << "2. Adding additional points on edge " << endl;
393 //- add additional points on edge
394 const label eLabel = dir1Edges.second();
396 newVerticesForSplitEdge_.sizeOfRow(eLabel) - 1;
398 for(label index=j+1;index<size;++index)
399 f.append(newVerticesForSplitEdge_(eLabel, index));
402 f.append(facePoints[i+1][j+1]);
404 if( (i == (nLayersDir0 - 1)) && (j == (nLayersDir1 - 1)) )
407 Pout << "3. Adding additional points on edge " << endl;
410 const label eLabel = dir0Edges.first();
412 newVerticesForSplitEdge_.sizeOfRow(eLabel) - 2;
413 for(label index=size;index>i;--index)
414 f.append(newVerticesForSplitEdge_(eLabel, index));
417 f.append(facePoints[i][j+1]);
419 if( (dir1 != -1) && (i == 0) && (j == (nLayersDir1 - 1)) )
422 Pout << "4. Adding additional points on edge " << endl;
425 const label eLabel = dir1Edges.first();
427 newVerticesForSplitEdge_.sizeOfRow(eLabel) - 2;
428 for(label index=size;index>j;--index)
429 f.append(newVerticesForSplitEdge_(eLabel, index));
437 Pout << "Input face " << f << endl;
438 Pout << "Decomposed faces are " << newFaces << endl;
439 //if( (nLayersInDirection[0] > 1) && (nLayersInDirection[1] > 1) )
444 void refineBoundaryLayers::sortFacePoints
447 DynList<DynList<label> >& facePoints,
448 const label transpose
451 const faceListPMG& faces = mesh_.faces();
452 const face& f = faces[faceI];
455 Pout << "Creating matrix of points on a split face " << faceI << endl;
456 Pout << "Face comprises of points " << f << endl;
457 Pout << "New faces from face " << facesFromFace_.sizeOfRow(faceI) << endl;
460 label procStart = mesh_.faces().size();
461 const PtrList<processorBoundaryPatch>& procBoundaries = mesh_.procBoundaries();
462 if( Pstream::parRun() )
463 procStart = procBoundaries[0].patchStart();
466 (faceI < procStart) ||
467 procBoundaries[mesh_.faceIsInProcPatch(faceI)].owner()
470 //- orientation of new faces is the same as the face itself
471 //- start the procedure by finding the number of splits in
472 //- both i and j direction
475 const label pos = f.which(newFaces_(facesFromFace_(faceI, 0), 0));
477 forAllRow(facesFromFace_, faceI, i)
479 const label nfI = facesFromFace_(faceI, i);
481 if( (numSplitsI == 1) && newFaces_.contains(nfI, f.nextLabel(pos)) )
488 const label numSplitsJ = (facesFromFace_.sizeOfRow(faceI) / numSplitsI);
491 Pout << "Pos " << pos << endl;
492 Pout << "Num splits in direction 0 " << numSplitsI << endl;
493 Pout << "Num splits in direction 1 " << numSplitsJ << endl;
496 facePoints.setSize(numSplitsI+1);
497 forAll(facePoints, i)
498 facePoints[i].setSize(numSplitsJ+1);
500 //- start filling in the matrix
501 forAllRow(facesFromFace_, faceI, fI)
503 const label nfI = facesFromFace_(faceI, fI);
505 const label i = fI % numSplitsI;
506 const label j = fI / numSplitsI;
509 Pout << "New face " << fI << " is " << newFaces_[nfI] << endl;
510 Pout << " i = " << i << endl;
511 Pout << " j = " << j << endl;
514 if( newFaces_.sizeOfRow(nfI) == 4 )
516 facePoints[i][j] = newFaces_(nfI, 0);
517 facePoints[i+1][j] = newFaces_(nfI, 1);
518 facePoints[i+1][j+1] = newFaces_(nfI, 2);
519 facePoints[i][j+1] = newFaces_(nfI, 3);
525 forAllRow(newFaces_, nfI, pI)
526 if( f.which(newFaces_(nfI, pI)) >= 0 )
528 facePoints[i+1][0] = newFaces_(nfI, pI);
534 forAllRow(newFaces_, nfI, pI)
535 if( f.which(newFaces_(nfI, pI)) >= 0 )
537 facePoints[0][j+1] = newFaces_(nfI, pI);
543 forAllRow(newFaces_, nfI, pI)
544 if( f.which(newFaces_(nfI, pI)) >= 0 )
546 facePoints[i+1][j+1] = newFaces_(nfI, pI);
554 Pout << "Generated matrix of points on face " << faceI
555 << " is " << facePoints << endl;
560 //- this situation exists on inter-processor boundaries
561 //- on neighbour processor. i and j coordinates are reversed
564 const label pos = f.which(newFaces_(facesFromFace_(faceI, 0), 0));
566 forAllRow(facesFromFace_, faceI, j)
568 const label nfI = facesFromFace_(faceI, j);
570 if( (numSplitsJ == 1) && newFaces_.contains(nfI, f.prevLabel(pos)) )
577 const label numSplitsI = (facesFromFace_.sizeOfRow(faceI) / numSplitsJ);
580 Pout << "2. Face comprises of points " << f << endl;
581 Pout << "2. Num splits in direction 0 " << numSplitsI << endl;
582 Pout << "2. Num splits in direction 1 " << numSplitsJ << endl;
585 facePoints.setSize(numSplitsI+1);
586 forAll(facePoints, i)
587 facePoints[i].setSize(numSplitsJ+1);
589 //- start filling in the matrix
590 forAllRow(facesFromFace_, faceI, fI)
592 const label nfI = facesFromFace_(faceI, fI);
594 const label i = fI / numSplitsJ;
595 const label j = fI % numSplitsJ;
598 Pout << "2. New face " << fI << " is " << newFaces_[nfI] << endl;
599 Pout << "2. i = " << i << endl;
600 Pout << "2. j = " << j << endl;
603 if( newFaces_.sizeOfRow(nfI) == 4 )
605 facePoints[i][j] = newFaces_(nfI, 0);
606 facePoints[i+1][j] = newFaces_(nfI, 1);
607 facePoints[i+1][j+1] = newFaces_(nfI, 2);
608 facePoints[i][j+1] = newFaces_(nfI, 3);
614 forAllRow(newFaces_, nfI, pI)
615 if( f.which(newFaces_(nfI, pI)) >= 0 )
617 facePoints[0][j+1] = newFaces_(nfI, pI);
623 forAllRow(newFaces_, nfI, pI)
624 if( f.which(newFaces_(nfI, pI)) >= 0 )
626 facePoints[i+1][0] = newFaces_(nfI, pI);
632 forAllRow(newFaces_, nfI, pI)
633 if( f.which(newFaces_(nfI, pI)) >= 0 )
635 facePoints[i+1][j+1] = newFaces_(nfI, pI);
643 Pout << "Generated matrix of points on processor face " << faceI
644 << " is " << facePoints << endl;
650 DynList<DynList<label> > transposedFacePoints;
651 transposedFacePoints.setSize(facePoints[0].size());
652 forAll(transposedFacePoints, j)
653 transposedFacePoints[j].setSize(facePoints.size());
655 forAll(facePoints, i)
656 forAll(facePoints[i], j)
657 transposedFacePoints[j][i] = facePoints[i][j];
659 facePoints = transposedFacePoints;
662 Pout << "Transposed face points " << facePoints << endl;
667 void refineBoundaryLayers::sortFaceFaces
670 DynList<DynList<label> >& faceFaces,
671 const label transpose
674 const faceListPMG& faces = mesh_.faces();
675 const face& f = faces[faceI];
678 Pout << "Creating matrix of faces on a split face " << faceI << endl;
679 Pout << "Face comprises of points " << f << endl;
682 label procStart = mesh_.faces().size();
683 const PtrList<processorBoundaryPatch>& procBoundaries = mesh_.procBoundaries();
684 if( Pstream::parRun() )
685 procStart = procBoundaries[0].patchStart();
688 (faceI < procStart) ||
689 procBoundaries[mesh_.faceIsInProcPatch(faceI)].owner()
692 //- orientation of new faces is the same as the face itself
693 //- start the procedure by finding the number of splits in
694 //- both i and j direction
697 const label pos = f.which(newFaces_(facesFromFace_(faceI, 0), 0));
699 forAllRow(facesFromFace_, faceI, i)
701 const label nfI = facesFromFace_(faceI, i);
703 if( (numSplitsI == 1) && newFaces_.contains(nfI, f.nextLabel(pos)) )
710 label numSplitsJ = (facesFromFace_.sizeOfRow(faceI) / numSplitsI);
713 Pout << "3. Num splits in direction 0 " << numSplitsI << endl;
714 Pout << "3. Num splits in direction 1 " << numSplitsJ << endl;
717 faceFaces.setSize(numSplitsI);
719 faceFaces[i].setSize(numSplitsJ);
721 //- start filling in the matrix
722 forAllRow(facesFromFace_, faceI, fI)
724 const label nfI = facesFromFace_(faceI, fI);
726 const label i = fI % numSplitsI;
727 const label j = fI / numSplitsI;
730 Pout << "3. New face " << fI << " is " << newFaces_[nfI] << endl;
731 Pout << "3. i = " << i << endl;
732 Pout << "3. j = " << j << endl;
735 faceFaces[i][j] = nfI;
739 Pout << "3. Generated matrix of points on face " << faceI
740 << " is " << faceFaces << endl;
745 //- this situation exists on inter-processor boundaries
746 //- on neighbour processor. i and j coordinates are reversed
749 const label pos = f.which(newFaces_(facesFromFace_(faceI, 0), 0));
751 forAllRow(facesFromFace_, faceI, j)
753 const label nfI = facesFromFace_(faceI, j);
755 if( (numSplitsJ == 1) && newFaces_.contains(nfI, f.prevLabel(pos)) )
762 const label numSplitsI = (facesFromFace_.sizeOfRow(faceI) / numSplitsJ);
765 Pout << "4. Num splits in direction 0 " << numSplitsI << endl;
766 Pout << "4. Num splits in direction 1 " << numSplitsJ << endl;
769 faceFaces.setSize(numSplitsI);
771 faceFaces[i].setSize(numSplitsJ);
773 //- start filling in the matrix
774 forAllRow(facesFromFace_, faceI, fI)
776 const label nfI = facesFromFace_(faceI, fI);
778 const label i = fI / numSplitsJ;
779 const label j = fI % numSplitsJ;
782 Pout << "4. New face " << fI << " is " << newFaces_[nfI] << endl;
783 Pout << "4. i = " << i << endl;
784 Pout << "4. j = " << j << endl;
787 faceFaces[i][j] = nfI;
791 Pout << "4. Generated matrix of faces on processor face " << faceI
792 << " is " << faceFaces << endl;
798 DynList<DynList<label> > transposedFaceFaces;
799 transposedFaceFaces.setSize(faceFaces[0].size());
800 forAll(transposedFaceFaces, j)
801 transposedFaceFaces[j].setSize(faceFaces.size());
804 forAll(faceFaces[i], j)
805 transposedFaceFaces[j][i] = faceFaces[i][j];
807 faceFaces = transposedFaceFaces;
810 Pout << "Transposed face faces " << faceFaces << endl;
815 void refineBoundaryLayers::generateNewFaces()
817 //- generate new boundary and inter-processor faces
818 const meshSurfaceEngine& mse = surfaceEngine();
819 const faceList::subList& bFaces = mse.boundaryFaces();
820 const labelList& facePatches = mse.boundaryFacePatches();
821 const edgeList& edges = mse.edges();
822 const labelList& bp = mse.bp();
823 const VRWGraph& bfEdges = mse.faceEdges();
824 const VRWGraph& bpEdges = mse.boundaryPointEdges();
825 const VRWGraph& beFaces = mse.edgeFaces();
828 const label nInternalFaces = mesh_.nInternalFaces();
829 const faceListPMG& faces = mesh_.faces();
831 //- container for faces
832 facesFromFace_.setSize(faces.size());
835 //- split internal faces
836 for(label faceI=0;faceI<nInternalFaces;++faceI)
838 const face& f = faces[faceI];
840 //- only quad faces can be split
843 facesFromFace_.append(faceI, newFaces_.size());
844 newFaces_.appendList(f);
848 //- check if there exist an edge of the face at the boundary
849 FixedList<label, 2> nRefinementInDirection(1);
853 const edge fe = f.faceEdge(eI);
855 const label bps = bp[fe.start()];
860 forAllRow(bpEdges, bps, bpsI)
862 const label beI = bpEdges(bps, bpsI);
864 if( edges[beI] == fe )
866 //- this edge is attached to the boundary
867 //- get the number of layers for neighbouring cells
868 const label nSplits0 = nLayersAtBndFace_[beFaces(beI, 0)];
869 const label nSplits1 = nLayersAtBndFace_[beFaces(beI, 1)];
871 //- set the number of layers for the given direction
872 const label dir = eI % 2;
873 nRefinementInDirection[dir] =
876 nRefinementInDirection[dir],
877 Foam::max(nSplits0, nSplits1)
884 DynList<DynList<label, 4>, 128> newFacesForFace;
885 refineFace(f, nRefinementInDirection, newFacesForFace);
887 //- store decomposed faces
888 forAll(newFacesForFace, fI)
890 facesFromFace_.append(faceI, newFaces_.size());
891 newFaces_.appendList(newFacesForFace[fI]);
895 Pout << "Internal face " << faceI << " with points " << f
896 << " is refined " << endl;
897 forAllRow(facesFromFace_, faceI, i)
898 Pout << "New face " << i << " is "
899 << newFaces_[facesFromFace_(faceI, i)] << endl;
900 DynList<DynList<label> > tralala;
901 sortFacePoints(faceI, tralala);
905 //- refine boundary faces where needed
906 //- it is required in locations where two or three layers intersect
907 const label startingBoundaryFace = mesh_.boundaries()[0].patchStart();
910 const face& bf = bFaces[bfI];
911 const label faceI = startingBoundaryFace + bfI;
913 //- only quad faces can be split
916 facesFromFace_.append(faceI, newFaces_.size());
917 newFaces_.appendList(bf);
921 //- check whether this face shall be refined and in which directions
922 FixedList<label, 2> nRefinementInDirection(1);
926 const label beI = bfEdges(bfI, eI);
928 if( beFaces.sizeOfRow(beI) != 2 )
931 //- get the neighbour face over the edge
932 label neiFace = beFaces(beI, 0);
935 neiFace = beFaces(beI, 1);
937 //- faces cannot be in the same layer
938 const DynList<label>& neiLayers =
939 layerAtPatch_[facePatches[neiFace]];
941 if( neiLayers.size() == 0 )
944 const DynList<label>& currLayers = layerAtPatch_[facePatches[bfI]];
946 bool foundSame(false);
948 forAll(currLayers, i)
950 if( neiLayers.contains(currLayers[i]) )
957 if( foundSame || (neiLayers.size() == 0) )
960 //- set the refinement direction for this face
961 nRefinementInDirection[eI%2] = nLayersAtBndFace_[neiFace];
965 DynList<DynList<label, 4>, 128> newFacesForFace;
966 refineFace(bf, nRefinementInDirection, newFacesForFace);
968 //- store the refined faces
969 forAll(newFacesForFace, fI)
971 facesFromFace_.append(faceI, newFaces_.size());
972 newFaces_.appendList(newFacesForFace[fI]);
976 Pout << "Boundary face " << faceI << " with points " << bf
977 << " owner cell " << mesh_.owner()[faceI] << " is refined " << endl;
978 forAllRow(facesFromFace_, faceI, i)
979 Pout << "New face " << i << " is "
980 << newFaces_[facesFromFace_(faceI, i)] << endl;
984 if( Pstream::parRun() )
986 //- refine faces at interprocessor boundaries
987 const PtrList<processorBoundaryPatch>& procBoundaries =
988 mesh_.procBoundaries();
990 //- exchange information about the number of splits
991 //- to other processors
992 std::map<label, DynList<labelPair, 2> > localSplits;
993 forAll(procBoundaries, patchI)
995 labelLongList sendData;
997 const label start = procBoundaries[patchI].patchStart();
998 const label size = procBoundaries[patchI].patchSize();
1000 for(label fI=0;fI<size;++fI)
1002 const label faceI = start + fI;
1003 const face& f = faces[faceI];
1007 const edge fe = f.faceEdge(eI);
1009 const label bps = bp[fe.start()];
1014 forAllRow(bpEdges, bps, bpeI)
1016 const label beI = bpEdges(bps, bpeI);
1018 if( edges[beI] == fe )
1020 //- this edge is attached to the boundary
1021 //- get the number of layers for neighbouring cell
1022 const label nSplits0 =
1023 nLayersAtBndFace_[beFaces(beI, 0)];
1025 //- add the data to the list for sending
1026 const label dir = (eI % 2);
1029 Pout << "Face " << fI << " owner of proc patch "
1030 << procBoundaries[patchI].myProcNo()
1032 << procBoundaries[patchI].neiProcNo()
1033 << " bnd face patch "
1034 << facePatches[beFaces(beI, 0)]
1035 << " direction " << dir
1036 << " nSplits " << nSplits0 << endl;
1039 //- add face label, direction
1040 //- and the number of splits
1041 sendData.append(fI);
1042 sendData.append(dir);
1043 sendData.append(nSplits0);
1044 localSplits[faceI].append(labelPair(dir, nSplits0));
1050 OPstream toOtherProc
1053 procBoundaries[patchI].neiProcNo(),
1057 toOtherProc << sendData;
1060 //- receive data from other procesors
1061 forAll(procBoundaries, patchI)
1063 //- get the data sent from the neighbour processor
1064 labelList receivedData;
1066 IPstream fromOtherProc
1069 procBoundaries[patchI].neiProcNo()
1072 fromOtherProc >> receivedData;
1074 const label start = procBoundaries[patchI].patchStart();
1077 while( counter < receivedData.size() )
1079 const label fI = receivedData[counter++];
1080 const label dir = ((receivedData[counter++] + 1) % 2);
1081 const label nSplits = receivedData[counter++];
1083 DynList<labelPair, 2>& currentSplits = localSplits[start+fI];
1084 forAll(currentSplits, i)
1086 if( currentSplits[i].first() == dir )
1087 currentSplits[i].second() =
1088 Foam::max(currentSplits[i].second(), nSplits);
1094 returnReduce(1, sumOp<label>());
1095 Pout << "Starting splitting processor boundaries" << endl;
1098 //- perform splitting
1099 forAll(procBoundaries, patchI)
1101 const label start = procBoundaries[patchI].patchStart();
1102 const label size = procBoundaries[patchI].patchSize();
1104 for(label fI=0;fI<size;++fI)
1106 const label faceI = start + fI;
1108 std::map<label, DynList<labelPair, 2> >::const_iterator it =
1109 localSplits.find(faceI);
1111 if( it == localSplits.end() )
1113 //- this face is not split
1114 facesFromFace_.append(faceI, newFaces_.size());
1115 newFaces_.appendList(faces[faceI]);
1119 //- split the face and add the faces to the list
1120 if( procBoundaries[patchI].owner() )
1122 //- this processor owns this patch
1123 FixedList<label, 2> nLayersInDirection(1);
1124 const DynList<labelPair, 2>& dirSplits = it->second;
1125 forAll(dirSplits, i)
1126 nLayersInDirection[dirSplits[i].first()] =
1127 dirSplits[i].second();
1130 Pout << "Face " << fI << " at owner processor "
1131 << procBoundaries[patchI].myProcNo()
1132 << " neighbour processor "
1133 << procBoundaries[patchI].neiProcNo()
1134 << " face " << faces[faceI] << " refinement direction "
1135 << nLayersInDirection << endl;
1138 DynList<DynList<label, 4>, 128> facesFromFace;
1139 refineFace(faces[faceI], nLayersInDirection, facesFromFace);
1142 forAll(facesFromFace, i)
1144 facesFromFace_.append(faceI, newFaces_.size());
1145 newFaces_.appendList(facesFromFace[i]);
1150 //- reverse the face before splitting
1151 FixedList<label, 2> nLayersInDirection(1);
1152 const DynList<labelPair, 2>& dirSplits = it->second;
1153 forAll(dirSplits, i)
1154 nLayersInDirection[(dirSplits[i].first()+1)%2] =
1155 dirSplits[i].second();
1157 const face rFace = faces[faceI].reverseFace();
1160 Pout << "Face " << fI << " at owner processor "
1161 << procBoundaries[patchI].myProcNo()
1162 << " neighbour processor "
1163 << procBoundaries[patchI].neiProcNo()
1164 << " face " << rFace << " refinement direction "
1165 << nLayersInDirection << endl;
1168 DynList<DynList<label, 4>, 128> facesFromFace;
1169 refineFace(rFace, nLayersInDirection, facesFromFace);
1171 forAll(facesFromFace, i)
1173 const DynList<label, 4>& df = facesFromFace[i];
1174 DynList<label, 4> rFace = help::reverseFace(df);
1176 facesFromFace_.append(faceI, newFaces_.size());
1177 newFaces_.appendList(rFace);
1184 returnReduce(1, sumOp<label>());
1185 for(label procI=0;procI<Pstream::nProcs();++procI)
1187 if( procI == Pstream::myProcNo() )
1189 forAll(procBoundaries, patchI)
1191 const label start = procBoundaries[patchI].patchStart();
1192 const label size = procBoundaries[patchI].patchSize();
1194 for(label fI=0;fI<size;++fI)
1196 const label faceI = start + fI;
1197 const face& f = faces[faceI];
1198 Pout << "Face " << fI << " in patch "
1199 << procBoundaries[patchI].patchName()
1200 << " has nodes " << f
1201 << " local splits " << localSplits[faceI]
1202 << " new faces from face " << facesFromFace_[faceI]
1205 Pout << " Face points ";
1207 Pout << mesh_.points()[f[pI]] << " ";
1210 forAllRow(facesFromFace_, faceI, ffI)
1212 const label nfI = facesFromFace_(faceI, ffI);
1213 Pout << "New face " << ffI << " with label " << nfI
1214 << " consists of points ";
1215 forAllRow(newFaces_, nfI, pI)
1216 Pout << mesh_.points()[newFaces_(nfI, pI)]
1224 returnReduce(1, sumOp<label>());
1227 returnReduce(1, sumOp<label>());
1233 returnReduce(1, sumOp<label>());
1235 for(label procI=0;procI<Pstream::nProcs();++procI)
1237 if( procI == Pstream::myProcNo() )
1239 Pout << "facesFromFace_ " << facesFromFace_ << endl;
1240 Pout << "newFaces_ " << newFaces_ << endl;
1243 returnReduce(1, sumOp<label>());
1246 OFstream file("refinedFaces.vtk");
1248 //- write the header
1249 file << "# vtk DataFile Version 3.0\n";
1250 file << "vtk output\n";
1252 file << "DATASET POLYDATA\n";
1255 file << "POINTS " << mesh_.points().size() << " float\n";
1256 forAll(mesh_.points(), pI)
1258 const point& p = mesh_.points()[pI];
1260 file << p.x() << ' ' << p.y() << ' ' << p.z() << nl;
1265 forAll(newFaces_, faceI)
1267 counter += newFaces_.sizeOfRow(faceI);
1271 file << "\nPOLYGONS " << faces.size()
1272 << " " << counter << nl;
1273 forAll(newFaces_, faceI)
1275 file << newFaces_.sizeOfRow(faceI);
1276 forAllRow(newFaces_, faceI, i)
1277 file << " " << newFaces_(faceI, i);
1284 Info << "Finished refining boundary-layer faces " << endl;
1287 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
1289 } // End namespace Foam
1291 // ************************************************************************* //