48 void Foam::meshRefinement::markBoundaryFace
56 isBoundaryFace[facei] =
true;
62 isBoundaryEdge[fEdges[fp]] =
true;
65 const face&
f = mesh_.
faces()[facei];
69 isBoundaryPoint[
f[fp]] =
true;
74 void Foam::meshRefinement::findNearest
77 List<pointIndexHit>& nearestInfo,
86 fc[i] = mesh_.faceCentres()[meshFaces[i]];
101 nearestNormal.setSize(nearestInfo.size());
102 nearestRegion.setSize(nearestInfo.size());
104 forAll(allSurfaces, surfi)
106 DynamicList<pointIndexHit> localHits;
110 if (nearestSurface[i] == surfi)
112 localHits.append(nearestInfo[i]);
116 const label geomi = surfaces_.surfaces()[surfi];
119 surfaces_.geometry()[geomi].getNormal(localHits, localNormals);
122 surfaces_.geometry()[geomi].getRegion(localHits, localRegion);
127 if (nearestSurface[i] == surfi)
129 nearestNormal[i] = localNormals[localI];
130 nearestRegion[i] = localRegion[localI];
145 autoPtr<indirectPrimitivePatch> ppPtr
159 DynamicList<label> candidateFaces(pp.size()/20);
163 const labelList& cellLevel = meshCutter_.cellLevel();
167 const labelList& eFaces = edgeFaces[edgei];
169 if (eFaces.size() == 2)
171 const label face0 = pp.addressing()[eFaces[0]];
172 const label face1 = pp.addressing()[eFaces[1]];
174 const label cell0 = mesh_.faceOwner()[face0];
175 const label cell1 = mesh_.faceOwner()[face1];
177 if (cellLevel[cell0] > cellLevel[cell1])
180 const vector& n0 = pp.faceNormals()[eFaces[0]];
181 const vector& n1 = pp.faceNormals()[eFaces[1]];
183 if (
mag(n0 & n1) < 0.1)
185 candidateFaces.append(face0);
188 else if (cellLevel[cell1] > cellLevel[cell0])
191 const vector& n0 = pp.faceNormals()[eFaces[0]];
192 const vector& n1 = pp.faceNormals()[eFaces[1]];
194 if (
mag(n0 & n1) < 0.1)
196 candidateFaces.append(face1);
201 candidateFaces.shrink();
204 <<
" faces on edge-connected cells of differing level."
209 faceSet fSet(mesh_,
"edgeConnectedFaces", candidateFaces);
210 fSet.instance() =
name();
211 Pout<<
"Writing " << fSet.size()
212 <<
" with problematic topology to faceSet "
213 << fSet.objectPath() <<
endl;
221 List<pointIndexHit> nearestInfo;
238 Map<label> candidateCells(candidateFaces.size());
240 faceSet perpFaces(mesh_,
"perpendicularFaces", pp.size()/100);
244 const label facei = candidateFaces[i];
245 const vector n = mesh_.faceAreas()[facei]/
mag(mesh_.faceAreas()[facei]);
247 const label region = surfaces_.globalRegion
253 const scalar angle =
degToRad(perpendicularAngle[region]);
259 perpFaces.insert(facei);
260 candidateCells.insert
262 mesh_.faceOwner()[facei],
263 globalToPatch[region]
271 perpFaces.instance() =
name();
272 Pout<<
"Writing " << perpFaces.size()
273 <<
" faces that are perpendicular to the surface to set "
274 << perpFaces.objectPath() <<
endl;
277 return candidateCells;
281 bool Foam::meshRefinement::isCollapsedFace
285 const scalar minFaceArea,
286 const scalar maxNonOrtho,
291 const scalar severeNonorthogonalityThreshold =
295 const scalar magS =
mag(
s);
298 if (magS < minFaceArea)
304 const point& ownCc = mesh_.cellCentres()[mesh_.faceOwner()[facei]];
306 if (mesh_.isInternalFace(facei))
308 const label nei = mesh_.faceNeighbour()[facei];
309 const vector d = mesh_.cellCentres()[nei] - ownCc;
311 const scalar dDotS = (d &
s)/(
mag(d)*magS + vSmall);
313 if (dDotS < severeNonorthogonalityThreshold)
324 const label patchi = mesh_.boundaryMesh().whichPatch(facei);
326 if (mesh_.boundaryMesh()[
patchi].coupled())
328 const vector d = neiCc[facei-mesh_.nInternalFaces()] - ownCc;
330 const scalar dDotS = (d &
s)/(
mag(d)*magS + vSmall);
332 if (dDotS < severeNonorthogonalityThreshold)
351 bool Foam::meshRefinement::isCollapsedCell
354 const scalar volFraction,
358 const scalar vol = mesh_.cells()[celli].mag(
points, mesh_.faces());
360 if (vol/mesh_.cellVolumes()[celli] < volFraction)
376 const polyBoundaryMesh&
patches = mesh_.boundaryMesh();
380 if (adaptPatchIDs.size())
382 nearestAdaptPatch.
setSize(mesh_.nFaces(), adaptPatchIDs[0]);
389 const polyPatch& pp =
patches[adaptPatchIDs[i]];
394 List<topoDistanceData> cellData(mesh_.nCells());
395 List<topoDistanceData> faceData(mesh_.nFaces());
399 List<topoDistanceData> patchData(nFaces);
408 patchFaces[nFaces] = pp.start()+i;
409 patchData[nFaces] = topoDistanceData(
patchi, 0);
415 FaceCellWave<topoDistanceData> deltaCalc
422 mesh_.globalData().nTotalCells()+1
427 bool haveWarned =
false;
430 if (!faceData[facei].
valid(deltaCalc.data()))
435 <<
"Did not visit some faces, e.g. face " << facei
436 <<
" at " << mesh_.faceCentres()[facei] <<
endl
437 <<
"Assigning these cells to patch "
445 nearestAdaptPatch[facei] = faceData[facei].data();
452 nearestAdaptPatch.setSize(mesh_.nFaces(), 0);
455 return nearestAdaptPatch;
461 const dictionary& motionDict,
462 const bool removeEdgeConnectedCells,
467 const labelList& cellLevel = meshCutter_.cellLevel();
468 const labelList& pointLevel = meshCutter_.pointLevel();
469 const polyBoundaryMesh&
patches = mesh_.boundaryMesh();
474 boolList isBoundaryPoint(mesh_.nPoints(),
false);
475 boolList isBoundaryEdge(mesh_.nEdges(),
false);
476 boolList isBoundaryFace(mesh_.nFaces(),
false);
480 labelList adaptPatchIDs(meshedPatches());
484 const polyPatch& pp =
patches[adaptPatchIDs[i]];
486 label facei = pp.start();
504 const labelList nearestAdaptPatch(nearestPatch(adaptPatchIDs));
512 labelList neiLevel(mesh_.nFaces()-mesh_.nInternalFaces());
513 pointField neiCc(mesh_.nFaces()-mesh_.nInternalFaces());
514 calcNeighbourData(neiLevel, neiCc);
518 label nBaffleFaces = 0;
522 label nPrevented = 0;
524 if (removeEdgeConnectedCells &&
max(perpendicularAngle) >= 0)
526 Info<<
"markFacesOnProblemCells :"
527 <<
" Checking for edge-connected cells of highly differing sizes."
532 Map<label> problemCells
534 findEdgeConnectedProblemCells
544 const cell& cFaces = mesh_.cells()[iter.key()];
548 const label facei = cFaces[i];
550 if (facePatch[facei] == -1 && mesh_.isInternalFace(facei))
552 facePatch[facei] = nearestAdaptPatch[facei];
566 Info<<
"markFacesOnProblemCells : Marked "
568 <<
" additional internal faces to be converted into baffles"
571 <<
" cells edge-connected to lower level cells." <<
endl;
575 cellSet problemCellSet(mesh_,
"problemCells", problemCells.toc());
576 problemCellSet.instance() =
name();
577 Pout<<
"Writing " << problemCellSet.size()
578 <<
" cells that are edge connected to coarser cell to set "
579 << problemCellSet.objectPath() <<
endl;
580 problemCellSet.
write();
612 const scalar volFraction =
613 motionDict.lookupOrDefault<scalar>(
"minVolCollapseRatio", -1);
615 const bool checkCollapse = (volFraction > 0);
617 scalar maxNonOrtho = -1;
625 minArea = motionDict.lookup<scalar>(
"minArea");
626 maxNonOrtho = motionDict.lookup<scalar>(
"maxNonOrtho");
628 Info<<
"markFacesOnProblemCells :"
629 <<
" Deleting all-anchor surface cells only if"
630 <<
" snapping them violates mesh quality constraints:" <<
nl
631 <<
" snapped/original cell volume < " << volFraction <<
nl
632 <<
" face area < " << minArea <<
nl
633 <<
" non-orthogonality > " << maxNonOrtho <<
nl
637 autoPtr<indirectPrimitivePatch> ppPtr
646 const pointField& localPoints = pp.localPoints();
647 const labelList& meshPoints = pp.meshPoints();
649 List<pointIndexHit> hitinfo;
651 surfaces_.findNearest
661 newPoints = mesh_.points();
665 if (hitinfo[i].hit())
667 newPoints[meshPoints[i]] = hitinfo[i].hitPoint();
673 const_cast<Time&
>(mesh_.time())++;
675 mesh_.movePoints(newPoints);
676 Pout<<
"Writing newPoints mesh to time " <<
name()
681 writeType(writeLevel() | WRITEMESH),
682 mesh_.time().path()/
"newPoints"
684 mesh_.movePoints(oldPoints);
702 PackedBoolList hasSevenBoundaryAnchorPoints(mesh_.nCells());
707 DynamicList<label> dynFEdges;
708 DynamicList<label> dynCPoints;
712 const labelList& cPoints = mesh_.cellPoints(celli, dynCPoints);
716 label nBoundaryAnchors = 0;
717 label nonBoundaryAnchor = -1;
721 const label pointi = cPoints[i];
723 if (pointLevel[pointi] <= cellLevel[celli])
726 if (isBoundaryPoint[pointi])
733 nonBoundaryAnchor = pointi;
738 if (nBoundaryAnchors == 8)
740 const cell& cFaces = mesh_.cells()[celli];
745 && !isCollapsedCell(newPoints, volFraction, celli)
763 const label facei = cFaces[cf];
767 facePatch[facei] == -1
768 && mesh_.isInternalFace(facei)
771 facePatch[facei] = nearestAdaptPatch[facei];
786 else if (nBoundaryAnchors == 7)
789 hasSevenBoundaryAnchorPoints.set(celli, 1u);
790 nonBoundaryAnchors.insert(nonBoundaryAnchor);
799 DynamicList<label> dynPCells;
803 label pointi = iter.key();
805 const labelList& pCells = mesh_.pointCells(pointi, dynPCells);
812 if (hasSevenBoundaryAnchorPoints.get(pCells[i]) == 1u)
823 label celli = pCells[i];
825 if (hasSevenBoundaryAnchorPoints.get(celli) == 1u)
830 && !isCollapsedCell(newPoints, volFraction, celli)
845 const cell& cFaces = mesh_.cells()[celli];
849 const label facei = cFaces[cf];
853 facePatch[facei] == -1
854 && mesh_.isInternalFace(facei)
857 facePatch[facei] = nearestAdaptPatch[facei];
905 for (
label facei = 0; facei < mesh_.nInternalFaces(); facei++)
907 if (facePatch[facei] == -1)
909 const labelList& fEdges = mesh_.faceEdges(facei, dynFEdges);
910 label nFaceBoundaryEdges = 0;
914 if (isBoundaryEdge[fEdges[fe]])
916 nFaceBoundaryEdges++;
920 if (nFaceBoundaryEdges == fEdges.size())
944 facePatch[facei] = nearestAdaptPatch[facei];
960 label facei = pp.start();
964 if (facePatch[facei] == -1)
966 const labelList& fEdges = mesh_.faceEdges(facei, dynFEdges);
967 label nFaceBoundaryEdges = 0;
971 if (isBoundaryEdge[fEdges[fe]])
973 nFaceBoundaryEdges++;
977 if (nFaceBoundaryEdges == fEdges.size())
1001 facePatch[facei] = nearestAdaptPatch[facei];
1002 if (isMasterFace[facei])
1031 Info<<
"markFacesOnProblemCells : marked "
1033 <<
" additional internal faces to be converted into baffles."
1038 Info<<
"markFacesOnProblemCells : prevented "
1040 <<
" internal faces from getting converted into baffles."
1050 Foam::labelList Foam::meshRefinement::markFacesOnProblemCellsGeometric
1052 const snapParameters& snapParams,
1053 const dictionary& motionDict
1060 labelList adaptPatchIDs(meshedPatches());
1063 autoPtr<indirectPrimitivePatch> ppPtr
1081 Info<<
"Constructing mesh displacer ..." <<
endl;
1082 Info<<
"Using mesh parameters " << motionDict <<
nl <<
endl;
1086 motionSmoother meshMover
1097 Info<<
"Checking initial mesh ..." <<
endl;
1106 Info<<
"Detected " << nInitErrors <<
" illegal faces"
1107 <<
" (concave, zero area or negative cell pyramid volume)"
1111 Info<<
"Checked initial mesh in = "
1112 << mesh_.time().cpuTimeIncrement() <<
" s\n" <<
nl <<
endl;
1138 const labelList& meshPoints = pp.meshPoints();
1143 newPoints[meshPoints[i]] += disp[i];
1150 minMagSqrEqOp<point>(),
1151 vector(great, great, great)
1154 mesh_.movePoints(newPoints);
1159 const labelList nearestAdaptPatch(nearestPatch(meshedPatches()));
1163 labelList facePatch(mesh_.nFaces(), -1);
1165 label nBaffleFaces = 0;
1168 faceSet wrongFaces(mesh_,
"wrongFaces", 100);
1176 label nWrongFaces = 0;
1207 scalar minArea(motionDict.lookup<scalar>(
"minArea"));
1208 if (minArea > -small)
1226 Info<<
" faces with area < "
1227 <<
setw(5) << minArea
1229 << nNewWrongFaces-nWrongFaces <<
endl;
1231 nWrongFaces = nNewWrongFaces;
1234 scalar minDet(motionDict.lookup<scalar>(
"minDeterminant"));
1253 Info<<
" faces on cells with determinant < "
1254 <<
setw(5) << minDet <<
" : "
1255 << nNewWrongFaces-nWrongFaces <<
endl;
1257 nWrongFaces = nNewWrongFaces;
1264 label patchi = mesh_.boundaryMesh().whichPatch(iter.key());
1266 if (
patchi == -1 || mesh_.boundaryMesh()[
patchi].coupled())
1268 facePatch[iter.key()] = nearestAdaptPatch[iter.key()];
1281 mesh_.movePoints(oldPoints);
1284 Info<<
"markFacesOnProblemCellsGeometric : marked "
1286 <<
" additional internal and coupled faces"
1287 <<
" to be converted into baffles." <<
endl;
Istream and Ostream manipulators taking arguments.
#define forAll(list, i)
Loop across all elements in list.
#define forAllConstIter(Container, container, iter)
Iterate across all elements in the container object of type.
static pointMesh & New(const polyMesh &mesh)
void setSize(const label)
Reset size of List.
A HashTable to objects of type <T> with a label key.
virtual Ostream & write(const char)=0
Write character.
label size() const
Return the number of elements in the UPtrList.
static tmp< pointVectorField > makeDisplacementField(const pointMesh &pMesh, const labelList &adaptPatchIDs)
Helper function to make a pointVectorField with correct.
static autoPtr< indirectPrimitivePatch > makePatch(const polyMesh &, const labelList &)
Create patch from set of patches.
static bool checkMesh(const bool report, const polyMesh &mesh, const dictionary &dict, labelHashSet &wrongFaces)
Check mesh with mesh settings in dict. Collects incorrect faces.
virtual const faceList & faces() const
Return raw faces.
const labelListList & faceEdges() const
static vectorField calcNearestSurface(const meshRefinement &meshRefiner, const scalarField &snapDist, const indirectPrimitivePatch &, pointField &nearestPoint, vectorField &nearestNormal)
Per patch point calculate point on nearest surface. Set as.
static void preSmoothPatch(const meshRefinement &meshRefiner, const snapParameters &snapParams, const label nInitErrors, const List< labelPair > &baffles, motionSmoother &)
Smooth the mesh (patch and internal) to increase visibility.
static scalarField calcSnapDistance(const fvMesh &mesh, const snapParameters &snapParams, const indirectPrimitivePatch &)
Calculate edge length per patch point.
static labelList getUnnamedSurfaces(const PtrList< surfaceZonesInfo > &surfList)
Get indices of unnamed surfaces (surfaces without faceZoneName)
PolyMesh checking routines. Checks various criteria for a mesh and supplied geometry,...
gmvFile<< "tracers "<< particles.size()<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().x()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().y()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.name(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
const fvPatchList & patches
#define WarningInFunction
Report a warning using Foam::Warning.
bool valid(const PtrList< ModelType > &l)
bool checkFaceArea(const bool report, const scalar minArea, const polyMesh &, const vectorField &faceAreas, const labelList &checkFaces, labelHashSet *setPtr)
Check for small faces.
bool checkCellDeterminant(const bool report, const scalar minDet, const polyMesh &, const vectorField &faceAreas, const labelList &checkFaces, labelHashSet *setPtr)
Check the area of internal faces v.s. boundary faces.
void write(std::ostream &os, const bool binary, List< floatScalar > &fField)
Write floats ascii or binary.
List< label > labelList
A List of labels.
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Ostream & endl(Ostream &os)
Add newline and flush stream.
word name(const bool)
Return a word representation of a bool.
Omanip< int > setw(const int i)
dimensionedScalar sin(const dimensionedScalar &ds)
vectorField pointField
pointField is a vectorField.
List< bool > boolList
Bool container classes.
vector point
Point is a vector.
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Vector< scalar > vector
A scalar version of the templated Vector.
List< labelList > labelListList
A List of labelList.
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
dimensioned< scalar > mag(const dimensioned< Type > &)
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
Field< vector > vectorField
Specialisation of Field<T> for vector.
prefixOSstream Pout(cout, "Pout")
HashSet< label, Hash< label > > labelHashSet
A HashSet with label keys.
labelList identityMap(const label len)
Create identity map (map[i] == i) of given length.
PrimitivePatch< IndirectList< face >, const pointField & > indirectPrimitivePatch
Foam::indirectPrimitivePatch.
dimensionedScalar cos(const dimensionedScalar &ds)
scalar degToRad(const scalar deg)
Conversion from degrees to radians.
Unit conversion functions.