1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM 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 2 of the License, or (at your
14 option) any later version.
16 OpenFOAM 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 OpenFOAM; if not, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 \*---------------------------------------------------------------------------*/
27 #include "edgeCollapser.H"
29 #include "polyTopoChange.H"
32 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
34 Foam::label Foam::edgeCollapser::findIndex
36 const labelList& elems,
42 for (label i = start; i < size; i++)
53 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
55 // Changes region of connected set of points
56 Foam::label Foam::edgeCollapser::changePointRegion
59 const label oldRegion,
65 if (pointRegion_[pointI] == oldRegion)
67 pointRegion_[pointI] = newRegion;
70 // Step to neighbouring point across edges with same region number
72 const labelList& pEdges = mesh_.pointEdges()[pointI];
76 label otherPointI = mesh_.edges()[pEdges[i]].otherVertex(pointI);
78 nChanged += changePointRegion(otherPointI, oldRegion, newRegion);
85 bool Foam::edgeCollapser::pointRemoved(const label pointI) const
87 label region = pointRegion_[pointI];
89 if (region == -1 || pointRegionMaster_[region] == pointI)
100 void Foam::edgeCollapser::filterFace(const label faceI, face& f) const
106 label pointI = f[fp];
108 label region = pointRegion_[pointI];
116 label master = pointRegionMaster_[region];
118 if (findIndex(f, 0, newFp, master) == -1)
125 // Check for pinched face. Tries to correct
126 // - consecutive duplicate vertex. Removes duplicate vertex.
127 // - duplicate vertex with one other vertex in between (spike).
128 // Both of these should not really occur! and should be checked before
131 const label size = newFp;
135 for (label fp = 2; fp < size; fp++)
140 label pointI = f[fp];
142 // Search for previous occurrence.
143 label index = findIndex(f, 0, fp, pointI);
149 "Foam::edgeCollapser::filterFace(const label faceI, "
151 ) << "Removing consecutive duplicate vertex in face "
153 // Don't store current pointI
155 else if (index == fp2)
159 "Foam::edgeCollapser::filterFace(const label faceI, "
161 ) << "Removing non-consecutive duplicate vertex in face "
163 // Don't store current pointI and remove previous
166 else if (index != -1)
170 "Foam::edgeCollapser::filterFace(const label faceI, "
172 ) << "Pinched face " << f << endl;
186 void Foam::edgeCollapser::printRegions() const
188 forAll(pointRegionMaster_, regionI)
190 label master = pointRegionMaster_[regionI];
194 Info<< "Region:" << regionI << nl
195 << " master:" << master
196 << ' ' << mesh_.points()[master] << nl;
198 forAll(pointRegion_, pointI)
200 if (pointRegion_[pointI] == regionI && pointI != master)
202 Info<< " slave:" << pointI
203 << ' ' << mesh_.points()[pointI] << nl;
212 // Collapse list of edges
213 void Foam::edgeCollapser::collapseEdges(const labelList& edgeLabels)
215 const edgeList& edges = mesh_.edges();
217 forAll(edgeLabels, i)
219 label edgeI = edgeLabels[i];
220 const edge& e = edges[edgeI];
222 label region0 = pointRegion_[e[0]];
223 label region1 = pointRegion_[e[1]];
229 // Both unaffected. Choose ad lib.
230 collapseEdge(edgeI, e[0]);
234 // Collapse to whatever e[1] collapses
235 collapseEdge(edgeI, e[1]);
242 // Collapse to whatever e[0] collapses
243 collapseEdge(edgeI, e[0]);
248 if (pointRegionMaster_[region0] == e[0])
251 collapseEdge(edgeI, e[0]);
253 else if (pointRegionMaster_[region1] == e[1])
256 collapseEdge(edgeI, e[1]);
261 collapseEdge(edgeI, e[0]);
269 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
271 // Construct from mesh
272 Foam::edgeCollapser::edgeCollapser(const polyMesh& mesh)
275 pointRegion_(mesh.nPoints(), -1),
276 pointRegionMaster_(mesh.nPoints() / 100),
281 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
283 bool Foam::edgeCollapser::unaffectedEdge(const label edgeI) const
285 const edge& e = mesh_.edges()[edgeI];
287 return (pointRegion_[e[0]] == -1) && (pointRegion_[e[1]] == -1);
291 bool Foam::edgeCollapser::collapseEdge(const label edgeI, const label master)
293 const edge& e = mesh_.edges()[edgeI];
295 label pointRegion0 = pointRegion_[e[0]];
296 label pointRegion1 = pointRegion_[e[1]];
298 if (pointRegion0 == -1)
300 if (pointRegion1 == -1)
302 // Both endpoints not collapsed. Create new region.
304 label freeRegion = -1;
306 if (freeRegions_.size())
308 freeRegion = freeRegions_.removeHead();
310 if (pointRegionMaster_[freeRegion] != -1)
313 ("edgeCollapser::collapseEdge(const label, const label)")
314 << "Problem : freeed region :" << freeRegion
315 << " has already master "
316 << pointRegionMaster_[freeRegion]
317 << abort(FatalError);
322 // If no region found create one. This is the only place where
323 // new regions are created.
324 freeRegion = pointRegionMaster_.size();
327 pointRegion_[e[0]] = freeRegion;
328 pointRegion_[e[1]] = freeRegion;
330 pointRegionMaster_(freeRegion) = master;
334 // e[1] is part of collapse network, e[0] not. Add e0 to e1 region.
335 pointRegion_[e[0]] = pointRegion1;
337 pointRegionMaster_[pointRegion1] = master;
342 if (pointRegion1 == -1)
344 // e[0] is part of collapse network. Add e1 to e0 region
345 pointRegion_[e[1]] = pointRegion0;
347 pointRegionMaster_[pointRegion0] = master;
349 else if (pointRegion0 != pointRegion1)
351 // Both part of collapse network. Merge the two regions.
353 // Use the smaller region number for the whole network.
354 label minRegion = min(pointRegion0, pointRegion1);
355 label maxRegion = max(pointRegion0, pointRegion1);
357 // Use minRegion as region for combined net, free maxRegion.
358 pointRegionMaster_[minRegion] = master;
359 pointRegionMaster_[maxRegion] = -1;
360 freeRegions_.insert(maxRegion);
362 if (minRegion != pointRegion0)
364 changePointRegion(e[0], pointRegion0, minRegion);
366 if (minRegion != pointRegion1)
368 changePointRegion(e[1], pointRegion1, minRegion);
377 bool Foam::edgeCollapser::setRefinement(polyTopoChange& meshMod)
379 const cellList& cells = mesh_.cells();
380 const labelList& faceOwner = mesh_.faceOwner();
381 const labelList& faceNeighbour = mesh_.faceNeighbour();
382 const labelListList& pointFaces = mesh_.pointFaces();
383 const labelListList& cellEdges = mesh_.cellEdges();
388 bool meshChanged = false;
391 // Current faces (is also collapseStatus: f.size() < 3)
392 faceList newFaces(mesh_.faces());
394 // Current cellCollapse status
395 boolList cellRemoved(mesh_.nCells(), false);
400 // Update face collapse from edge collapses
401 forAll(newFaces, faceI)
403 filterFace(faceI, newFaces[faceI]);
406 // Check if faces to be collapsed cause cells to become collapsed.
407 label nCellCollapsed = 0;
411 if (!cellRemoved[cellI])
413 const cell& cFaces = cells[cellI];
415 label nFaces = cFaces.size();
419 label faceI = cFaces[i];
421 if (newFaces[faceI].size() < 3)
427 Info<< "Cell:" << cellI
428 << " uses faces:" << cFaces
429 << " of which too many are marked for removal:"
434 if (newFaces[cFaces[j]].size() < 3)
436 Info<< ' '<< cFaces[j];
441 cellRemoved[cellI] = true;
443 // Collapse all edges of cell to nothing
444 collapseEdges(cellEdges[cellI]);
455 if (nCellCollapsed == 0)
462 // Keep track of faces that have been done already.
463 boolList doneFace(mesh_.nFaces(), false);
467 boolList usedPoint(mesh_.nPoints(), false);
470 forAll(cellRemoved, cellI)
472 if (cellRemoved[cellI])
474 meshMod.removeCell(cellI, -1);
480 forAll(newFaces, faceI)
482 const face& f = newFaces[faceI];
486 meshMod.removeFace(faceI, -1);
489 // Mark face as been done.
490 doneFace[faceI] = true;
494 // Kept face. Mark vertices
497 usedPoint[f[fp]] = true;
502 // Remove unused vertices that have not been marked for removal already
503 forAll(usedPoint, pointI)
505 if (!usedPoint[pointI] && !pointRemoved(pointI))
507 meshMod.removePoint(pointI, -1);
516 forAll(pointRegion_, pointI)
518 if (pointRemoved(pointI))
520 meshMod.removePoint(pointI, -1);
527 const polyBoundaryMesh& boundaryMesh = mesh_.boundaryMesh();
528 const faceZoneMesh& faceZones = mesh_.faceZones();
531 // Renumber faces that use points
532 forAll(pointRegion_, pointI)
534 if (pointRemoved(pointI))
536 const labelList& changedFaces = pointFaces[pointI];
538 forAll(changedFaces, changedFaceI)
540 label faceI = changedFaces[changedFaceI];
542 if (!doneFace[faceI])
544 doneFace[faceI] = true;
546 // Get current zone info
547 label zoneID = faceZones.whichZone(faceI);
549 bool zoneFlip = false;
553 const faceZone& fZone = faceZones[zoneID];
555 zoneFlip = fZone.flipMap()[fZone.whichFace(faceI)];
558 // Get current connectivity
559 label own = faceOwner[faceI];
563 if (mesh_.isInternalFace(faceI))
565 nei = faceNeighbour[faceI];
569 patchID = boundaryMesh.whichPatch(faceI);
574 newFaces[faceI], // face
575 faceI, // faceI to change
578 false, // flipFaceFlux
593 void Foam::edgeCollapser::updateMesh(const mapPolyMesh& map)
595 pointRegion_.setSize(mesh_.nPoints());
597 // Reset count, do not remove underlying storage
598 pointRegionMaster_.clear();
599 freeRegions_.clear();
603 // ************************************************************************* //