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 "surfaceMorpherCells.H"
29 #include "demandDrivenData.H"
30 #include "helperFunctions.H"
36 #include "polyMeshGenAddressing.H"
39 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
44 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
46 void surfaceMorpherCells::findBoundaryVertices()
48 const faceListPMG& faces = mesh_.faces();
50 boundaryVertex_.setSize(mesh_.points().size());
51 boundaryVertex_ = false;
53 const PtrList<boundaryPatch>& boundaries = mesh_.boundaries();
54 forAll(boundaries, patchI)
56 const label start = boundaries[patchI].patchStart();
57 const label end = start + boundaries[patchI].patchSize();
59 for(label faceI=start;faceI<end;++faceI)
61 const face& f = faces[faceI];
66 if( (f[pI] >= boundaryVertex_.size()) || (f[pI] < 0) )
69 FatalError << "Wrong label " << f[pI] << " in face "
70 << faceI << abort(FatalError);
74 boundaryVertex_[f[pI]] = true;
79 if( Pstream::parRun() )
81 const PtrList<processorBoundaryPatch>& procBoundaries =
82 mesh_.procBoundaries();
89 //- send data about boundary vertices to other processors
90 forAll(procBoundaries, patchI)
92 const label start = procBoundaries[patchI].patchStart();
93 const label end = start + procBoundaries[patchI].patchSize();
95 //- create information about bnd nodes which must be exchanged
96 //- with other processors
97 labelHashSet addToSend;
99 for(label faceI=start;faceI<end;++faceI)
101 const face& f = faces[faceI];
104 if( boundaryVertex_[f[pI]] && !addToSend.found(f[pI]) )
106 addToSend.insert(f[pI]);
107 dts.append(faceI-start);
108 dts.append((f.size()-pI)%f.size());
112 labelList bndVertsToSend(dts.size());
114 bndVertsToSend[i] = dts[i];
116 //- send the list of other processor
120 procBoundaries[patchI].neiProcNo(),
121 bndVertsToSend.byteSize()
123 toOtherProc << bndVertsToSend;
126 //- receive boundary vertices from other processor and
127 //- continue sending and receiving as long as it makes some change
128 forAll(procBoundaries, patchI)
130 labelList receivedBndNodes;
131 IPstream fromOtherProc
134 procBoundaries[patchI].neiProcNo()
136 fromOtherProc >> receivedBndNodes;
137 const label start = procBoundaries[patchI].patchStart();
140 while( entryI < receivedBndNodes.size() )
142 const label fI = receivedBndNodes[entryI++];
143 const label pI = receivedBndNodes[entryI++];
145 const face& f = faces[start+fI];
147 if( !boundaryVertex_[f[pI]] )
149 boundaryVertex_[f[pI]] = true;
155 reduce(changed, maxOp<bool>());
160 void surfaceMorpherCells::findBoundaryCells()
162 const labelList& owner = mesh_.owner();
164 cellFlags_.setSize(mesh_.cells().size());
167 const PtrList<boundaryPatch>& boundaries = mesh_.boundaries();
169 forAll(boundaries, patchI)
171 const label start = boundaries[patchI].patchStart();
172 const label end = start + boundaries[patchI].patchSize();
174 for(label faceI=start;faceI<end;++faceI)
175 cellFlags_[owner[faceI]] = BOUNDARY;
179 bool surfaceMorpherCells::morphInternalFaces()
181 Info << "Morphing internal faces" << endl;
184 Serr << "Zip check 1" << endl;
185 labelHashSet zipCellsBefore;
186 mesh_.addressingData().checkCellsZipUp(true, &zipCellsBefore);
187 if( zipCellsBefore.size() )
189 Serr << Pstream::myProcNo() << "Open cells found!" << endl;
190 Serr << "Cells " << zipCellsBefore << " are not zipped!!" << endl;
192 mesh_.clearAddressingData();
197 newBoundaryFaces_.setSize(0);
198 newBoundaryOwners_.setSize(0);
199 newBoundaryPatches_.setSize(0);
201 const label nIntFaces = mesh_.nInternalFaces();
202 const faceListPMG& faces = mesh_.faces();
203 const labelList& owner = mesh_.owner();
204 const labelList& neighbour = mesh_.neighbour();
206 //- copy boundary faces
207 const PtrList<boundaryPatch>& boundaries = mesh_.boundaries();
209 forAll(boundaries, patchI)
211 const label start = boundaries[patchI].patchStart();
212 const label end = start + boundaries[patchI].patchSize();
214 for(label faceI=start;faceI<end;++faceI)
216 newBoundaryFaces_.appendList(faces[faceI]);
217 newBoundaryOwners_.append(owner[faceI]);
218 newBoundaryPatches_.append(0);
222 //- start morphing internal faces
223 for(label faceI=0;faceI<nIntFaces;++faceI)
226 Info << "Morphing internal face " << faceI << endl;
229 const face& f = faces[faceI];
231 DynList<bool> removeFaceVertex(f.size(), false);
238 boundaryVertex_[f.prevLabel(pI)] &&
239 boundaryVertex_[f[pI]] &&
240 boundaryVertex_[f.nextLabel(pI)]
243 removeFaceVertex[pI] = true;
246 Info << "Removing vertex " << f[pI] << " from face "
259 //- store shrinked face
263 Info << "Removing edges " << removeEdge << endl;
264 Info << "Face label " << faceI << " owner " << owner[faceI]
265 << " neighbour " << neighbour[faceI] << endl;
266 Info << "Internal face " << f << " has been shrinked into "
270 //- create new boundary faces from the removed part
272 DynList<direction> nodeMaterial(f.size(), direction(0));
273 DynList<DynList<edge>, 2> edgeMats;
274 forAll(nodeMaterial, nI)
275 if( !nodeMaterial[nI] && removeFaceVertex[nI] )
277 edgeMats.append(DynList<edge>());
278 DynList<label> front;
283 DynList<label> newFront;
286 const label fLabel = front[pI];
287 if( nodeMaterial[fLabel] )
289 nodeMaterial[fLabel] = mat;
290 edgeMats[mat-1].appendIfNotIn(f.faceEdge(fLabel));
291 edgeMats[mat-1].appendIfNotIn
293 f.faceEdge(f.rcIndex(fLabel))
296 if( removeFaceVertex[f.rcIndex(fLabel)] )
297 newFront.append(f.rcIndex(fLabel));
298 if( removeFaceVertex[f.fcIndex(fLabel)] )
299 newFront.append(f.fcIndex(fLabel));
303 while( front.size() != 0 );
308 forAll(edgeMats, matI)
310 edgeMats[matI].shrink();
311 const face rf = help::removeEdgesFromFace(f, edgeMats[matI]);
312 const face newBf = help::createFaceFromRemovedPart(f, rf);
315 Info << "Adding face " << newBf << " as boundary faces" << endl;
316 Info << "Owner and neighbour are " << owner[faceI] << " and "
317 << neighbour[faceI] << endl;
320 newBoundaryFaces_.appendList(newBf);
321 newBoundaryOwners_.append(owner[faceI]);
322 newBoundaryPatches_.append(0);
324 newBoundaryFaces_.appendList(newBf.reverseFace());
325 newBoundaryOwners_.append(neighbour[faceI]);
326 newBoundaryPatches_.append(0);
329 const_cast<face&>(faces[faceI]) = newF;
333 //- treat processor boundaries
334 if( Pstream::parRun() )
336 const PtrList<processorBoundaryPatch>& procBoundaries =
337 mesh_.procBoundaries();
339 forAll(procBoundaries, patchI)
341 const label start = procBoundaries[patchI].patchStart();
342 const label end = start + procBoundaries[patchI].patchSize();
343 const bool isOwner = procBoundaries[patchI].owner();
345 for(label faceI=start;faceI<end;++faceI)
354 copy = faces[faceI].reverseFace();
357 const face& f = copy;
359 DynList<bool> removeFaceVertex(f.size(), false);
366 boundaryVertex_[f.prevLabel(pI)] &&
367 boundaryVertex_[f[pI]] &&
368 boundaryVertex_[f.nextLabel(pI)]
371 removeFaceVertex[pI] = true;
374 Info << "Removing vertex " << f[pI] << " from face "
387 //- store shrinked face
391 Info << "Removing edges " << removeEdge << endl;
392 Info << "Face label " << faceI << " owner " << owner[faceI]
393 << " neighbour " << neighbour[faceI] << endl;
394 Info << "Internal face " << f << " has been shrinked into "
398 //- create new boundary faces from the removed part
400 DynList<direction> nodeMaterial(f.size(), direction(0));
401 DynList< DynList<edge> > edgeMats;
402 forAll(nodeMaterial, nI)
403 if( !nodeMaterial[nI] && removeFaceVertex[nI] )
405 edgeMats.append(DynList<edge>());
406 DynList<label> front;
411 DynList<label> newFront;
414 const label fLabel = front[pI];
415 if( nodeMaterial[fLabel] ) continue;
416 nodeMaterial[fLabel] = mat;
417 edgeMats[mat-1].appendIfNotIn
421 edgeMats[mat-1].appendIfNotIn
423 f.faceEdge(f.rcIndex(fLabel))
426 if( removeFaceVertex[f.rcIndex(fLabel)] )
427 newFront.append(f.rcIndex(fLabel));
428 if( removeFaceVertex[f.fcIndex(fLabel)] )
429 newFront.append(f.fcIndex(fLabel));
433 while( front.size() != 0 );
438 forAll(edgeMats, matI)
440 edgeMats[matI].shrink();
442 help::removeEdgesFromFace(f, edgeMats[matI]);
444 help::createFaceFromRemovedPart(f, rf);
447 Info << "Adding face " << newBf
448 << " as boundary faces" << endl;
449 Info << "Owner and neighbour are "
450 << owner[faceI] << endl;
455 newBoundaryFaces_.appendList(newBf);
459 newBoundaryFaces_.appendList(newBf.reverseFace());
461 newBoundaryOwners_.append(owner[faceI]);
462 newBoundaryPatches_.append(0);
465 if( isOwner || (newF.size() < 3) )
467 const_cast<face&>(faces[faceI]) = newF;
471 const_cast<face&>(faces[faceI]) = newF.reverseFace();
478 polyMeshGenModifier meshModifier(mesh_);
480 if( Pstream::parRun() )
482 reduce(changed, maxOp<bool>());
487 //- replace boundary of the mesh
488 replaceMeshBoundary();
491 Serr << "Zip check 2" << endl;
492 const cellListPMG& cells = mesh_.cells();
495 const cell& c = cells[cI];
498 DynList<direction> nAppearances;
502 const face& f = faces[c[fI]];
505 const label pos = edges.containsAtPosition(f.faceEdge(eI));
509 edges.append(f.faceEdge(eI));
510 nAppearances.append(1);
519 forAll(nAppearances, eI)
520 if( nAppearances[eI] != 2 )
522 Warning << "Cell " << cI << " is not closed" << endl;
523 Serr << "Cell faces " << c << endl;
525 Serr << "Face " << c[fI] << " is "
526 << faces[c[fI]] << endl;
531 //- remove faces which do not exist any more
532 boolList removeFace(faces.size(), false);
533 bool removeFaces(false);
534 for(register label faceI=0;faceI<nIntFaces;++faceI)
535 if( faces[faceI].size() < 3 )
537 removeFace[faceI] = true;
541 if( Pstream::parRun() )
543 const PtrList<processorBoundaryPatch>& procBoundaries =
544 mesh_.procBoundaries();
546 forAll(procBoundaries, patchI)
548 const label start = procBoundaries[patchI].patchStart();
549 const label end = start + procBoundaries[patchI].patchSize();
550 for(label faceI=start;faceI<end;++faceI)
551 if( faces[faceI].size() < 3 )
553 removeFace[faceI] = true;
558 reduce(removeFaces, maxOp<bool>());
562 meshModifier.removeFaces(removeFace);
566 Serr << "Zip check 3" << endl;
567 labelHashSet zipCells;
568 mesh_.addressingData().checkCellsZipUp(true, &zipCells);
569 if( zipCells.size() )
571 Serr << Pstream::myProcNo() << "Open cells appeared!" << endl;
573 Serr << "Cells " << zipCells << " are not zipped!!" << endl;
575 mesh_.clearAddressingData();
578 Info << "Finished morphing internal faces" << endl;
583 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
585 } // End namespace Foam
587 // ************************************************************************* //