From b4a742fc893ae4721d5c90b0003e310b7e5b1a08 Mon Sep 17 00:00:00 2001 From: laurence <laurence> Date: Wed, 18 Sep 2013 15:31:58 +0100 Subject: [PATCH] ENH: collapseEdges: Points now get a priority. The higher the number, the more likely the collapse will be towards that point --- .../advanced/collapseEdges/collapseEdges.C | 65 +- .../conformalVoronoiMesh.C | 20 +- .../conformalVoronoiMesh.H | 15 +- .../conformalVoronoiMeshCalcDualMesh.C | 458 ++-- .../conformalVoronoiMeshIO.C | 200 +- .../indexedCell/indexedCell.H | 5 + .../indexedCell/indexedCellI.H | 81 + .../indexedVertex/indexedVertex.H | 2 + .../indexedVertex/indexedVertexEnum.C | 8 +- .../indexedVertex/indexedVertexEnum.H | 28 +- .../indexedVertex/indexedVertexI.H | 20 + src/dynamicMesh/Make/files | 1 + .../polyMeshFilter/polyMeshFilter.C | 1882 +++++++---------- .../polyMeshFilter/polyMeshFilter.H | 85 +- .../polyTopoChange/edgeCollapser.C | 270 ++- 15 files changed, 1428 insertions(+), 1712 deletions(-) diff --git a/applications/utilities/mesh/advanced/collapseEdges/collapseEdges.C b/applications/utilities/mesh/advanced/collapseEdges/collapseEdges.C index 7a07b63d8f0..0515205c788 100644 --- a/applications/utilities/mesh/advanced/collapseEdges/collapseEdges.C +++ b/applications/utilities/mesh/advanced/collapseEdges/collapseEdges.C @@ -95,24 +95,56 @@ int main(int argc, char *argv[]) const bool collapseFaces = args.optionFound("collapseFaces"); const bool collapseFaceZone = args.optionFound("collapseFaceZone"); + if (collapseFaces && collapseFaceZone) + { + FatalErrorIn("main(int, char*[])") + << "Both face zone collapsing and face collapsing have been" + << "selected. Choose only one of:" << nl + << " -collapseFaces" << nl + << " -collapseFaceZone <faceZoneName>" + << abort(FatalError); + } + + labelIOList pointPriority + ( + IOobject + ( + "pointPriority", + runTime.timeName(), + runTime, + IOobject::READ_IF_PRESENT, + IOobject::AUTO_WRITE + ), + labelList(mesh.nPoints(), labelMin) + ); + forAll(timeDirs, timeI) { runTime.setTime(timeDirs[timeI], timeI); Info<< "Time = " << runTime.timeName() << endl; - polyMeshFilter meshFilter(mesh); + autoPtr<polyMeshFilter> meshFilterPtr; - // newMesh will be empty until it is filtered - const autoPtr<fvMesh>& newMesh = meshFilter.filteredMesh(); + label nBadFaces = 0; - // Filter small edges only. This reduces the number of faces so that - // the face filtering is sped up. - label nBadFaces = meshFilter.filterEdges(0); { - polyTopoChange meshMod(newMesh); + meshFilterPtr.set(new polyMeshFilter(mesh, pointPriority)); + polyMeshFilter& meshFilter = meshFilterPtr(); + + // newMesh will be empty until it is filtered + const autoPtr<fvMesh>& newMesh = meshFilter.filteredMesh(); + + // Filter small edges only. This reduces the number of faces so that + // the face filtering is sped up. + nBadFaces = meshFilter.filterEdges(0); + { + polyTopoChange meshMod(newMesh); - meshMod.changeMesh(mesh, false); + meshMod.changeMesh(mesh, false); + } + + pointPriority = meshFilter.pointPriority(); } if (collapseFaceZone) @@ -121,18 +153,30 @@ int main(int argc, char *argv[]) const faceZone& fZone = mesh.faceZones()[faceZoneName]; + meshFilterPtr.reset(new polyMeshFilter(mesh, pointPriority)); + polyMeshFilter& meshFilter = meshFilterPtr(); + + const autoPtr<fvMesh>& newMesh = meshFilter.filteredMesh(); + // Filter faces. Pass in the number of bad faces that are present // from the previous edge filtering to use as a stopping criterion. - meshFilter.filterFaceZone(fZone); + meshFilter.filter(fZone); { polyTopoChange meshMod(newMesh); meshMod.changeMesh(mesh, false); } + + pointPriority = meshFilter.pointPriority(); } if (collapseFaces) { + meshFilterPtr.reset(new polyMeshFilter(mesh, pointPriority)); + polyMeshFilter& meshFilter = meshFilterPtr(); + + const autoPtr<fvMesh>& newMesh = meshFilter.filteredMesh(); + // Filter faces. Pass in the number of bad faces that are present // from the previous edge filtering to use as a stopping criterion. meshFilter.filter(nBadFaces); @@ -141,6 +185,8 @@ int main(int argc, char *argv[]) meshMod.changeMesh(mesh, false); } + + pointPriority = meshFilter.pointPriority(); } // Write resulting mesh @@ -157,6 +203,7 @@ int main(int argc, char *argv[]) << runTime.timeName() << nl << endl; mesh.write(); + pointPriority.write(); } Info<< nl << "ExecutionTime = " << runTime.elapsedCpuTime() << " s" diff --git a/applications/utilities/mesh/generation/foamyHexMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.C b/applications/utilities/mesh/generation/foamyHexMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.C index 8224492921d..e5a5d9e1bf6 100644 --- a/applications/utilities/mesh/generation/foamyHexMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.C +++ b/applications/utilities/mesh/generation/foamyHexMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.C @@ -41,9 +41,26 @@ License namespace Foam { -defineTypeNameAndDebug(conformalVoronoiMesh, 0); + defineTypeNameAndDebug(conformalVoronoiMesh, 0); + + template<> + const char* Foam::NamedEnum + < + Foam::conformalVoronoiMesh::dualMeshPointType, + 5 + >::names[] = + { + "internal", + "surface", + "featureEdge", + "featurePoint", + "constrained" + }; } +const Foam::NamedEnum<Foam::conformalVoronoiMesh::dualMeshPointType, 5> + Foam::conformalVoronoiMesh::dualMeshPointTypeNames_; + // * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * // @@ -1600,7 +1617,6 @@ void Foam::conformalVoronoiMesh::move() printVertexInfo(Info); } - // Write the intermediate mesh, do not filter the dual faces. if (time().outputTime()) { writeMesh(time().timeName()); diff --git a/applications/utilities/mesh/generation/foamyHexMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.H b/applications/utilities/mesh/generation/foamyHexMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.H index eb75909d1c2..1daffd4c745 100644 --- a/applications/utilities/mesh/generation/foamyHexMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.H +++ b/applications/utilities/mesh/generation/foamyHexMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.H @@ -120,6 +120,17 @@ private: // Static data + enum dualMeshPointType + { + internal = 0, + surface = 1, + featureEdge = 2, + featurePoint = 3, + constrained = 4 + }; + + static const NamedEnum<dualMeshPointType, 5> dualMeshPointTypeNames_; + static const scalar searchConeAngle; static const scalar searchAngleOppositeSurface; @@ -682,14 +693,12 @@ private: //- Merge vertices that are identical void mergeIdenticalDualVertices ( - const pointField& pts, - const labelList& boundaryPts + const pointField& pts ); label mergeIdenticalDualVertices ( const pointField& pts, - const labelList& boundaryPts, Map<label>& dualPtIndexMap ) const; diff --git a/applications/utilities/mesh/generation/foamyHexMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshCalcDualMesh.C b/applications/utilities/mesh/generation/foamyHexMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshCalcDualMesh.C index 4e70aab9649..c96fad1e490 100644 --- a/applications/utilities/mesh/generation/foamyHexMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshCalcDualMesh.C +++ b/applications/utilities/mesh/generation/foamyHexMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshCalcDualMesh.C @@ -207,209 +207,214 @@ void Foam::conformalVoronoiMesh::checkCells() } -void Foam::conformalVoronoiMesh::checkDuals() -{ - List<List<Point> > pointFieldList(Pstream::nProcs()); - - List<Point> duals(number_of_finite_cells()); - -// PackedBoolList bPoints(number_of_finite_cells()); - -// indexDualVertices(duals, bPoints); - - label count = 0;//duals.size(); - - duals.setSize(number_of_finite_cells()); - - globalIndex gIndex(number_of_vertices()); - - for - ( - Delaunay::Finite_cells_iterator cit = finite_cells_begin(); - cit != finite_cells_end(); - ++cit - ) - { - if (cit->hasFarPoint()) - { - continue; - } - - duals[count++] = cit->circumcenter(); - -// List<labelPair> cellVerticesPair(4); -// List<Point> cellVertices(4); +//void Foam::conformalVoronoiMesh::checkDuals() +//{ +// List<List<Point> > pointFieldList(Pstream::nProcs()); +// +// List<Point> duals(number_of_finite_cells()); +// +// typedef CGAL::Exact_predicates_exact_constructions_kernel EK2; +// typedef CGAL::Regular_triangulation_euclidean_traits_3<EK2> EK; +// typedef CGAL::Cartesian_converter<baseK::Kernel, EK2> To_exact; +// typedef CGAL::Cartesian_converter<EK2, baseK::Kernel> Back_from_exact; +// +//// PackedBoolList bPoints(number_of_finite_cells()); // -// for (label vI = 0; vI < 4; ++vI) +//// indexDualVertices(duals, bPoints); +// +// label count = 0;//duals.size(); +// +// duals.setSize(number_of_finite_cells()); +// +// globalIndex gIndex(number_of_vertices()); +// +// for +// ( +// Delaunay::Finite_cells_iterator cit = finite_cells_begin(); +// cit != finite_cells_end(); +// ++cit +// ) +// { +// if (cit->hasFarPoint()) // { -// cellVerticesPair[vI] = labelPair -// ( -// cit->vertex(vI)->procIndex(), -// cit->vertex(vI)->index() -// ); -// cellVertices[vI] = cit->vertex(vI)->point(); +// continue; // } // -// labelList oldToNew; -// sortedOrder(cellVerticesPair, oldToNew); -// oldToNew = invert(oldToNew.size(), oldToNew); -// inplaceReorder(oldToNew, cellVerticesPair); -// inplaceReorder(oldToNew, cellVertices); +// duals[count++] = cit->circumcenter(); // -// duals[count++] = CGAL::circumcenter -// ( -// cellVertices[0], -// cellVertices[1], -// cellVertices[2], -// cellVertices[3] -// ); - -// To_exact to_exact; -// Back_from_exact back_from_exact; -// EK::Construct_circumcenter_3 exact_circumcenter = -// EK().construct_circumcenter_3_object(); +//// List<labelPair> cellVerticesPair(4); +//// List<Point> cellVertices(4); +//// +//// for (label vI = 0; vI < 4; ++vI) +//// { +//// cellVerticesPair[vI] = labelPair +//// ( +//// cit->vertex(vI)->procIndex(), +//// cit->vertex(vI)->index() +//// ); +//// cellVertices[vI] = cit->vertex(vI)->point(); +//// } +//// +//// labelList oldToNew; +//// sortedOrder(cellVerticesPair, oldToNew); +//// oldToNew = invert(oldToNew.size(), oldToNew); +//// inplaceReorder(oldToNew, cellVerticesPair); +//// inplaceReorder(oldToNew, cellVertices); +//// +//// duals[count++] = CGAL::circumcenter +//// ( +//// cellVertices[0], +//// cellVertices[1], +//// cellVertices[2], +//// cellVertices[3] +//// ); // -// duals[count++] = topoint -// ( -// back_from_exact -// ( -// exact_circumcenter -// ( -// to_exact(cit->vertex(0)->point()), -// to_exact(cit->vertex(1)->point()), -// to_exact(cit->vertex(2)->point()), -// to_exact(cit->vertex(3)->point()) -// ) -// ) -// ); - } - - Pout<< "Duals Calculated " << count << endl; - - duals.setSize(count); - - pointFieldList[Pstream::myProcNo()] = duals; - - Pstream::gatherList(pointFieldList); - - if (Pstream::master()) - { - Info<< "Checking on master processor the dual locations of each " << nl - << "processor point list against the master dual list." << nl - << "There are " << pointFieldList.size() << " processors" << nl - << "The size of each processor's dual list is:" << endl; - - forAll(pointFieldList, pfI) - { - Info<< " Proc " << pfI << " has " << pointFieldList[pfI].size() - << " duals" << endl; - } - - label nNonMatches = 0; - label nNearMatches = 0; - label nExactMatches = 0; - - forAll(pointFieldList[0], pI) - { - const Point& masterPoint = pointFieldList[0][pI]; - - bool foundMatch = false; - bool foundNearMatch = false; - - scalar minCloseness = GREAT; - Point closestPoint(0, 0, 0); - - forAll(pointFieldList, pfI) - { - if (pfI == 0) - { - continue; - } - -// label pfI = 1; - - forAll(pointFieldList[pfI], pISlave) - { - const Point& slavePoint - = pointFieldList[pfI][pISlave]; - - if (masterPoint == slavePoint) - { - foundMatch = true; - break; - } - - const scalar closeness = mag - ( - topoint(masterPoint) - topoint(slavePoint) - ); - - if (closeness < 1e-12) - { - foundNearMatch = true; - } - else - { - if (closeness < minCloseness) - { - minCloseness = closeness; - closestPoint = slavePoint; - } - } - } - - if (!foundMatch) - { - if (foundNearMatch) - { - CGAL::Gmpq x(CGAL::to_double(masterPoint.x())); - CGAL::Gmpq y(CGAL::to_double(masterPoint.y())); - CGAL::Gmpq z(CGAL::to_double(masterPoint.z())); - - std::cout<< "master = " << x << " " << y << " " << z - << std::endl; - - CGAL::Gmpq xs(CGAL::to_double(closestPoint.x())); - CGAL::Gmpq ys(CGAL::to_double(closestPoint.y())); - CGAL::Gmpq zs(CGAL::to_double(closestPoint.z())); - std::cout<< "slave = " << xs << " " << ys << " " << zs - << std::endl; - - nNearMatches++; - } - else - { - nNonMatches++; - Info<< " Closest point to " << masterPoint << " is " - << closestPoint << nl - << " Separation is " << minCloseness << endl; - - CGAL::Gmpq x(CGAL::to_double(masterPoint.x())); - CGAL::Gmpq y(CGAL::to_double(masterPoint.y())); - CGAL::Gmpq z(CGAL::to_double(masterPoint.z())); - - std::cout<< "master = " << x << " " << y << " " << z - << std::endl; - - CGAL::Gmpq xs(CGAL::to_double(closestPoint.x())); - CGAL::Gmpq ys(CGAL::to_double(closestPoint.y())); - CGAL::Gmpq zs(CGAL::to_double(closestPoint.z())); - std::cout<< "slave = " << xs << " " << ys << " " << zs - << std::endl; - } - } - else - { - nExactMatches++; - } - } - } - - Info<< "Found " << nNonMatches << " non-matching duals" << nl - << " and " << nNearMatches << " near matches" - << " and " << nExactMatches << " exact matches" << endl; - } -} +//// To_exact to_exact; +//// Back_from_exact back_from_exact; +//// EK::Construct_circumcenter_3 exact_circumcenter = +//// EK().construct_circumcenter_3_object(); +//// +//// duals[count++] = topoint +//// ( +//// back_from_exact +//// ( +//// exact_circumcenter +//// ( +//// to_exact(cit->vertex(0)->point()), +//// to_exact(cit->vertex(1)->point()), +//// to_exact(cit->vertex(2)->point()), +//// to_exact(cit->vertex(3)->point()) +//// ) +//// ) +//// ); +// } +// +// Pout<< "Duals Calculated " << count << endl; +// +// duals.setSize(count); +// +// pointFieldList[Pstream::myProcNo()] = duals; +// +// Pstream::gatherList(pointFieldList); +// +// if (Pstream::master()) +// { +// Info<< "Checking on master processor the dual locations of each " << nl +// << "processor point list against the master dual list." << nl +// << "There are " << pointFieldList.size() << " processors" << nl +// << "The size of each processor's dual list is:" << endl; +// +// forAll(pointFieldList, pfI) +// { +// Info<< " Proc " << pfI << " has " << pointFieldList[pfI].size() +// << " duals" << endl; +// } +// +// label nNonMatches = 0; +// label nNearMatches = 0; +// label nExactMatches = 0; +// +// forAll(pointFieldList[0], pI) +// { +// const Point& masterPoint = pointFieldList[0][pI]; +// +// bool foundMatch = false; +// bool foundNearMatch = false; +// +// scalar minCloseness = GREAT; +// Point closestPoint(0, 0, 0); +// +// forAll(pointFieldList, pfI) +// { +// if (pfI == 0) +// { +// continue; +// } +// +//// label pfI = 1; +// +// forAll(pointFieldList[pfI], pISlave) +// { +// const Point& slavePoint +// = pointFieldList[pfI][pISlave]; +// +// if (masterPoint == slavePoint) +// { +// foundMatch = true; +// break; +// } +// +// const scalar closeness = mag +// ( +// topoint(masterPoint) - topoint(slavePoint) +// ); +// +// if (closeness < 1e-12) +// { +// foundNearMatch = true; +// } +// else +// { +// if (closeness < minCloseness) +// { +// minCloseness = closeness; +// closestPoint = slavePoint; +// } +// } +// } +// +// if (!foundMatch) +// { +// if (foundNearMatch) +// { +// CGAL::Gmpq x(CGAL::to_double(masterPoint.x())); +// CGAL::Gmpq y(CGAL::to_double(masterPoint.y())); +// CGAL::Gmpq z(CGAL::to_double(masterPoint.z())); +// +// std::cout<< "master = " << x << " " << y << " " << z +// << std::endl; +// +// CGAL::Gmpq xs(CGAL::to_double(closestPoint.x())); +// CGAL::Gmpq ys(CGAL::to_double(closestPoint.y())); +// CGAL::Gmpq zs(CGAL::to_double(closestPoint.z())); +// std::cout<< "slave = " << xs << " " << ys << " " << zs +// << std::endl; +// +// nNearMatches++; +// } +// else +// { +// nNonMatches++; +// Info<< " Closest point to " << masterPoint << " is " +// << closestPoint << nl +// << " Separation is " << minCloseness << endl; +// +// CGAL::Gmpq x(CGAL::to_double(masterPoint.x())); +// CGAL::Gmpq y(CGAL::to_double(masterPoint.y())); +// CGAL::Gmpq z(CGAL::to_double(masterPoint.z())); +// +// std::cout<< "master = " << x << " " << y << " " << z +// << std::endl; +// +// CGAL::Gmpq xs(CGAL::to_double(closestPoint.x())); +// CGAL::Gmpq ys(CGAL::to_double(closestPoint.y())); +// CGAL::Gmpq zs(CGAL::to_double(closestPoint.z())); +// std::cout<< "slave = " << xs << " " << ys << " " << zs +// << std::endl; +// } +// } +// else +// { +// nExactMatches++; +// } +// } +// } +// +// Info<< "Found " << nNonMatches << " non-matching duals" << nl +// << " and " << nNearMatches << " near matches" +// << " and " << nExactMatches << " exact matches" << endl; +// } +//} void Foam::conformalVoronoiMesh::checkVertices() @@ -578,7 +583,7 @@ void Foam::conformalVoronoiMesh::calcDualMesh Info<< nl << "Merging identical points" << endl; // There is no guarantee that a merge of close points is no-risk - mergeIdenticalDualVertices(points, boundaryPts); + mergeIdenticalDualVertices(points); } // Final dual face and owner neighbour construction @@ -813,8 +818,7 @@ void Foam::conformalVoronoiMesh::calcTetMesh void Foam::conformalVoronoiMesh::mergeIdenticalDualVertices ( - const pointField& pts, - const labelList& boundaryPts + const pointField& pts ) { // Assess close points to be merged @@ -829,7 +833,6 @@ void Foam::conformalVoronoiMesh::mergeIdenticalDualVertices nPtsMerged = mergeIdenticalDualVertices ( pts, - boundaryPts, dualPtIndexMap ); @@ -851,7 +854,6 @@ void Foam::conformalVoronoiMesh::mergeIdenticalDualVertices Foam::label Foam::conformalVoronoiMesh::mergeIdenticalDualVertices ( const pointField& pts, - const labelList& boundaryPts, Map<label>& dualPtIndexMap ) const { @@ -883,6 +885,19 @@ Foam::label Foam::conformalVoronoiMesh::mergeIdenticalDualVertices if (p1 == p2) { +// if (c1->parallelDualVertex() || c2->parallelDualVertex()) +// { +// if (c1->vertexLowestProc() < c2->vertexLowestProc()) +// { +// dualPtIndexMap.insert(c1I, c1I); +// dualPtIndexMap.insert(c2I, c1I); +// } +// else +// { +// dualPtIndexMap.insert(c1I, c2I); +// dualPtIndexMap.insert(c2I, c2I); +// } +// } if (c1I < c2I) { dualPtIndexMap.insert(c1I, c1I); @@ -1338,13 +1353,13 @@ void Foam::conformalVoronoiMesh::checkCellSizing() timeCheck("Start of Cell Sizing"); - labelList boundaryPts(number_of_finite_cells(), -1); + labelList boundaryPts(number_of_finite_cells(), internal); pointField ptsField; indexDualVertices(ptsField, boundaryPts); // Merge close dual vertices. - mergeIdenticalDualVertices(ptsField, boundaryPts); + mergeIdenticalDualVertices(ptsField); autoPtr<polyMesh> meshPtr = createPolyMeshFromPoints(ptsField); const polyMesh& pMesh = meshPtr(); @@ -1755,7 +1770,7 @@ void Foam::conformalVoronoiMesh::indexDualVertices boundaryPts.setSize ( number_of_finite_cells() + nConstrainedVertices, - -1 + internal ); if (foamyHexMeshControls().guardFeaturePoints()) @@ -1774,7 +1789,7 @@ void Foam::conformalVoronoiMesh::indexDualVertices topoint(vit->point()); boundaryPts[number_of_finite_cells() + nConstrainedVertices] = - 1; + constrained; nConstrainedVertices++; } @@ -1974,15 +1989,40 @@ void Foam::conformalVoronoiMesh::indexDualVertices if (cit->boundaryDualVertex()) { - if (cit->featureEdgeDualVertex()) + if (cit->featurePointDualVertex()) { - boundaryPts[cit->cellIndex()] = 1; + boundaryPts[cit->cellIndex()] = featurePoint; + } + else if (cit->featureEdgeDualVertex()) + { + boundaryPts[cit->cellIndex()] = featureEdge; } else { - boundaryPts[cit->cellIndex()] = 0; + boundaryPts[cit->cellIndex()] = surface; } } + else if + ( + cit->baffleBoundaryDualVertex() + ) + { + boundaryPts[cit->cellIndex()] = surface; + } + else if + ( + cit->vertex(0)->featureEdgePoint() + && cit->vertex(1)->featureEdgePoint() + && cit->vertex(2)->featureEdgePoint() + && cit->vertex(3)->featureEdgePoint() + ) + { + boundaryPts[cit->cellIndex()] = featureEdge; + } + else + { + boundaryPts[cit->cellIndex()] = internal; + } } else { diff --git a/applications/utilities/mesh/generation/foamyHexMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshIO.C b/applications/utilities/mesh/generation/foamyHexMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshIO.C index 4f02fb67f60..d733b33e35a 100644 --- a/applications/utilities/mesh/generation/foamyHexMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshIO.C +++ b/applications/utilities/mesh/generation/foamyHexMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshIO.C @@ -958,7 +958,7 @@ void Foam::conformalVoronoiMesh::writeMesh { Info<< nl << "Filtering edges on polyMesh" << nl << endl; - meshFilter.reset(new polyMeshFilter(mesh)); + meshFilter.reset(new polyMeshFilter(mesh, boundaryPts)); // Filter small edges only. This reduces the number of faces so that // the face filtering is sped up. @@ -974,9 +974,28 @@ void Foam::conformalVoronoiMesh::writeMesh if (foamyHexMeshControls().filterFaces()) { + labelIOList boundaryPtsIO + ( + IOobject + ( + "pointPriority", + instance, + time(), + IOobject::NO_READ, + IOobject::NO_WRITE + ), + labelList(mesh.nPoints(), labelMin) + ); + + forAll(mesh.points(), ptI) + { + boundaryPtsIO[ptI] = mesh.pointZones().whichZone(ptI); + } + + Info<< nl << "Filtering faces on polyMesh" << nl << endl; - meshFilter.reset(new polyMeshFilter(mesh)); + meshFilter.reset(new polyMeshFilter(mesh, boundaryPtsIO)); meshFilter().filter(nInitialBadFaces); { @@ -1005,158 +1024,43 @@ void Foam::conformalVoronoiMesh::writeMesh << endl; } - -// volTensorField alignments -// ( -// IOobject -// ( -// "alignmentsField", -// runTime_.timeName(), -// runTime_, -// IOobject::NO_READ, -// IOobject::AUTO_WRITE -// ), -// mesh, -// tensor::zero -// ); -// -// forAll(mesh.cellCentres(), pI) -// { -// Vertex_handle nearV = -// nearest_vertex -// ( -// toPoint<Point>(mesh.cellCentres()[pI]) -// ); -// alignments[pI] = nearV->alignment(); -// } -// alignments.write(); -// -// { -// volVectorField alignmentx -// ( -// IOobject -// ( -// "alignmentsx", -// runTime_.timeName(), -// runTime_, -// IOobject::NO_READ, -// IOobject::AUTO_WRITE -// ), -// mesh, -// vector::zero -// ); -// forAll(alignmentx, aI) -// { -// alignmentx[aI] = alignments[aI].x(); -// } -// alignmentx.write(); -// } -// { -// volVectorField alignmenty -// ( -// IOobject -// ( -// "alignmentsy", -// runTime_.timeName(), -// runTime_, -// IOobject::NO_READ, -// IOobject::AUTO_WRITE -// ), -// mesh, -// vector::zero -// ); -// forAll(alignmenty, aI) -// { -// alignmenty[aI] = alignments[aI].y(); -// } -// alignmenty.write(); -// } -// { -// volVectorField alignmentz -// ( -// IOobject -// ( -// "alignmentsz", -// runTime_.timeName(), -// runTime_, -// IOobject::NO_READ, -// IOobject::AUTO_WRITE -// ), -// mesh, -// vector::zero -// ); -// forAll(alignmentz, aI) -// { -// alignmentz[aI] = alignments[aI].z(); -// } -// alignmentz.write(); -// } - - - labelIOList boundaryIOPts - ( - IOobject + { + pointScalarField boundaryPtsScalarField ( - "boundaryPoints", - instance, - runTime_, - IOobject::NO_READ, - IOobject::AUTO_WRITE - ), - boundaryPts - ); + IOobject + ( + "boundaryPoints_collapsed", + instance, + time(), + IOobject::NO_READ, + IOobject::AUTO_WRITE + ), + pointMesh::New(mesh), + scalar(labelMin) + ); - // Dump list of boundary points - forAll(mesh.boundaryMesh(), patchI) - { - const polyPatch& pp = mesh.boundaryMesh()[patchI]; + labelIOList boundaryPtsIO + ( + IOobject + ( + "pointPriority", + instance, + time(), + IOobject::NO_READ, + IOobject::AUTO_WRITE + ), + labelList(mesh.nPoints(), labelMin) + ); - if (!isA<coupledPolyPatch>(pp)) + forAll(mesh.points(), ptI) { - forAll(pp, fI) - { - const face& boundaryFace = pp[fI]; - - forAll(boundaryFace, pI) - { - const label boundaryPointI = boundaryFace[pI]; - - boundaryIOPts[boundaryPointI] = boundaryPts[boundaryPointI]; - } - } + boundaryPtsScalarField[ptI] = mesh.pointZones().whichZone(ptI); + boundaryPtsIO[ptI] = mesh.pointZones().whichZone(ptI); } - } - - boundaryIOPts.write(); -// forAllConstIter(labelHashSet, pointsInPatch, pI) -// { -// const Foam::point& ptMaster = mesh.points()[pI.key()]; -// -// forAllConstIter(labelHashSet, pointsInPatch, ptI) -// { -// if (ptI.key() != pI.key()) -// { -// const Foam::point& ptSlave = mesh.points()[ptI.key()]; -// -// const scalar dist = mag(ptMaster - ptSlave); -// if (ptMaster == ptSlave) -// { -// Pout<< "Point(" << pI.key() << ") " << ptMaster -// << " == " -// << "(" << ptI.key() << ") " << ptSlave -// << endl; -// } -// else if (dist == 0) -// { -// Pout<< "Point(" << pI.key() << ") " << ptMaster -// << " ~= " -// << "(" << ptI.key() << ") " << ptSlave -// << endl; -// } -// } -// } -// } + boundaryPtsScalarField.write(); + boundaryPtsIO.write(); + } // writeCellSizes(mesh); diff --git a/applications/utilities/mesh/generation/foamyHexMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCell/indexedCell.H b/applications/utilities/mesh/generation/foamyHexMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCell/indexedCell.H index 82bbe43b953..15b155d85b1 100644 --- a/applications/utilities/mesh/generation/foamyHexMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCell/indexedCell.H +++ b/applications/utilities/mesh/generation/foamyHexMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCell/indexedCell.H @@ -176,6 +176,9 @@ public: //- Does the Delaunay cell have a far point inline bool hasFarPoint() const; + //- Does the Delaunay cell have a referred point + inline bool hasReferredPoint() const; + //- Does the Delaunay cell have a feature point inline bool hasFeaturePoint() const; @@ -216,6 +219,8 @@ public: // least one Delaunay vertex outside and at least one inside inline bool boundaryDualVertex() const; + inline bool baffleBoundaryDualVertex() const; + //- A dual vertex on a feature edge will result from this Delaunay cell inline bool featureEdgeDualVertex() const; diff --git a/applications/utilities/mesh/generation/foamyHexMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCell/indexedCellI.H b/applications/utilities/mesh/generation/foamyHexMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCell/indexedCellI.H index 2f5d076138e..6c55a8eb307 100644 --- a/applications/utilities/mesh/generation/foamyHexMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCell/indexedCellI.H +++ b/applications/utilities/mesh/generation/foamyHexMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCell/indexedCellI.H @@ -189,6 +189,19 @@ inline bool CGAL::indexedCell<Gt, Cb>::hasFarPoint() const } +template<class Gt, class Cb> +inline bool CGAL::indexedCell<Gt, Cb>::hasReferredPoint() const +{ + return + ( + this->vertex(0)->referred() + || this->vertex(1)->referred() + || this->vertex(2)->referred() + || this->vertex(3)->referred() + ); +} + + template<class Gt, class Cb> inline bool CGAL::indexedCell<Gt, Cb>::hasFeaturePoint() const { @@ -372,6 +385,14 @@ inline bool CGAL::indexedCell<Gt, Cb>::anyInternalOrBoundaryDualVertex() const template<class Gt, class Cb> inline bool CGAL::indexedCell<Gt, Cb>::boundaryDualVertex() const { +// return +// ( +// this->vertex(0)->boundaryPoint() +// && this->vertex(1)->boundaryPoint() +// && this->vertex(2)->boundaryPoint() +// && this->vertex(3)->boundaryPoint() +// ); + return ( ( @@ -387,6 +408,41 @@ inline bool CGAL::indexedCell<Gt, Cb>::boundaryDualVertex() const || this->vertex(3)->externalBoundaryPoint() ) ); + +// Foam::label nBoundaryPoints = 0; +// +// for (Foam::label i = 0; i < 4; ++i) +// { +// Vertex_handle v = this->vertex(i); +// +// if (v->boundaryPoint()) +// { +// nBoundaryPoints++; +// } +// } +// +// return (nBoundaryPoints > 1); +} + + +template<class Gt, class Cb> +inline bool CGAL::indexedCell<Gt, Cb>::baffleBoundaryDualVertex() const +{ + return + ( + ( + this->vertex(0)->internalBafflePoint() + || this->vertex(1)->internalBafflePoint() + || this->vertex(2)->internalBafflePoint() + || this->vertex(3)->internalBafflePoint() + ) + && ( + this->vertex(0)->externalBafflePoint() + || this->vertex(1)->externalBafflePoint() + || this->vertex(2)->externalBafflePoint() + || this->vertex(3)->externalBafflePoint() + ) + ); } @@ -400,6 +456,31 @@ inline bool CGAL::indexedCell<Gt, Cb>::featureEdgeDualVertex() const && this->vertex(2)->featureEdgePoint() && this->vertex(3)->featureEdgePoint() ); +// ( +// this->vertex(0)->featureEdgePoint() +// || this->vertex(1)->featureEdgePoint() +// || this->vertex(2)->featureEdgePoint() +// || this->vertex(3)->featureEdgePoint() +// ) +// && ( +// ( +// this->vertex(0)->featureEdgePoint() +// || this->vertex(0)->featurePoint() +// ) +// && ( +// this->vertex(1)->featureEdgePoint() +// || this->vertex(1)->featurePoint() +// ) +// && ( +// this->vertex(2)->featureEdgePoint() +// || this->vertex(2)->featurePoint() +// ) +// && ( +// this->vertex(3)->featureEdgePoint() +// || this->vertex(3)->featurePoint() +// ) +// ) +// ); } diff --git a/applications/utilities/mesh/generation/foamyHexMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex/indexedVertex.H b/applications/utilities/mesh/generation/foamyHexMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex/indexedVertex.H index b556be66cc4..362e457d748 100644 --- a/applications/utilities/mesh/generation/foamyHexMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex/indexedVertex.H +++ b/applications/utilities/mesh/generation/foamyHexMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex/indexedVertex.H @@ -243,8 +243,10 @@ public: inline bool surfacePoint() const; inline bool internalBoundaryPoint() const; + inline bool internalBafflePoint() const; inline bool externalBoundaryPoint() const; + inline bool externalBafflePoint() const; inline bool constrained() const; diff --git a/applications/utilities/mesh/generation/foamyHexMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex/indexedVertexEnum.C b/applications/utilities/mesh/generation/foamyHexMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex/indexedVertexEnum.C index d0ac9717827..34c933e162f 100644 --- a/applications/utilities/mesh/generation/foamyHexMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex/indexedVertexEnum.C +++ b/applications/utilities/mesh/generation/foamyHexMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex/indexedVertexEnum.C @@ -30,13 +30,17 @@ License template<> const char* -Foam::NamedEnum<Foam::indexedVertexEnum::vertexType, 11>::names[] = +Foam::NamedEnum<Foam::indexedVertexEnum::vertexType, 15>::names[] = { "Unassigned", "Internal", "InternalNearBoundary", "InternalSurface", + "InternalSurfaceBaffle", + "ExternalSurfaceBaffle", "InternalFeatureEdge", + "InternalFeatureEdgeBaffle", + "ExternalFeatureEdgeBaffle", "InternalFeaturePoint", "ExternalSurface", "ExternalFeatureEdge", @@ -45,7 +49,7 @@ Foam::NamedEnum<Foam::indexedVertexEnum::vertexType, 11>::names[] = "Constrained" }; -const Foam::NamedEnum<Foam::indexedVertexEnum::vertexType, 11> +const Foam::NamedEnum<Foam::indexedVertexEnum::vertexType, 15> Foam::indexedVertexEnum::vertexTypeNames_; diff --git a/applications/utilities/mesh/generation/foamyHexMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex/indexedVertexEnum.H b/applications/utilities/mesh/generation/foamyHexMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex/indexedVertexEnum.H index 072470d6732..c606f815d2d 100644 --- a/applications/utilities/mesh/generation/foamyHexMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex/indexedVertexEnum.H +++ b/applications/utilities/mesh/generation/foamyHexMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex/indexedVertexEnum.H @@ -49,17 +49,21 @@ public: enum vertexType { - vtUnassigned = 0, - vtInternal = 1, - vtInternalNearBoundary = 2, - vtInternalSurface = 3, - vtInternalFeatureEdge = 4, - vtInternalFeaturePoint = 5, - vtExternalSurface = 6, - vtExternalFeatureEdge = 7, - vtExternalFeaturePoint = 8, - vtFar = 9, - vtConstrained = 10 + vtUnassigned = 0, + vtInternal = 1, + vtInternalNearBoundary = 2, + vtInternalSurface = 3, + vtInternalSurfaceBaffle = 4, + vtExternalSurfaceBaffle = 5, + vtInternalFeatureEdge = 6, + vtInternalFeatureEdgeBaffle = 7, + vtExternalFeatureEdgeBaffle = 8, + vtInternalFeaturePoint = 9, + vtExternalSurface = 10, + vtExternalFeatureEdge = 11, + vtExternalFeaturePoint = 12, + vtFar = 13, + vtConstrained = 14 }; enum vertexMotion @@ -68,7 +72,7 @@ public: movable = 1 }; - static const Foam::NamedEnum<vertexType, 11> vertexTypeNames_; + static const Foam::NamedEnum<vertexType, 15> vertexTypeNames_; static const Foam::NamedEnum<vertexMotion, 2> vertexMotionNames_; diff --git a/applications/utilities/mesh/generation/foamyHexMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex/indexedVertexI.H b/applications/utilities/mesh/generation/foamyHexMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex/indexedVertexI.H index 76a77da47dd..c5930395c3d 100644 --- a/applications/utilities/mesh/generation/foamyHexMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex/indexedVertexI.H +++ b/applications/utilities/mesh/generation/foamyHexMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex/indexedVertexI.H @@ -307,6 +307,16 @@ inline bool CGAL::indexedVertex<Gt, Vb>::internalBoundaryPoint() const return type_ >= vtInternalSurface && type_ <= vtInternalFeaturePoint; } +template<class Gt, class Vb> +inline bool CGAL::indexedVertex<Gt, Vb>::internalBafflePoint() const +{ + return + ( + type_ == vtInternalSurfaceBaffle + || type_ == vtInternalFeatureEdgeBaffle + ); +} + template<class Gt, class Vb> inline bool CGAL::indexedVertex<Gt, Vb>::externalBoundaryPoint() const @@ -314,6 +324,16 @@ inline bool CGAL::indexedVertex<Gt, Vb>::externalBoundaryPoint() const return type_ >= vtExternalSurface && type_ <= vtExternalFeaturePoint; } +template<class Gt, class Vb> +inline bool CGAL::indexedVertex<Gt, Vb>::externalBafflePoint() const +{ + return + ( + type_ == vtExternalSurfaceBaffle + || type_ == vtExternalFeatureEdgeBaffle + ); +} + template<class Gt, class Vb> inline bool CGAL::indexedVertex<Gt, Vb>::constrained() const diff --git a/src/dynamicMesh/Make/files b/src/dynamicMesh/Make/files index 6429d3b4a5d..f769607f949 100644 --- a/src/dynamicMesh/Make/files +++ b/src/dynamicMesh/Make/files @@ -99,6 +99,7 @@ createShellMesh/createShellMesh.C extrudePatchMesh/extrudePatchMesh.C +polyMeshFilter/polyMeshFilterSettings.C polyMeshFilter/polyMeshFilter.C LIB = $(FOAM_LIBBIN)/libdynamicMesh diff --git a/src/dynamicMesh/polyMeshFilter/polyMeshFilter.C b/src/dynamicMesh/polyMeshFilter/polyMeshFilter.C index 0c18d84e4fd..7e629d1c3c9 100644 --- a/src/dynamicMesh/polyMeshFilter/polyMeshFilter.C +++ b/src/dynamicMesh/polyMeshFilter/polyMeshFilter.C @@ -78,1100 +78,894 @@ Foam::autoPtr<Foam::fvMesh> Foam::polyMeshFilter::copyMesh(const fvMesh& mesh) // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // -void Foam::polyMeshFilter::updatePointErrorCount -( - const PackedBoolList& isErrorPoint, - const labelList& oldToNewMesh, - labelList& pointErrorCount -) const +Foam::label Foam::polyMeshFilter::filterFacesLoop(const label nOriginalBadFaces) { - forAll(mesh_.points(), pI) - { - if (isErrorPoint[oldToNewMesh[pI]]) - { - pointErrorCount[pI]++; - } - } -} + label nBadFaces = labelMax; + label nOuterIterations = 0; + // Maintain the number of times a point has been part of a bad face + labelList pointErrorCount(mesh_.nPoints(), 0); -void Foam::polyMeshFilter::checkMeshEdgesAndRelaxEdges -( - const polyMesh& newMesh, - const labelList& oldToNewMesh, - const PackedBoolList& isErrorPoint, - const labelList& pointErrorCount -) -{ - const edgeList& edges = mesh_.edges(); + PackedBoolList newErrorPoint(mesh_.nPoints()); + edgeCollapser::checkMeshQuality + ( + mesh_, + meshQualityCoeffDict(), + newErrorPoint + ); - forAll(edges, edgeI) + bool newBadFaces = true; + + // Main loop + // ~~~~~~~~~ + // It tries and do some collapses, checks the resulting mesh and + // 'freezes' some edges (by marking in minEdgeLen) and tries again. + // This will iterate ultimately to the situation where every edge is + // frozen and nothing gets collapsed. + while + ( + nOuterIterations < maxIterations() + //&& nBadFaces > nOriginalBadFaces + && newBadFaces + ) { - const edge& e = edges[edgeI]; - label newStart = oldToNewMesh[e[0]]; - label newEnd = oldToNewMesh[e[1]]; + Info<< nl << "Outer Iteration = " << nOuterIterations++ << nl + << endl; - if - ( - pointErrorCount[e[0]] >= maxPointErrorCount_ - || pointErrorCount[e[1]] >= maxPointErrorCount_ - ) - { - minEdgeLen_[edgeI] = 0; - } + printScalarFieldStats("Edge Filter Factor", minEdgeLen_); + printScalarFieldStats("Face Filter Factor", faceFilterFactor_); - if - ( - (newStart >= 0 && isErrorPoint[newStart]) - || (newEnd >= 0 && isErrorPoint[newEnd]) - ) - { - minEdgeLen_[edgeI] *= edgeReductionFactor_; - } - } + // Reset the new mesh to the old mesh + newMeshPtr_ = copyMesh(mesh_); + fvMesh& newMesh = newMeshPtr_(); - syncTools::syncEdgeList(mesh_, minEdgeLen_, minEqOp<scalar>(), scalar(0.0)); + scalarField newMeshFaceFilterFactor = faceFilterFactor_; + pointPriority_.reset(new labelList(originalPointPriority_)); + + labelList origToCurrentPointMap(identity(newMesh.nPoints())); - for (label smoothIter = 0; smoothIter < maxSmoothIters_; ++smoothIter) - { - // Smooth minEdgeLen - forAll(mesh_.edges(), edgeI) { - const edge& e = mesh_.edges()[edgeI]; + label nInnerIterations = 0; + label nPrevLocalCollapse = labelMax; - scalar sumMinEdgeLen = 0; - label nEdges = 0; + Info<< incrIndent; - forAll(e, pointI) + while (true) { - const labelList& pEdges = mesh_.pointEdges()[e[pointI]]; + Info<< nl << indent << "Inner iteration = " + << nInnerIterations++ << nl << incrIndent << endl; - forAll(pEdges, pEdgeI) + label nLocalCollapse = filterFaces + ( + newMesh, + newMeshFaceFilterFactor, + origToCurrentPointMap + ); + Info<< decrIndent; + + if + ( + nLocalCollapse >= nPrevLocalCollapse + || nLocalCollapse == 0 + ) { - const label pEdge = pEdges[pEdgeI]; - sumMinEdgeLen += minEdgeLen_[pEdge]; - nEdges++; + Info<< decrIndent; + break; + } + else + { + nPrevLocalCollapse = nLocalCollapse; } } - - minEdgeLen_[edgeI] = min - ( - minEdgeLen_[edgeI], - sumMinEdgeLen/nEdges - ); } - syncTools::syncEdgeList - ( - mesh_, - minEdgeLen_, - minEqOp<scalar>(), - scalar(0.0) - ); - } -} - - -void Foam::polyMeshFilter::checkMeshFacesAndRelaxEdges -( - const polyMesh& newMesh, - const labelList& oldToNewMesh, - const PackedBoolList& isErrorPoint, - const labelList& pointErrorCount -) -{ - const faceList& faces = mesh_.faces(); - - forAll(faces, faceI) - { - const face& f = faces[faceI]; + scalarField newMeshMinEdgeLen = minEdgeLen_; - forAll(f, fpI) { - const label ptIndex = oldToNewMesh[f[fpI]]; + label nInnerIterations = 0; + label nPrevLocalCollapse = labelMax; - if (pointErrorCount[f[fpI]] >= maxPointErrorCount_) - { - faceFilterFactor_[faceI] = 0; - } + Info<< incrIndent; - if (isErrorPoint[ptIndex]) + while (true) { - faceFilterFactor_[faceI] *= faceReductionFactor_; - - break; - } - } - } - - syncTools::syncFaceList(mesh_, faceFilterFactor_, minEqOp<scalar>()); - - for (label smoothIter = 0; smoothIter < maxSmoothIters_; ++smoothIter) - { - // Smooth faceFilterFactor - forAll(faces, faceI) - { - const labelList& fEdges = mesh_.faceEdges()[faceI]; - - scalar sumFaceFilterFactors = 0; - label nFaces = 0; - - // This is important: Only smooth around faces that share an - // edge with a bad face - bool skipFace = true; + Info<< nl << indent << "Inner iteration = " + << nInnerIterations++ << nl << incrIndent << endl; - forAll(fEdges, fEdgeI) - { - const labelList& eFaces = mesh_.edgeFaces()[fEdges[fEdgeI]]; + label nLocalCollapse = filterEdges + ( + newMesh, + newMeshMinEdgeLen, + origToCurrentPointMap + ); + Info<< decrIndent; - forAll(eFaces, eFaceI) + if + ( + nLocalCollapse >= nPrevLocalCollapse + || nLocalCollapse == 0 + ) { - const label eFace = eFaces[eFaceI]; - - const face& f = faces[eFace]; - - forAll(f, fpI) - { - const label ptIndex = oldToNewMesh[f[fpI]]; - - if (isErrorPoint[ptIndex]) - { - skipFace = false; - break; - } - } - - if (eFace != faceI) - { - sumFaceFilterFactors += faceFilterFactor_[eFace]; - nFaces++; - } + Info<< decrIndent; + break; + } + else + { + nPrevLocalCollapse = nLocalCollapse; } } + } - if (skipFace) - { - continue; - } - faceFilterFactor_[faceI] = min + // Mesh check + // ~~~~~~~~~~~~~~~~~~ + // Do not allow collapses in regions of error. + // Updates minEdgeLen, nRelaxedEdges + + if (controlMeshQuality()) + { + PackedBoolList isErrorPoint(newMesh.nPoints()); + nBadFaces = edgeCollapser::checkMeshQuality ( - faceFilterFactor_[faceI], - sumFaceFilterFactors/nFaces + newMesh, + meshQualityCoeffDict(), + isErrorPoint ); - } - - // Face filter factor needs to be synchronised! - syncTools::syncFaceList(mesh_, faceFilterFactor_, minEqOp<scalar>()); - } -} + Info<< nl << " Number of bad faces : " << nBadFaces << nl + << " Number of marked points : " + << returnReduce(isErrorPoint.count(), sumOp<unsigned int>()) + << endl; -Foam::labelList Foam::polyMeshFilter::findBoundaryPoints -( - const polyMesh& mesh//, -// labelIOList& boundaryIOPts -) const -{ - const polyBoundaryMesh& bMesh = mesh.boundaryMesh(); + updatePointErrorCount + ( + isErrorPoint, + origToCurrentPointMap, + pointErrorCount + ); - labelList boundaryPoint(mesh.nPoints(), -1); + checkMeshEdgesAndRelaxEdges + ( + newMesh, + origToCurrentPointMap, + isErrorPoint, + pointErrorCount + ); - // Get all processor boundary points and the processor patch label - // that they are on. - forAll(bMesh, patchI) - { - const polyPatch& patch = bMesh[patchI]; + checkMeshFacesAndRelaxEdges + ( + newMesh, + origToCurrentPointMap, + isErrorPoint, + pointErrorCount + ); - if (!isA<coupledPolyPatch>(patch)) - { - forAll(patch, fI) + newBadFaces = false; + forAll(mesh_.points(), pI) { - const face& f = patch[fI]; - - forAll(f, fp) + if (isErrorPoint[origToCurrentPointMap[pI]]) { - boundaryPoint[f[fp]] = 0; //boundaryIOPts[f[fp]]; + if (!newErrorPoint[pI]) + { + newBadFaces = true; + break; + } } } - } - } - - syncTools::syncPointList - ( - mesh, - boundaryPoint, - maxEqOp<label>(), - labelMin - ); - - return boundaryPoint; -} - - -void Foam::polyMeshFilter::printScalarFieldStats -( - const string desc, - const scalarField& fld -) const -{ - Info<< incrIndent << indent << desc - << ": min = " << returnReduce(min(fld), minOp<scalar>()) - << " av = " - << returnReduce(sum(fld), sumOp<scalar>()) - /returnReduce(fld.size(), sumOp<label>()) - << " max = " << returnReduce(max(fld), maxOp<scalar>()) - << decrIndent << endl; -} - -void Foam::polyMeshFilter::mapOldMeshEdgeFieldToNewMesh -( - const polyMesh& newMesh, - const labelList& pointMap, - scalarField& newMeshMinEdgeLen -) const -{ - scalarField tmp(newMesh.nEdges()); - - const edgeList& newEdges = newMesh.edges(); - - forAll(newEdges, newEdgeI) - { - const edge& newEdge = newEdges[newEdgeI]; - const label pStart = newEdge.start(); - const label pEnd = newEdge.end(); - - tmp[newEdgeI] = min - ( - newMeshMinEdgeLen[pointMap[pStart]], - newMeshMinEdgeLen[pointMap[pEnd]] - ); - } - - newMeshMinEdgeLen.transfer(tmp); - - syncTools::syncEdgeList - ( - newMesh, - newMeshMinEdgeLen, - maxEqOp<scalar>(), - scalar(0.0) - ); -} - - -void Foam::polyMeshFilter::mapOldMeshFaceFieldToNewMesh -( - const polyMesh& newMesh, - const labelList& faceMap, - scalarField& newMeshFaceFilterFactor -) const -{ - scalarField tmp(newMesh.nFaces()); - - forAll(faceMap, newFaceI) - { - const label oldFaceI = faceMap[newFaceI]; - - tmp[newFaceI] = newMeshFaceFilterFactor[oldFaceI]; - } - - newMeshFaceFilterFactor.transfer(tmp); - - syncTools::syncFaceList - ( - newMesh, - newMeshFaceFilterFactor, - maxEqOp<scalar>() - ); + reduce(newBadFaces, orOp<bool>()); + } + else + { + return -1; + } + } + + return nBadFaces; } -void Foam::polyMeshFilter::updateOldToNewPointMap +Foam::label Foam::polyMeshFilter::filterFaces ( - const labelList& currToNew, + polyMesh& newMesh, + scalarField& newMeshFaceFilterFactor, labelList& origToCurrentPointMap -) const +) { - forAll(origToCurrentPointMap, origPointI) + // Per edge collapse status + PackedBoolList collapseEdge(newMesh.nEdges()); + + Map<point> collapsePointToLocation(newMesh.nPoints()); + + edgeCollapser collapser(newMesh, collapseFacesCoeffDict()); + { - label oldPointI = origToCurrentPointMap[origPointI]; + // Collapse faces + labelPair nCollapsedPtEdge = collapser.markSmallSliverFaces + ( + newMeshFaceFilterFactor, + pointPriority_(), + collapseEdge, + collapsePointToLocation + ); - if (oldPointI < currToNew.size()) + label nCollapsed = 0; + forAll(nCollapsedPtEdge, collapseTypeI) { - label newPointI = currToNew[oldPointI]; + nCollapsed += nCollapsedPtEdge[collapseTypeI]; + } - if (newPointI != -1) - { - origToCurrentPointMap[origPointI] = newPointI; - } + reduce(nCollapsed, sumOp<label>()); + + label nToPoint = returnReduce(nCollapsedPtEdge.first(), sumOp<label>()); + label nToEdge = returnReduce(nCollapsedPtEdge.second(), sumOp<label>()); + + Info<< indent + << "Collapsing " << nCollapsed << " faces " + << "(to point = " << nToPoint << ", to edge = " << nToEdge << ")" + << endl; + + if (nCollapsed == 0) + { + return 0; } } -} - -// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + // Merge edge collapses into consistent collapse-network. + // Make sure no cells get collapsed. + List<pointEdgeCollapse> allPointInfo; + const globalIndex globalPoints(newMesh.nPoints()); -Foam::polyMeshFilter::polyMeshFilter(const fvMesh& mesh) -: - mesh_(mesh), - newMeshPtr_(), - dict_ - ( - IOobject - ( - "collapseDict", - mesh.time().system(), - mesh.time(), - IOobject::MUST_READ, - IOobject::NO_WRITE - ) - ), - controlMeshQuality_ - ( - dict_.lookupOrDefault<Switch>("controlMeshQuality", false) - ), - collapseEdgesCoeffDict_(dict_.subDict("collapseEdgesCoeffs")), - collapseFacesCoeffDict_(dict_.subOrEmptyDict("collapseFacesCoeffs")), - meshQualityCoeffDict_(dict_.subOrEmptyDict("controlMeshQualityCoeffs")), - minLen_(readScalar(collapseEdgesCoeffDict_.lookup("minimumEdgeLength"))), - maxCos_ - ( - ::cos - ( - degToRad - ( - readScalar(collapseEdgesCoeffDict_.lookup("maximumMergeAngle")) - ) - ) - ), - edgeReductionFactor_ - ( - meshQualityCoeffDict_.lookupOrDefault<scalar>("edgeReductionFactor", -1) - ), - maxIterations_ - ( - meshQualityCoeffDict_.lookupOrAddDefault<label>("maximumIterations", 1) - ), - maxSmoothIters_ - ( - meshQualityCoeffDict_.lookupOrAddDefault<label> - ( - "maximumSmoothingIterations", - 0 - ) - ), - initialFaceLengthFactor_ - ( - collapseFacesCoeffDict_.lookupOrAddDefault<scalar> - ( - "initialFaceLengthFactor", - -1 - ) - ), - faceReductionFactor_ - ( - meshQualityCoeffDict_.lookupOrAddDefault<scalar> - ( - "faceReductionFactor", - -1 - ) - ), - maxPointErrorCount_ + collapser.consistentCollapse ( - meshQualityCoeffDict_.lookupOrAddDefault<label>("maxPointErrorCount", 0) - ), - minEdgeLen_(), - faceFilterFactor_() -{ - Info<< "Merging:" << nl - << " edges with length less than " << minLen_ << " metres" << nl - << " edges split by a point with edges in line to within " - << radToDeg(::acos(maxCos_)) << " degrees" << nl - << " Minimum edge length reduction factor = " - << edgeReductionFactor_ << nl - << endl; + globalPoints, + pointPriority_(), + collapsePointToLocation, + collapseEdge, + allPointInfo + ); - if (collapseFacesCoeffDict_.empty()) - { - Info<< "Face collapsing is off" << endl; - } - else + label nLocalCollapse = collapseEdge.count(); + + reduce(nLocalCollapse, sumOp<label>()); + Info<< nl << indent << "Collapsing " << nLocalCollapse + << " edges after synchronisation and PointEdgeWave" << endl; + + if (nLocalCollapse == 0) { - Info<< "Face collapsing is on" << endl; - Info<< " Initial face length factor = "<< initialFaceLengthFactor_ - << endl; + return 0; } - Info<< "Control mesh quality = " << controlMeshQuality_.asText() << endl; - - if (controlMeshQuality_) { - Info<< " Minimum edge length reduction factor = " - << edgeReductionFactor_ << nl - << " Minimum face area reduction factor = " - << faceReductionFactor_ << endl; + // Apply collapses to current mesh + polyTopoChange newMeshMod(newMesh); - Info<< " Maximum number of collapse iterations = " << maxIterations_ - << endl; + // Insert mesh refinement into polyTopoChange. + collapser.setRefinement(allPointInfo, newMeshMod); - Info<< " Maximum number of edge/face reduction factor smoothing " - << "iterations = " << maxSmoothIters_ << endl; + Info<< indent << "Apply changes to the current mesh" << endl; - Info<< " Maximum number of times a point can contribute to bad " - << "faces across " << nl - << " collapse iterations = " << maxPointErrorCount_ - << endl; - } + // Apply changes to current mesh + autoPtr<mapPolyMesh> newMapPtr = newMeshMod.changeMesh + ( + newMesh, + false + ); + const mapPolyMesh& newMap = newMapPtr(); - Info<< "Selectively disabling wanted collapses until resulting quality" - << " satisfies constraints in system/meshQualityDict" << nl - << endl; -} + // Update fields + newMesh.updateMesh(newMap); + if (newMap.hasMotionPoints()) + { + newMesh.movePoints(newMap.preMotionPoints()); + } + updatePointPriorities(newMesh, newMap.pointMap()); -// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + mapOldMeshFaceFieldToNewMesh + ( + newMesh, + newMap.faceMap(), + newMeshFaceFilterFactor + ); -Foam::polyMeshFilter::~polyMeshFilter() -{} + updateOldToNewPointMap + ( + newMap.reversePointMap(), + origToCurrentPointMap + ); + } + return nLocalCollapse; +} -// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // -Foam::label Foam::polyMeshFilter::filter(const label nOriginalBadFaces) +Foam::label Foam::polyMeshFilter::filterEdges +( + polyMesh& newMesh, + scalarField& newMeshMinEdgeLen, + labelList& origToCurrentPointMap +) { - label nBadFaces = labelMax; - label nOuterIterations = 0; + // Per edge collapse status + PackedBoolList collapseEdge(newMesh.nEdges()); - minEdgeLen_.resize(mesh_.nEdges(), minLen_); - faceFilterFactor_.resize(mesh_.nFaces(), initialFaceLengthFactor_); + Map<point> collapsePointToLocation(newMesh.nPoints()); - // Maintain the number of times a point has been part of a bad face - labelList pointErrorCount(mesh_.nPoints(), 0); + edgeCollapser collapser(newMesh, collapseFacesCoeffDict()); - PackedBoolList newErrorPoint(mesh_.nPoints()); - edgeCollapser::checkMeshQuality + // Work out which edges to collapse + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // This is by looking at minEdgeLen (to avoid frozen edges) + // and marking in collapseEdge. + label nSmallCollapsed = collapser.markSmallEdges ( - mesh_, - meshQualityCoeffDict_, - newErrorPoint + newMeshMinEdgeLen, + pointPriority_(), + collapseEdge, + collapsePointToLocation ); - bool newBadFaces = true; + reduce(nSmallCollapsed, sumOp<label>()); + Info<< indent << "Collapsing " << nSmallCollapsed + << " small edges" << endl; - // Main loop - // ~~~~~~~~~ - // It tries and do some collapses, checks the resulting mesh and - // 'freezes' some edges (by marking in minEdgeLen) and tries again. - // This will iterate ultimately to the situation where every edge is - // frozen and nothing gets collapsed. - while + // Merge inline edges + label nMerged = collapser.markMergeEdges ( - nOuterIterations < maxIterations_ - //&& nBadFaces > nOriginalBadFaces - && newBadFaces - ) - { - Info<< nl << "Outer Iteration = " << nOuterIterations++ << nl - << endl; - - printScalarFieldStats("Edge Filter Factor", minEdgeLen_); - printScalarFieldStats("Face Filter Factor", faceFilterFactor_); - - // Reset the new mesh to the old mesh - newMeshPtr_ = copyMesh(mesh_); - fvMesh& newMesh = newMeshPtr_(); + maxCos(), + pointPriority_(), + collapseEdge, + collapsePointToLocation + ); - scalarField newMeshFaceFilterFactor = faceFilterFactor_; + reduce(nMerged, sumOp<label>()); + Info<< indent << "Collapsing " << nMerged << " in line edges" + << endl; - labelList origToCurrentPointMap(identity(newMesh.nPoints())); - { + if (nMerged + nSmallCollapsed == 0) + { + return 0; + } - label nInnerIterations = 0; - label nPrevLocalCollapse = labelMax; + // Merge edge collapses into consistent collapse-network. + // Make sure no cells get collapsed. + List<pointEdgeCollapse> allPointInfo; + const globalIndex globalPoints(newMesh.nPoints()); - Info<< incrIndent; + collapser.consistentCollapse + ( + globalPoints, + pointPriority_(), + collapsePointToLocation, + collapseEdge, + allPointInfo + ); - while (true) - { - Info<< nl << indent << "Inner iteration = " - << nInnerIterations++ << nl << incrIndent << endl; + label nLocalCollapse = collapseEdge.count(); - // Per edge collapse status - PackedBoolList collapseEdge(newMesh.nEdges()); + reduce(nLocalCollapse, sumOp<label>()); + Info<< nl << indent << "Collapsing " << nLocalCollapse + << " edges after synchronisation and PointEdgeWave" << endl; - Map<point> collapsePointToLocation(newMesh.nPoints()); + if (nLocalCollapse == 0) + { + return 0; + } - // Mark points on boundary - const labelList boundaryPoint = findBoundaryPoints(newMesh); + // Apply collapses to current mesh + polyTopoChange newMeshMod(newMesh); - edgeCollapser collapser(newMesh, collapseFacesCoeffDict_); + // Insert mesh refinement into polyTopoChange. + collapser.setRefinement(allPointInfo, newMeshMod); - { - // Collapse faces - labelPair nCollapsedPtEdge = collapser.markSmallSliverFaces - ( - newMeshFaceFilterFactor, - boundaryPoint, - collapseEdge, - collapsePointToLocation - ); - - label nCollapsed = 0; - forAll(nCollapsedPtEdge, collapseTypeI) - { - nCollapsed += nCollapsedPtEdge[collapseTypeI]; - } + Info<< indent << "Apply changes to the current mesh" << endl; - reduce(nCollapsed, sumOp<label>()); - - Info<< indent - << "Collapsing " << nCollapsed << " faces" - << " (to point = " - << returnReduce - ( - nCollapsedPtEdge.first(), - sumOp<label>() - ) - << ", to edge = " - << returnReduce - ( - nCollapsedPtEdge.second(), - sumOp<label>() - ) - << ")" << endl; - - if (nCollapsed == 0) - { - Info<< decrIndent; - Info<< decrIndent; - break; - } - } + // Apply changes to current mesh + autoPtr<mapPolyMesh> newMapPtr = newMeshMod.changeMesh + ( + newMesh, + false + ); + const mapPolyMesh& newMap = newMapPtr(); - // Merge edge collapses into consistent collapse-network. - // Make sure no cells get collapsed. - List<pointEdgeCollapse> allPointInfo; - const globalIndex globalPoints(newMesh.nPoints()); + // Update fields + newMesh.updateMesh(newMap); + if (newMap.hasMotionPoints()) + { + newMesh.movePoints(newMap.preMotionPoints()); + } - collapser.consistentCollapse - ( - globalPoints, - boundaryPoint, - collapsePointToLocation, - collapseEdge, - allPointInfo - ); + // Synchronise the factors + mapOldMeshEdgeFieldToNewMesh + ( + newMesh, + newMap.pointMap(), + newMeshMinEdgeLen + ); - label nLocalCollapse = collapseEdge.count(); + updateOldToNewPointMap + ( + newMap.reversePointMap(), + origToCurrentPointMap + ); - reduce(nLocalCollapse, sumOp<label>()); - Info<< nl << indent << "Collapsing " << nLocalCollapse - << " edges after synchronisation and PointEdgeWave" << endl; + updatePointPriorities(newMesh, newMap.pointMap()); - if (nLocalCollapse >= nPrevLocalCollapse) - { - Info<< decrIndent; - Info<< decrIndent; - break; - } - else - { - nPrevLocalCollapse = nLocalCollapse; - } + return nLocalCollapse; +} - { - // Apply collapses to current mesh - polyTopoChange newMeshMod(newMesh); - - // Insert mesh refinement into polyTopoChange. - collapser.setRefinement(allPointInfo, newMeshMod); - - Info<< indent << "Apply changes to the current mesh" - << decrIndent << endl; - - // Apply changes to current mesh - autoPtr<mapPolyMesh> newMapPtr = newMeshMod.changeMesh - ( - newMesh, - false - ); - const mapPolyMesh& newMap = newMapPtr(); - - // Update fields - newMesh.updateMesh(newMap); - if (newMap.hasMotionPoints()) - { - newMesh.movePoints(newMap.preMotionPoints()); - } - // Relabel the boundary points - // labelList newBoundaryPoints(newMesh.nPoints(), -1); - // forAll(newBoundaryPoints, pI) - // { - // const label newToOldptI= map.pointMap()[pI]; - // newBoundaryPoints[pI] = boundaryIOPts[newToOldptI]; - // } - // boundaryIOPts = newBoundaryPoints; - - - mapOldMeshFaceFieldToNewMesh - ( - newMesh, - newMap.faceMap(), - newMeshFaceFilterFactor - ); - - updateOldToNewPointMap - ( - newMap.reversePointMap(), - origToCurrentPointMap - ); - } - } +void Foam::polyMeshFilter::updatePointErrorCount +( + const PackedBoolList& isErrorPoint, + const labelList& oldToNewMesh, + labelList& pointErrorCount +) const +{ + forAll(mesh_.points(), pI) + { + if (isErrorPoint[oldToNewMesh[pI]]) + { + pointErrorCount[pI]++; } + } +} - scalarField newMeshMinEdgeLen = minEdgeLen_; +void Foam::polyMeshFilter::checkMeshEdgesAndRelaxEdges +( + const polyMesh& newMesh, + const labelList& oldToNewMesh, + const PackedBoolList& isErrorPoint, + const labelList& pointErrorCount +) +{ + const edgeList& edges = mesh_.edges(); - label nInnerIterations = 0; - label nPrevLocalCollapse = labelMax; + forAll(edges, edgeI) + { + const edge& e = edges[edgeI]; + label newStart = oldToNewMesh[e[0]]; + label newEnd = oldToNewMesh[e[1]]; - while (true) + if + ( + pointErrorCount[e[0]] >= maxPointErrorCount() + || pointErrorCount[e[1]] >= maxPointErrorCount() + ) { - Info<< nl << indent << "Inner iteration = " - << nInnerIterations++ << nl << incrIndent << endl; - - // Per edge collapse status - PackedBoolList collapseEdge(newMesh.nEdges()); - - Map<point> collapsePointToLocation(newMesh.nPoints()); - - // Mark points on boundary - const labelList boundaryPoint = findBoundaryPoints - ( - newMesh//, -// boundaryIOPts - ); - - edgeCollapser collapser(newMesh, collapseFacesCoeffDict_); + minEdgeLen_[edgeI] = -1; + } - // Work out which edges to collapse - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // This is by looking at minEdgeLen (to avoid frozen edges) - // and marking in collapseEdge. - label nSmallCollapsed = collapser.markSmallEdges - ( - newMeshMinEdgeLen, - boundaryPoint, - collapseEdge, - collapsePointToLocation - ); + if + ( + (newStart >= 0 && isErrorPoint[newStart]) + || (newEnd >= 0 && isErrorPoint[newEnd]) + ) + { + minEdgeLen_[edgeI] *= edgeReductionFactor(); + } + } - reduce(nSmallCollapsed, sumOp<label>()); - Info<< indent << "Collapsing " << nSmallCollapsed - << " small edges" << endl; + syncTools::syncEdgeList(mesh_, minEdgeLen_, minEqOp<scalar>(), scalar(0.0)); - // Merge inline edges - label nMerged = collapser.markMergeEdges - ( - maxCos_, - boundaryPoint, - collapseEdge, - collapsePointToLocation - ); + for (label smoothIter = 0; smoothIter < maxSmoothIters(); ++smoothIter) + { + // Smooth minEdgeLen + forAll(mesh_.edges(), edgeI) + { + const edge& e = mesh_.edges()[edgeI]; - reduce(nMerged, sumOp<label>()); - Info<< indent << "Collapsing " << nMerged << " in line edges" - << endl; + scalar sumMinEdgeLen = 0; + label nEdges = 0; - if (nMerged + nSmallCollapsed == 0) + forAll(e, pointI) { - Info<< decrIndent; - break; + const labelList& pEdges = mesh_.pointEdges()[e[pointI]]; + + forAll(pEdges, pEdgeI) + { + const label pEdge = pEdges[pEdgeI]; + sumMinEdgeLen += minEdgeLen_[pEdge]; + nEdges++; + } } - // Merge edge collapses into consistent collapse-network. - // Make sure no cells get collapsed. - List<pointEdgeCollapse> allPointInfo; - const globalIndex globalPoints(newMesh.nPoints()); - - collapser.consistentCollapse + minEdgeLen_[edgeI] = min ( - globalPoints, - boundaryPoint, - collapsePointToLocation, - collapseEdge, - allPointInfo + minEdgeLen_[edgeI], + sumMinEdgeLen/nEdges ); + } - label nLocalCollapse = collapseEdge.count(); - - reduce(nLocalCollapse, sumOp<label>()); - Info<< nl << indent << "Collapsing " << nLocalCollapse - << " edges after synchronisation and PointEdgeWave" << endl; - - if (nLocalCollapse >= nPrevLocalCollapse) - { - Info<< decrIndent; - break; - } - else - { - nPrevLocalCollapse = nLocalCollapse; - } + syncTools::syncEdgeList + ( + mesh_, + minEdgeLen_, + minEqOp<scalar>(), + scalar(0.0) + ); + } +} - // Apply collapses to current mesh - polyTopoChange newMeshMod(newMesh); - // Insert mesh refinement into polyTopoChange. - collapser.setRefinement(allPointInfo, newMeshMod); +void Foam::polyMeshFilter::checkMeshFacesAndRelaxEdges +( + const polyMesh& newMesh, + const labelList& oldToNewMesh, + const PackedBoolList& isErrorPoint, + const labelList& pointErrorCount +) +{ + const faceList& faces = mesh_.faces(); - Info<< indent << "Apply changes to the current mesh" - << decrIndent << endl; + forAll(faces, faceI) + { + const face& f = faces[faceI]; - // Apply changes to current mesh - autoPtr<mapPolyMesh> newMapPtr = newMeshMod.changeMesh - ( - newMesh, - false - ); - const mapPolyMesh& newMap = newMapPtr(); + forAll(f, fpI) + { + const label ptIndex = oldToNewMesh[f[fpI]]; - // Update fields - newMesh.updateMesh(newMap); - if (newMap.hasMotionPoints()) + if (pointErrorCount[f[fpI]] >= maxPointErrorCount()) { - newMesh.movePoints(newMap.preMotionPoints()); + faceFilterFactor_[faceI] = -1; } - // Relabel the boundary points -// labelList newBoundaryPoints(newMesh.nPoints(), -1); -// forAll(newBoundaryPoints, pI) -// { -// const label newToOldptI= map.pointMap()[pI]; -// newBoundaryPoints[pI] = boundaryIOPts[newToOldptI]; -// } -// boundaryIOPts = newBoundaryPoints; - - // Synchronise the factors - mapOldMeshEdgeFieldToNewMesh - ( - newMesh, - newMap.pointMap(), - newMeshMinEdgeLen - ); + if (isErrorPoint[ptIndex]) + { + faceFilterFactor_[faceI] *= faceReductionFactor(); - updateOldToNewPointMap - ( - newMap.reversePointMap(), - origToCurrentPointMap - ); + break; + } } + } + syncTools::syncFaceList(mesh_, faceFilterFactor_, minEqOp<scalar>()); - // Mesh check - // ~~~~~~~~~~~~~~~~~~ - // Do not allow collapses in regions of error. - // Updates minEdgeLen, nRelaxedEdges - - if (controlMeshQuality_) + for (label smoothIter = 0; smoothIter < maxSmoothIters(); ++smoothIter) + { + // Smooth faceFilterFactor + forAll(faces, faceI) { - PackedBoolList isErrorPoint(newMesh.nPoints()); - nBadFaces = edgeCollapser::checkMeshQuality - ( - newMesh, - meshQualityCoeffDict_, - isErrorPoint - ); - - Info<< nl << " Number of bad faces : " << nBadFaces << nl - << " Number of marked points : " - << returnReduce(isErrorPoint.count(), sumOp<unsigned int>()) - << endl; - - updatePointErrorCount - ( - isErrorPoint, - origToCurrentPointMap, - pointErrorCount - ); + const labelList& fEdges = mesh_.faceEdges()[faceI]; - checkMeshEdgesAndRelaxEdges - ( - newMesh, - origToCurrentPointMap, - isErrorPoint, - pointErrorCount - ); + scalar sumFaceFilterFactors = 0; + label nFaces = 0; - checkMeshFacesAndRelaxEdges - ( - newMesh, - origToCurrentPointMap, - isErrorPoint, - pointErrorCount - ); + // This is important: Only smooth around faces that share an + // edge with a bad face + bool skipFace = true; - newBadFaces = false; - forAll(mesh_.points(), pI) + forAll(fEdges, fEdgeI) { - if (isErrorPoint[origToCurrentPointMap[pI]]) + const labelList& eFaces = mesh_.edgeFaces()[fEdges[fEdgeI]]; + + forAll(eFaces, eFaceI) { - if (!newErrorPoint[pI]) + const label eFace = eFaces[eFaceI]; + + const face& f = faces[eFace]; + + forAll(f, fpI) { - newBadFaces = true; - break; + const label ptIndex = oldToNewMesh[f[fpI]]; + + if (isErrorPoint[ptIndex]) + { + skipFace = false; + break; + } + } + + if (eFace != faceI) + { + sumFaceFilterFactors += faceFilterFactor_[eFace]; + nFaces++; } } } - reduce(newBadFaces, orOp<bool>()); - } - else - { - return -1; + if (skipFace) + { + continue; + } + + faceFilterFactor_[faceI] = min + ( + faceFilterFactor_[faceI], + sumFaceFilterFactors/nFaces + ); } - } - return nBadFaces; + // Face filter factor needs to be synchronised! + syncTools::syncFaceList(mesh_, faceFilterFactor_, minEqOp<scalar>()); + } } -Foam::label Foam::polyMeshFilter::filterEdges +void Foam::polyMeshFilter::updatePointPriorities ( - const label nOriginalBadFaces + const polyMesh& newMesh, + const labelList& pointMap ) { - label nBadFaces = labelMax/2; - label nPreviousBadFaces = labelMax; - label nOuterIterations = 0; + labelList newPointPriority(newMesh.nPoints(), labelMin); + const labelList& currPointPriority = pointPriority_(); - minEdgeLen_.resize(mesh_.nEdges(), minLen_); - faceFilterFactor_.resize(0); + forAll(newPointPriority, ptI) + { + const label newPointToOldPoint = pointMap[ptI]; + const label origPointPriority = currPointPriority[newPointToOldPoint]; - labelList pointErrorCount(mesh_.nPoints(), 0); + newPointPriority[ptI] = max(origPointPriority, newPointPriority[ptI]); + } - // Main loop - // ~~~~~~~~~ - // It tries and do some collapses, checks the resulting mesh and - // 'freezes' some edges (by marking in minEdgeLen) and tries again. - // This will iterate ultimately to the situation where every edge is - // frozen and nothing gets collapsed. - while + syncTools::syncPointList ( - nOuterIterations < maxIterations_ - && nBadFaces > nOriginalBadFaces - && nBadFaces < nPreviousBadFaces - ) + newMesh, + newPointPriority, + maxEqOp<label>(), + labelMin + ); + + pointPriority_.reset(new labelList(newPointPriority)); +} + + +void Foam::polyMeshFilter::printScalarFieldStats +( + const string desc, + const scalarField& fld +) const +{ + scalar sum = 0; + scalar validElements = 0; + scalar min = GREAT; + scalar max = -GREAT; + + forAll(fld, i) { - Info<< nl << "Outer Iteration = " << nOuterIterations++ << nl - << endl; + const scalar fldElement = fld[i]; - printScalarFieldStats("Edge Filter Factor", minEdgeLen_); + if (fldElement >= 0) + { + sum += fldElement; - nPreviousBadFaces = nBadFaces; + if (fldElement < min) + { + min = fldElement; + } - // Reset the new mesh to the old mesh - newMeshPtr_ = copyMesh(mesh_); - fvMesh& newMesh = newMeshPtr_(); + if (fldElement > max) + { + max = fldElement; + } - scalarField newMeshMinEdgeLen = minEdgeLen_; + validElements++; + } + } - labelList origToCurrentPointMap(identity(newMesh.nPoints())); + reduce(sum, sumOp<scalar>()); + reduce(min, minOp<scalar>()); + reduce(max, maxOp<scalar>()); + reduce(validElements, sumOp<label>()); + const label totFieldSize = returnReduce(fld.size(), sumOp<label>()); - label nInnerIterations = 0; - label nPrevLocalCollapse = labelMax; + Info<< incrIndent << indent << desc + << ": min = " << min + << " av = " << sum/(validElements + SMALL) + << " max = " << max << nl + << indent + << " " << validElements << " / " << totFieldSize << " elements used" + << decrIndent << endl; +} - Info<< incrIndent; - while (true) - { - Info<< nl << indent << "Inner iteration = " - << nInnerIterations++ << nl << incrIndent << endl; +void Foam::polyMeshFilter::mapOldMeshEdgeFieldToNewMesh +( + const polyMesh& newMesh, + const labelList& pointMap, + scalarField& newMeshMinEdgeLen +) const +{ + scalarField tmp(newMesh.nEdges()); - // Per edge collapse status - PackedBoolList collapseEdge(newMesh.nEdges()); + const edgeList& newEdges = newMesh.edges(); + + forAll(newEdges, newEdgeI) + { + const edge& newEdge = newEdges[newEdgeI]; + const label pStart = newEdge.start(); + const label pEnd = newEdge.end(); - Map<point> collapsePointToLocation(newMesh.nPoints()); + tmp[newEdgeI] = min + ( + newMeshMinEdgeLen[pointMap[pStart]], + newMeshMinEdgeLen[pointMap[pEnd]] + ); + } - // Mark points on boundary - const labelList boundaryPoint = findBoundaryPoints(newMesh); + newMeshMinEdgeLen.transfer(tmp); - edgeCollapser collapser(newMesh, collapseFacesCoeffDict_); + syncTools::syncEdgeList + ( + newMesh, + newMeshMinEdgeLen, + maxEqOp<scalar>(), + scalar(0.0) + ); +} - // Work out which edges to collapse - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // This is by looking at minEdgeLen (to avoid frozen edges) - // and marking in collapseEdge. - label nSmallCollapsed = collapser.markSmallEdges - ( - newMeshMinEdgeLen, - boundaryPoint, - collapseEdge, - collapsePointToLocation - ); - reduce(nSmallCollapsed, sumOp<label>()); - Info<< indent << "Collapsing " << nSmallCollapsed - << " small edges" << endl; +void Foam::polyMeshFilter::mapOldMeshFaceFieldToNewMesh +( + const polyMesh& newMesh, + const labelList& faceMap, + scalarField& newMeshFaceFilterFactor +) const +{ + scalarField tmp(newMesh.nFaces()); - // Merge inline edges - label nMerged = collapser.markMergeEdges - ( - maxCos_, - boundaryPoint, - collapseEdge, - collapsePointToLocation - ); + forAll(faceMap, newFaceI) + { + const label oldFaceI = faceMap[newFaceI]; - reduce(nMerged, sumOp<label>()); - Info<< indent << "Collapsing " << nMerged << " in line edges" - << endl; + tmp[newFaceI] = newMeshFaceFilterFactor[oldFaceI]; + } - if (nMerged + nSmallCollapsed == 0) - { - Info<< decrIndent; - Info<< decrIndent; - break; - } + newMeshFaceFilterFactor.transfer(tmp); - // Merge edge collapses into consistent collapse-network. - // Make sure no cells get collapsed. - List<pointEdgeCollapse> allPointInfo; - const globalIndex globalPoints(newMesh.nPoints()); + syncTools::syncFaceList + ( + newMesh, + newMeshFaceFilterFactor, + maxEqOp<scalar>() + ); +} - collapser.consistentCollapse - ( - globalPoints, - boundaryPoint, - collapsePointToLocation, - collapseEdge, - allPointInfo - ); - label nLocalCollapse = collapseEdge.count(); +void Foam::polyMeshFilter::updateOldToNewPointMap +( + const labelList& currToNew, + labelList& origToCurrentPointMap +) const +{ + forAll(origToCurrentPointMap, origPointI) + { + label oldPointI = origToCurrentPointMap[origPointI]; - reduce(nLocalCollapse, sumOp<label>()); - Info<< nl << indent << "Collapsing " << nLocalCollapse - << " edges after synchronisation and PointEdgeWave" << endl; + if (oldPointI < currToNew.size()) + { + label newPointI = currToNew[oldPointI]; - if (nLocalCollapse >= nPrevLocalCollapse) - { - Info<< decrIndent; - Info<< decrIndent; - break; - } - else + if (newPointI != -1) { - nPrevLocalCollapse = nLocalCollapse; + origToCurrentPointMap[origPointI] = newPointI; } + } + } +} - // Apply collapses to current mesh - polyTopoChange newMeshMod(newMesh); - - // Insert mesh refinement into polyTopoChange. - collapser.setRefinement(allPointInfo, newMeshMod); - Info<< indent << "Apply changes to the current mesh" - << decrIndent << endl; +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // - // Apply changes to current mesh - autoPtr<mapPolyMesh> newMapPtr = newMeshMod.changeMesh +Foam::polyMeshFilter::polyMeshFilter(const fvMesh& mesh) +: + polyMeshFilterSettings + ( + IOdictionary + ( + IOobject ( - newMesh, - false - ); - const mapPolyMesh& newMap = newMapPtr(); + "collapseDict", + mesh.time().system(), + mesh.time(), + IOobject::MUST_READ, + IOobject::NO_WRITE + ) + ) + ), + mesh_(mesh), + newMeshPtr_(), + originalPointPriority_ + ( + IOobject + ( + "pointPriority", + mesh.time().timeName(), + mesh.time(), + IOobject::READ_IF_PRESENT, + IOobject::AUTO_WRITE + ), + labelList(mesh.nPoints(), labelMin) + ), + pointPriority_(), + minEdgeLen_(), + faceFilterFactor_() +{ + writeSettings(Info); +} - // Update fields - newMesh.updateMesh(newMap); - if (newMap.hasMotionPoints()) - { - newMesh.movePoints(newMap.preMotionPoints()); - } - // Relabel the boundary points -// labelList newBoundaryPoints(newMesh.nPoints(), -1); -// forAll(newBoundaryPoints, pI) -// { -// const label newToOldptI= map.pointMap()[pI]; -// newBoundaryPoints[pI] = boundaryIOPts[newToOldptI]; -// } -// boundaryIOPts = newBoundaryPoints; - - // Synchronise the factors - mapOldMeshEdgeFieldToNewMesh +Foam::polyMeshFilter::polyMeshFilter +( + const fvMesh& mesh, + const labelList& pointPriority +) +: + polyMeshFilterSettings + ( + IOdictionary + ( + IOobject ( - newMesh, - newMap.pointMap(), - newMeshMinEdgeLen - ); + "collapseDict", + mesh.time().system(), + mesh.time(), + IOobject::MUST_READ, + IOobject::NO_WRITE + ) + ) + ), + mesh_(mesh), + newMeshPtr_(), + originalPointPriority_(pointPriority), + pointPriority_(), + minEdgeLen_(), + faceFilterFactor_() +{ + writeSettings(Info); +} - updateOldToNewPointMap - ( - newMap.reversePointMap(), - origToCurrentPointMap - ); - } - // Mesh check - // ~~~~~~~~~~~~~~~~~~ - // Do not allow collapses in regions of error. - // Updates minEdgeLen, nRelaxedEdges +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // - if (controlMeshQuality_) - { - PackedBoolList isErrorPoint(newMesh.nPoints()); - nBadFaces = edgeCollapser::checkMeshQuality - ( - newMesh, - meshQualityCoeffDict_, - isErrorPoint - ); +Foam::polyMeshFilter::~polyMeshFilter() +{} - Info<< nl << " Number of bad faces : " << nBadFaces << nl - << " Number of marked points : " - << returnReduce(isErrorPoint.count(), sumOp<unsigned int>()) - << endl; - updatePointErrorCount - ( - isErrorPoint, - origToCurrentPointMap, - pointErrorCount - ); +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // - checkMeshEdgesAndRelaxEdges - ( - newMesh, - origToCurrentPointMap, - isErrorPoint, - pointErrorCount - ); - } - else +Foam::label Foam::polyMeshFilter::filter(const label nOriginalBadFaces) +{ + minEdgeLen_.resize(mesh_.nEdges(), minLen()); + faceFilterFactor_.resize(mesh_.nFaces(), initialFaceLengthFactor()); + + return filterFacesLoop(nOriginalBadFaces); +} + + +Foam::label Foam::polyMeshFilter::filter(const faceZone& fZone) +{ + minEdgeLen_.resize(mesh_.nEdges(), minLen()); + faceFilterFactor_.resize(mesh_.nFaces(), initialFaceLengthFactor()); + + forAll(faceFilterFactor_, fI) + { + if (fZone.whichFace(fI) == -1) { - return -1; + faceFilterFactor_[fI] = -1; } } - return nBadFaces; + return filterFacesLoop(0); } -Foam::label Foam::polyMeshFilter::filterFaceZone(const faceZone& fZone) +Foam::label Foam::polyMeshFilter::filterEdges +( + const label nOriginalBadFaces +) { - const label nOriginalBadFaces = 0; - - label nBadFaces = labelMax; + label nBadFaces = labelMax/2; + label nPreviousBadFaces = labelMax; label nOuterIterations = 0; - minEdgeLen_.resize(mesh_.nEdges(), minLen_); - faceFilterFactor_.resize(mesh_.nFaces(), initialFaceLengthFactor_); + minEdgeLen_.resize(mesh_.nEdges(), minLen()); + faceFilterFactor_.resize(0); - // Maintain the number of times a point has been part of a bad face labelList pointErrorCount(mesh_.nPoints(), 0); // Main loop @@ -1182,251 +976,52 @@ Foam::label Foam::polyMeshFilter::filterFaceZone(const faceZone& fZone) // frozen and nothing gets collapsed. while ( - nOuterIterations < maxIterations_ + nOuterIterations < maxIterations() && nBadFaces > nOriginalBadFaces + && nBadFaces < nPreviousBadFaces ) { Info<< nl << "Outer Iteration = " << nOuterIterations++ << nl << endl; printScalarFieldStats("Edge Filter Factor", minEdgeLen_); - printScalarFieldStats("Face Filter Factor", faceFilterFactor_); + + nPreviousBadFaces = nBadFaces; // Reset the new mesh to the old mesh newMeshPtr_ = copyMesh(mesh_); fvMesh& newMesh = newMeshPtr_(); - scalarField newMeshFaceFilterFactor = faceFilterFactor_; + scalarField newMeshMinEdgeLen = minEdgeLen_; + pointPriority_.reset(new labelList(originalPointPriority_)); labelList origToCurrentPointMap(identity(newMesh.nPoints())); - { - - label nInnerIterations = 0; - label nPrevLocalCollapse = labelMax; - - Info<< incrIndent; - - while (true) - { - Info<< nl << indent << "Inner iteration = " - << nInnerIterations++ << nl << incrIndent << endl; - - // Per edge collapse status - PackedBoolList collapseEdge(newMesh.nEdges()); - - Map<point> collapsePointToLocation(newMesh.nPoints()); - - // Mark points on boundary - const labelList boundaryPoint = findBoundaryPoints(newMesh); - - edgeCollapser collapser(newMesh, collapseFacesCoeffDict_); - - { - // Collapse faces - labelPair nCollapsedPtEdge = collapser.markFaceZoneEdges - ( - fZone, - newMeshFaceFilterFactor, - boundaryPoint, - collapseEdge, - collapsePointToLocation - ); - - label nCollapsed = 0; - forAll(nCollapsedPtEdge, collapseTypeI) - { - nCollapsed += nCollapsedPtEdge[collapseTypeI]; - } - - reduce(nCollapsed, sumOp<label>()); - - Info<< indent - << "Collapsing " << nCollapsed << " faces" - << " (to point = " - << returnReduce - ( - nCollapsedPtEdge.first(), - sumOp<label>() - ) - << ", to edge = " - << returnReduce - ( - nCollapsedPtEdge.second(), - sumOp<label>() - ) - << ")" << endl; - - if (nCollapsed == 0) - { - Info<< decrIndent; - Info<< decrIndent; - break; - } - } - - // Merge edge collapses into consistent collapse-network. - // Make sure no cells get collapsed. - List<pointEdgeCollapse> allPointInfo; - const globalIndex globalPoints(newMesh.nPoints()); - - collapser.consistentCollapse - ( - globalPoints, - boundaryPoint, - collapsePointToLocation, - collapseEdge, - allPointInfo - ); - - label nLocalCollapse = collapseEdge.count(); - - reduce(nLocalCollapse, sumOp<label>()); - Info<< nl << indent << "Collapsing " << nLocalCollapse - << " edges after synchronisation and PointEdgeWave" << endl; - - if (nLocalCollapse >= nPrevLocalCollapse) - { - Info<< decrIndent; - Info<< decrIndent; - break; - } - else - { - nPrevLocalCollapse = nLocalCollapse; - } - - { - // Apply collapses to current mesh - polyTopoChange newMeshMod(newMesh); - - // Insert mesh refinement into polyTopoChange. - collapser.setRefinement(allPointInfo, newMeshMod); - - Info<< indent << "Apply changes to the current mesh" - << decrIndent << endl; - - // Apply changes to current mesh - autoPtr<mapPolyMesh> newMapPtr = newMeshMod.changeMesh - ( - newMesh, - false - ); - const mapPolyMesh& newMap = newMapPtr(); - - // Update fields - newMesh.updateMesh(newMap); - if (newMap.hasMotionPoints()) - { - newMesh.movePoints(newMap.preMotionPoints()); - } - - // Relabel the boundary points - // labelList newBoundaryPoints(newMesh.nPoints(), -1); - // forAll(newBoundaryPoints, pI) - // { - // const label newToOldptI= map.pointMap()[pI]; - // newBoundaryPoints[pI] = boundaryIOPts[newToOldptI]; - // } - // boundaryIOPts = newBoundaryPoints; - - - mapOldMeshFaceFieldToNewMesh - ( - newMesh, - newMap.faceMap(), - newMeshFaceFilterFactor - ); - - updateOldToNewPointMap - ( - newMap.reversePointMap(), - origToCurrentPointMap - ); - } - } - } - - scalarField newMeshMinEdgeLen = minEdgeLen_; + Info<< incrIndent; label nInnerIterations = 0; label nPrevLocalCollapse = labelMax; while (true) { - Info<< nl << indent << "Inner iteration = " - << nInnerIterations++ << nl << incrIndent << endl; - - // Per edge collapse status - PackedBoolList collapseEdge(newMesh.nEdges()); - - Map<point> collapsePointToLocation(newMesh.nPoints()); - - // Mark points on boundary - const labelList boundaryPoint = findBoundaryPoints - ( - newMesh//, -// boundaryIOPts - ); + Info<< nl + << indent << "Inner iteration = " << nInnerIterations++ << nl + << incrIndent << endl; - edgeCollapser collapser(newMesh, collapseFacesCoeffDict_); - - // Work out which edges to collapse - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // This is by looking at minEdgeLen (to avoid frozen edges) - // and marking in collapseEdge. - label nSmallCollapsed = collapser.markSmallEdges + label nLocalCollapse = filterEdges ( + newMesh, newMeshMinEdgeLen, - boundaryPoint, - collapseEdge, - collapsePointToLocation - ); - - reduce(nSmallCollapsed, sumOp<label>()); - Info<< indent << "Collapsing " << nSmallCollapsed - << " small edges" << endl; - - // Merge inline edges - label nMerged = collapser.markMergeEdges - ( - maxCos_, - boundaryPoint, - collapseEdge, - collapsePointToLocation + origToCurrentPointMap ); - reduce(nMerged, sumOp<label>()); - Info<< indent << "Collapsing " << nMerged << " in line edges" - << endl; - - if (nMerged + nSmallCollapsed == 0) - { - Info<< decrIndent; - break; - } - - // Merge edge collapses into consistent collapse-network. - // Make sure no cells get collapsed. - List<pointEdgeCollapse> allPointInfo; - const globalIndex globalPoints(newMesh.nPoints()); + Info<< decrIndent; - collapser.consistentCollapse + if ( - globalPoints, - boundaryPoint, - collapsePointToLocation, - collapseEdge, - allPointInfo - ); - - label nLocalCollapse = collapseEdge.count(); - - reduce(nLocalCollapse, sumOp<label>()); - Info<< nl << indent << "Collapsing " << nLocalCollapse - << " edges after synchronisation and PointEdgeWave" << endl; - - if (nLocalCollapse >= nPrevLocalCollapse) + nLocalCollapse >= nPrevLocalCollapse + || nLocalCollapse == 0 + ) { Info<< decrIndent; break; @@ -1435,68 +1030,20 @@ Foam::label Foam::polyMeshFilter::filterFaceZone(const faceZone& fZone) { nPrevLocalCollapse = nLocalCollapse; } - - // Apply collapses to current mesh - polyTopoChange newMeshMod(newMesh); - - // Insert mesh refinement into polyTopoChange. - collapser.setRefinement(allPointInfo, newMeshMod); - - Info<< indent << "Apply changes to the current mesh" - << decrIndent << endl; - - // Apply changes to current mesh - autoPtr<mapPolyMesh> newMapPtr = newMeshMod.changeMesh - ( - newMesh, - false - ); - const mapPolyMesh& newMap = newMapPtr(); - - // Update fields - newMesh.updateMesh(newMap); - if (newMap.hasMotionPoints()) - { - newMesh.movePoints(newMap.preMotionPoints()); - } - - // Relabel the boundary points -// labelList newBoundaryPoints(newMesh.nPoints(), -1); -// forAll(newBoundaryPoints, pI) -// { -// const label newToOldptI= map.pointMap()[pI]; -// newBoundaryPoints[pI] = boundaryIOPts[newToOldptI]; -// } -// boundaryIOPts = newBoundaryPoints; - - // Synchronise the factors - mapOldMeshEdgeFieldToNewMesh - ( - newMesh, - newMap.pointMap(), - newMeshMinEdgeLen - ); - - updateOldToNewPointMap - ( - newMap.reversePointMap(), - origToCurrentPointMap - ); } - // Mesh check // ~~~~~~~~~~~~~~~~~~ // Do not allow collapses in regions of error. // Updates minEdgeLen, nRelaxedEdges - if (controlMeshQuality_) + if (controlMeshQuality()) { PackedBoolList isErrorPoint(newMesh.nPoints()); nBadFaces = edgeCollapser::checkMeshQuality ( newMesh, - meshQualityCoeffDict_, + meshQualityCoeffDict(), isErrorPoint ); @@ -1519,14 +1066,6 @@ Foam::label Foam::polyMeshFilter::filterFaceZone(const faceZone& fZone) isErrorPoint, pointErrorCount ); - - checkMeshFacesAndRelaxEdges - ( - newMesh, - origToCurrentPointMap, - isErrorPoint, - pointErrorCount - ); } else { @@ -1544,4 +1083,11 @@ const Foam::autoPtr<Foam::fvMesh>& Foam::polyMeshFilter::filteredMesh() const } +const Foam::autoPtr<Foam::labelList>& +Foam::polyMeshFilter::pointPriority() const +{ + return pointPriority_; +} + + // ************************************************************************* // diff --git a/src/dynamicMesh/polyMeshFilter/polyMeshFilter.H b/src/dynamicMesh/polyMeshFilter/polyMeshFilter.H index 0f26687608f..95cddd0058c 100644 --- a/src/dynamicMesh/polyMeshFilter/polyMeshFilter.H +++ b/src/dynamicMesh/polyMeshFilter/polyMeshFilter.H @@ -43,6 +43,7 @@ SourceFiles #include "List.H" #include "autoPtr.H" #include "scalarField.H" +#include "polyMeshFilterSettings.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -59,6 +60,8 @@ class faceZone; \*---------------------------------------------------------------------------*/ class polyMeshFilter +: + private polyMeshFilterSettings { // Private data @@ -68,52 +71,9 @@ class polyMeshFilter //- Copy of the original mesh to perform the filtering on autoPtr<fvMesh> newMeshPtr_; - //- Dictionary containing the coefficient sub-dictionaries - const IOdictionary dict_; - - //- After collapsing, check the mesh quality and redo the collapsing - // iteration if there are too many bad faces in the mesh - Switch controlMeshQuality_; - - //- Coefficients for collapsing edges - const dictionary& collapseEdgesCoeffDict_; - - //- Coefficients for collapsing faces - dictionary collapseFacesCoeffDict_; - - //- Coefficients for controlling the mesh quality - dictionary meshQualityCoeffDict_; - - //- Remove edges shorter than this length - const scalar minLen_; - - //- Merge points that are only attached to two edges and have an angle - // between the edge greater than this value - const scalar maxCos_; - - //- The amount that the local minimum edge length will be reduced by if - // the edge is part of a collapse string that generates poor quality - // faces - const scalar edgeReductionFactor_; - - //- Maximum number of outer iterations - const label maxIterations_; - - //- Maximum number of smoothing iterations of minEdgeLen_ and - // faceFilterFactor_ - const label maxSmoothIters_; - - //- Initialisation value of faceFilterFactor_ - const scalar initialFaceLengthFactor_; - - //- The amount that the local face size factor will be reduced by if - // the face is part of a collapse string that generates poor quality - // faces - const scalar faceReductionFactor_; - - //- Maximum number of times a deleted point can be associated with the - // creation of a bad face it is forced to be kept. - const label maxPointErrorCount_; + //- + labelList originalPointPriority_; + autoPtr<labelList> pointPriority_; //- The minimum edge length for each edge scalarField minEdgeLen_; @@ -124,6 +84,22 @@ class polyMeshFilter // Private Member Functions + label filterFacesLoop(const label nOriginalBadFaces); + + label filterFaces + ( + polyMesh& newMesh, + scalarField& newMeshFaceFilterFactor, + labelList& origToCurrentPointMap + ); + + label filterEdges + ( + polyMesh& newMesh, + scalarField& newMeshMinEdgeLen, + labelList& origToCurrentPointMap + ); + //- Increment pointErrorCount for points attached to a bad face void updatePointErrorCount ( @@ -160,7 +136,11 @@ class polyMeshFilter // + >0 : point on a processor patch with that ID // @todo Need to mark boundaryEdges as well, as an edge may have two // boundary points but not itself lie on a boundary - labelList findBoundaryPoints(const polyMesh& mesh) const; + void updatePointPriorities + ( + const polyMesh& newMesh, + const labelList& pointMap + ); //- Print min/mean/max data for a field void printScalarFieldStats @@ -213,6 +193,9 @@ public: //- Construct from fvMesh explicit polyMeshFilter(const fvMesh& mesh); + //- Construct from fvMesh and a label list of point priorities + polyMeshFilter(const fvMesh& mesh, const labelList& pointPriority); + //- Destructor ~polyMeshFilter(); @@ -226,6 +209,8 @@ public: // mesh has actually been filtered. const autoPtr<fvMesh>& filteredMesh() const; + const autoPtr<labelList>& pointPriority() const; + // Edit @@ -235,11 +220,11 @@ public: //- Filter edges and faces label filter(const label nOriginalBadFaces); + //- Filter all faces that are in the face zone indirectPatchFaces + label filter(const faceZone& fZone); + //- Filter edges only. label filterEdges(const label nOriginalBadFaces); - - //- Filter all faces that are in the face zone indirectPatchFaces - label filterFaceZone(const faceZone& fZone); }; diff --git a/src/dynamicMesh/polyTopoChange/polyTopoChange/edgeCollapser.C b/src/dynamicMesh/polyTopoChange/polyTopoChange/edgeCollapser.C index 6ea1e748b05..cb6334306e3 100644 --- a/src/dynamicMesh/polyTopoChange/polyTopoChange/edgeCollapser.C +++ b/src/dynamicMesh/polyTopoChange/polyTopoChange/edgeCollapser.C @@ -182,53 +182,46 @@ void Foam::edgeCollapser::collapseToEdge Map<point>& collapsePointToLocation ) const { - const face& f = mesh_.faces()[faceI]; - // Negative half - Foam::point collapseToPtA = - collapseAxis*(sum(dNeg)/dNeg.size() - dShift) + fC; + Foam::point collapseToPtA(GREAT, GREAT, GREAT); + //collapseAxis*(sum(dNeg)/dNeg.size() - dShift) + fC; - DynamicList<label> faceBoundaryPts(f.size()); - DynamicList<label> faceFeaturePts(f.size()); + label maxPriority = labelMin; + DynamicList<label> maxPriorityPts(max(dNeg.size(), dPos.size())); forAll(facePtsNeg, fPtI) { - if (pointPriority[facePtsNeg[fPtI]] == 1) + const label facePointI = facePtsNeg[fPtI]; + const label facePtPriority = pointPriority[facePointI]; + + if (facePtPriority > maxPriority) { - faceFeaturePts.append(facePtsNeg[fPtI]); + maxPriority = facePtPriority; + maxPriorityPts.clear(); + maxPriorityPts.append(facePointI); } - else if (pointPriority[facePtsNeg[fPtI]] == 0) + else if (facePtPriority == maxPriority) { - faceBoundaryPts.append(facePtsNeg[fPtI]); + maxPriorityPts.append(facePointI); } } - if (!faceBoundaryPts.empty() || !faceFeaturePts.empty()) + if (!maxPriorityPts.empty()) { - if (!faceFeaturePts.empty()) + Foam::point averagePt(vector::zero); + + forAll(maxPriorityPts, ptI) { - collapseToPtA = pts[faceFeaturePts.first()]; + averagePt += pts[maxPriorityPts[ptI]]; } - else if (faceBoundaryPts.size() == 2) - { - collapseToPtA = - 0.5 - *( - pts[faceBoundaryPts[0]] - + pts[faceBoundaryPts[1]] - ); - } - else if (faceBoundaryPts.size() <= f.size()) - { - face bFace(faceBoundaryPts); - collapseToPtA = bFace.centre(pts); - } + collapseToPtA = averagePt/maxPriorityPts.size(); +// collapseToPtA = pts[maxPriorityPts.first()]; } - faceFeaturePts.clear(); - faceBoundaryPts.clear(); + maxPriority = labelMin; + maxPriorityPts.clear(); labelList faceEdgesNeg = edgesFromPoints(faceI, facePtsNeg); @@ -244,47 +237,37 @@ void Foam::edgeCollapser::collapseToEdge // Positive half - - Foam::point collapseToPtB - = collapseAxis*(sum(dPos)/dPos.size() - dShift) + fC; + Foam::point collapseToPtB(GREAT, GREAT, GREAT); +// = collapseAxis*(sum(dPos)/dPos.size() - dShift) + fC; forAll(facePtsPos, fPtI) { - if (pointPriority[facePtsPos[fPtI]] == 1) + const label facePointI = facePtsPos[fPtI]; + const label facePtPriority = pointPriority[facePointI]; + + if (facePtPriority > maxPriority) { - faceFeaturePts.append(facePtsPos[fPtI]); + maxPriority = facePtPriority; + maxPriorityPts.clear(); + maxPriorityPts.append(facePointI); } - else if (pointPriority[facePtsPos[fPtI]] == 0) + else if (facePtPriority == maxPriority) { - // If there is a point which is on the boundary, - // use it as the point to collapse others to, will - // use the first boundary point encountered if - // there are multiple boundary points. - faceBoundaryPts.append(facePtsPos[fPtI]); + maxPriorityPts.append(facePointI); } } - if (!faceBoundaryPts.empty() || !faceFeaturePts.empty()) + if (!maxPriorityPts.empty()) { - if (!faceFeaturePts.empty()) + Foam::point averagePt(vector::zero); + + forAll(maxPriorityPts, ptI) { - collapseToPtB = pts[faceFeaturePts.first()]; + averagePt += pts[maxPriorityPts[ptI]]; } - else if (faceBoundaryPts.size() == 2) - { - collapseToPtB = - 0.5 - *( - pts[faceBoundaryPts[0]] - + pts[faceBoundaryPts[1]] - ); - } - else if (faceBoundaryPts.size() <= f.size()) - { - face bFace(faceBoundaryPts); - collapseToPtB = bFace.centre(pts); - } + collapseToPtB = averagePt/maxPriorityPts.size(); +// collapseToPtB = pts[maxPriorityPts.first()]; } labelList faceEdgesPos = edgesFromPoints(faceI, facePtsPos); @@ -316,45 +299,79 @@ void Foam::edgeCollapser::collapseToPoint Foam::point collapseToPt = fC; - DynamicList<label> faceBoundaryPts(f.size()); - DynamicList<label> faceFeaturePts(f.size()); + label maxPriority = labelMin; + DynamicList<label> maxPriorityPts(f.size()); forAll(facePts, fPtI) { - if (pointPriority[facePts[fPtI]] == 1) + const label facePointI = facePts[fPtI]; + const label facePtPriority = pointPriority[facePointI]; + + if (facePtPriority > maxPriority) { - faceFeaturePts.append(facePts[fPtI]); + maxPriority = facePtPriority; + maxPriorityPts.clear(); + maxPriorityPts.append(facePointI); } - else if (pointPriority[facePts[fPtI]] == 0) + else if (facePtPriority == maxPriority) { - faceBoundaryPts.append(facePts[fPtI]); + maxPriorityPts.append(facePointI); } } - if (!faceBoundaryPts.empty() || !faceFeaturePts.empty()) + if (!maxPriorityPts.empty()) { - if (!faceFeaturePts.empty()) + Foam::point averagePt(vector::zero); + + forAll(maxPriorityPts, ptI) { - collapseToPt = pts[faceFeaturePts.first()]; + averagePt += pts[maxPriorityPts[ptI]]; } - else if (faceBoundaryPts.size() == 2) - { - collapseToPt = - 0.5 - *( - pts[faceBoundaryPts[0]] - + pts[faceBoundaryPts[1]] - ); - } - else if (faceBoundaryPts.size() <= f.size()) - { - face bFace(faceBoundaryPts); - collapseToPt = bFace.centre(pts); - } + collapseToPt = averagePt/maxPriorityPts.size(); + +// collapseToPt = pts[maxPriorityPts.first()]; } - const labelList faceEdges = mesh_.faceEdges()[faceI]; +// DynamicList<label> faceBoundaryPts(f.size()); +// DynamicList<label> faceFeaturePts(f.size()); +// +// forAll(facePts, fPtI) +// { +// if (pointPriority[facePts[fPtI]] == 1) +// { +// faceFeaturePts.append(facePts[fPtI]); +// } +// else if (pointPriority[facePts[fPtI]] == 0) +// { +// faceBoundaryPts.append(facePts[fPtI]); +// } +// } +// +// if (!faceBoundaryPts.empty() || !faceFeaturePts.empty()) +// { +// if (!faceFeaturePts.empty()) +// { +// collapseToPt = pts[faceFeaturePts.first()]; +// } +// else if (faceBoundaryPts.size() == 2) +// { +// collapseToPt = +// 0.5 +// *( +// pts[faceBoundaryPts[0]] +// + pts[faceBoundaryPts[1]] +// ); +// } +// else if (faceBoundaryPts.size() <= f.size()) +// { +// face bFace(faceBoundaryPts); +// +// collapseToPt = bFace.centre(pts); +// } +// } + + const labelList& faceEdges = mesh_.faceEdges()[faceI]; forAll(faceEdges, eI) { @@ -740,35 +757,51 @@ Foam::label Foam::edgeCollapser::edgeMaster { label masterPoint = -1; - label e0 = e.start(); - label e1 = e.end(); + const label e0 = e.start(); + const label e1 = e.end(); - // Collapse edge to point with higher priority. - if (pointPriority[e0] >= 0) + const label e0Priority = pointPriority[e0]; + const label e1Priority = pointPriority[e1]; + + if (e0Priority > e1Priority) { - if (pointPriority[e1] >= 0) - { - // Both points have high priority. Choose one to collapse to. - // Note: should look at feature edges/points! - masterPoint = e0; - } - else - { - masterPoint = e0; - } + masterPoint = e0; } - else + else if (e0Priority < e1Priority) { - if (pointPriority[e1] >= 0) - { - masterPoint = e1; - } - else - { - // None on boundary. Neither is a master. - return -1; - } + masterPoint = e1; } + else if (e0Priority == e1Priority) + { + masterPoint = e0; + } + +// // Collapse edge to point with higher priority. +// if (pointPriority[e0] >= 0) +// { +// if (pointPriority[e1] >= 0) +// { +// // Both points have high priority. Choose one to collapse to. +// // Note: should look at feature edges/points! +// masterPoint = e0; +// } +// else +// { +// masterPoint = e0; +// } +// } +// else +// { +// if (pointPriority[e1] >= 0) +// { +// masterPoint = e1; +// } +// else +// { +// // None on boundary. Neither is a master. +// return -1; +// } +// } return masterPoint; } @@ -784,7 +817,10 @@ void Foam::edgeCollapser::checkBoundaryPointMergeEdges { const pointField& points = mesh_.points(); - if (pointPriority[pointI] >= 0 && pointPriority[otherPointI] < 0) + const label e0Priority = pointPriority[pointI]; + const label e1Priority = pointPriority[otherPointI]; + + if (e0Priority > e1Priority) { collapsePointToLocation.set ( @@ -792,13 +828,29 @@ void Foam::edgeCollapser::checkBoundaryPointMergeEdges points[pointI] ); } - else + else if (e0Priority < e1Priority) + { + collapsePointToLocation.set + ( + pointI, + points[otherPointI] + ); + } + else // e0Priority == e1Priority { collapsePointToLocation.set ( pointI, points[otherPointI] ); + +// Foam::point averagePt +// ( +// 0.5*(points[otherPointI] + points[pointI]) +// ); +// +// collapsePointToLocation.set(pointI, averagePt); +// collapsePointToLocation.set(otherPointI, averagePt); } } @@ -1963,7 +2015,7 @@ Foam::labelPair Foam::edgeCollapser::markSmallSliverFaces { const face& f = faces[fI]; - if (faceFilterFactor[fI] == 0) + if (faceFilterFactor[fI] <= 0) { continue; } @@ -2030,7 +2082,7 @@ Foam::labelPair Foam::edgeCollapser::markFaceZoneEdges const face& f = faces[fI]; - if (faceFilterFactor[fI] == 0) + if (faceFilterFactor[fI] <= 0) { continue; } -- GitLab