46 const vector Cpf = fCtrs[facei] - ownCc;
47 const vector d = neiCc - ownCc;
52 - ((fAreas[facei] & Cpf)/((fAreas[facei] & d) + rootVSmall))*d;
53 const vector svHat = sv/(
mag(sv) + rootVSmall);
58 scalar fd = 0.2*
mag(d) + rootVSmall;
62 fd =
max(fd,
mag(svHat & (
p[
f[
pi]] - fCtrs[facei])));
81 const vector Cpf = fCtrs[facei] - ownCc;
83 vector normal = fAreas[facei];
84 normal /=
mag(normal) + rootVSmall;
85 const vector d = normal*(normal & Cpf);
91 - ((fAreas[facei] & Cpf)/((fAreas[facei] & d) + rootVSmall))*d;
92 const vector svHat = sv/(
mag(sv) + rootVSmall);
97 scalar fd = 0.4*
mag(d) + rootVSmall;
101 fd =
max(fd,
mag(svHat & (
p[
f[
pi]] - fCtrs[facei])));
116 const vector d = neiCc - ownCc;
117 return (d &
s)/(
mag(d)*
mag(
s) + rootVSmall);
176 cellCtrs[own[facei]],
264 sumClosed[own[facei]] += areas[facei];
265 sumMagClosed[own[facei]] +=
cmptMag(areas[facei]);
271 sumClosed[nei[facei]] -= areas[facei];
272 sumMagClosed[nei[facei]] +=
cmptMag(areas[facei]);
277 for (
direction dir = 0; dir < vector::nComponents; dir++)
292 scalar maxOpenness = 0;
294 for (
direction cmpt=0; cmpt<vector::nComponents; cmpt++)
299 mag(sumClosed[celli][cmpt])
300 /(sumMagClosed[celli][cmpt] + rootVSmall)
303 openness[celli] = maxOpenness;
307 scalar minCmpt = vGreat;
308 scalar maxCmpt = -vGreat;
309 for (
direction dir = 0; dir < vector::nComponents; dir++)
313 minCmpt =
min(minCmpt, sumMagClosed[celli][dir]);
314 maxCmpt =
max(maxCmpt, sumMagClosed[celli][dir]);
318 scalar aspectRatio = maxCmpt/(minCmpt + rootVSmall);
321 scalar v =
max(rootVSmall, vols[celli]);
326 1.0/6.0*
cmptSum(sumMagClosed[celli])/
pow(v, 2.0/3.0)
330 aratio[celli] = aspectRatio;
346 faceNormals /=
mag(faceNormals) + rootVSmall;
354 const face&
f = fcs[facei];
358 scalar magEPrev =
mag(ePrev);
359 ePrev /= magEPrev + rootVSmall;
361 scalar maxEdgeSin = 0.0;
366 const label fp1 =
f.fcIndex(fp0);
370 const scalar magE10 =
mag(e10);
371 e10 /= magE10 + rootVSmall;
373 if (magEPrev > small && magE10 > small)
375 vector edgeNormal = ePrev ^ e10;
376 const scalar magEdgeNormal =
mag(edgeNormal);
378 if (magEdgeNormal < maxSin)
385 edgeNormal /= magEdgeNormal;
387 if ((edgeNormal & faceNormals[facei]) < small)
389 maxEdgeSin =
max(maxEdgeSin, magEdgeNormal);
398 faceAngles[facei] = maxEdgeSin;
425 const face&
f = fcs[facei];
427 if (
f.size() > 3 && magAreas[facei] > rootVSmall)
429 const point& fc = fCtrs[facei];
438 const point& thisPoint =
p[
f[fp]];
439 const point& nextPoint =
p[
f.nextLabel(fp)];
442 const vector n = 0.5*((nextPoint - thisPoint)^(fc - thisPoint));
446 faceFlatness[facei] = magAreas[facei]/(sumA + rootVSmall);
450 return tfaceFlatness;
465 for (
direction dir = 0; dir < vector::nComponents; dir++)
495 label nInternalFaces = 0;
499 if (internalOrCoupledFace[curFaces[i]])
501 avgArea +=
mag(faceAreas[curFaces[i]]);
507 if (nInternalFaces == 0)
513 avgArea /= nInternalFaces;
519 if (internalOrCoupledFace[curFaces[i]])
521 areaTensor +=
sqr(faceAreas[curFaces[i]]/avgArea);
548 return tcellDeterminant;
555 const scalar closedThreshold,
562 <<
"Checking whether the boundary is closed" <<
endl;
571 scalar sumMagClosedBoundary = 0;
575 sumClosed += areas[facei];
576 sumMagClosedBoundary +=
mag(areas[facei]);
582 vector openness = sumClosed/(sumMagClosedBoundary + vSmall);
588 Info<<
" ***Boundary openness " << openness
589 <<
" possible hole in boundary description."
599 Info<<
" Boundary openness " << openness <<
" OK."
611 const scalar closedThreshold,
612 const scalar aspectThreshold,
622 <<
"Checking whether cells are closed" <<
endl;
631 label nErrorClosed = 0;
635 const cell& curCell =
c[cI];
648 if (nErrorClosed > 0)
652 Info<<
" ***Cells with invalid face labels found, number of cells "
653 << nErrorClosed <<
endl;
673 scalar maxOpennessCell =
max(openness);
675 scalar maxAspectRatio =
max(aspectRatio);
680 if (openness[celli] > closedThreshold)
690 if (aspectRatio[celli] > aspectThreshold)
694 aspectSetPtr->
insert(celli);
712 Info<<
" ***Open cells found, max cell openness: "
713 << maxOpennessCell <<
", number of open cells " << nOpen
724 Info<<
" ***High aspect ratio cells found, Max aspect ratio: "
726 <<
", number of cells " << nAspect
735 Info<<
" Max cell openness = " << maxOpennessCell <<
" OK." <<
nl
736 <<
" Max aspect ratio = " << maxAspectRatio <<
" OK."
759 scalar minArea = great;
760 scalar maxArea = -great;
762 forAll(magFaceAreas, facei)
764 if (magFaceAreas[facei] < vSmall)
772 minArea =
min(minArea, magFaceAreas[facei]);
773 maxArea =
max(maxArea, magFaceAreas[facei]);
779 if (minArea < vSmall)
783 Info<<
" ***Zero or negative face area detected. "
784 "Minimum area: " << minArea <<
endl;
793 Info<<
" Minimum face area = " << minArea
794 <<
". Maximum face area = " << maxArea
795 <<
". Face area magnitudes OK." <<
endl;
816 scalar minVolume = great;
817 scalar maxVolume = -great;
819 label nNegVolCells = 0;
823 if (vols[celli] < vSmall)
833 minVolume =
min(minVolume, vols[celli]);
834 maxVolume =
max(maxVolume, vols[celli]);
841 if (minVolume < vSmall)
845 Info<<
" ***Zero or negative cell volume detected. "
846 <<
"Minimum negative volume: " << minVolume
847 <<
", Number of negative volume cells: " << nNegVolCells
857 Info<<
" Min volume = " << minVolume
858 <<
". Max volume = " << maxVolume
859 <<
". Total volume = " <<
gSum(vols)
860 <<
". Cell volumes OK." <<
endl;
872 const scalar minPyrVol,
897 label nErrorPyrs = 0;
901 if (ownPyrVol[facei] < minPyrVol)
913 if (neiPyrVol[facei] < minPyrVol)
930 Info<<
" ***Error in face pyramids: "
931 << nErrorPyrs <<
" faces are incorrectly oriented."
941 Info<<
" Face pyramids OK." <<
endl;
953 const scalar maxConcave,
962 if (maxConcave < -small || maxConcave >
degToRad(180)+small)
965 <<
"maxConcave should be [0..180] degrees but is "
969 const scalar maxSin =
Foam::sin(maxConcave);
983 scalar maxEdgeSin =
max(faceAngles);
989 if (faceAngles[facei] > small)
1007 Info<<
" *There are " << nConcave
1008 <<
" faces with concave angles between consecutive"
1009 <<
" edges. Max concave angle = "
1011 <<
" degrees." <<
endl;
1020 Info<<
" All angles in faces OK." <<
endl;
1032 const scalar warnFlatness,
1041 if (warnFlatness < 0 || warnFlatness > 1)
1044 <<
"warnFlatness should be [0..1] but is now " << warnFlatness
1064 scalar minFlatness = great;
1065 scalar sumFlatness = 0;
1071 if (fcs[facei].size() > 3 && magAreas[facei] > vSmall)
1101 Info<<
" Face flatness (1 = flat, 0 = butterfly) : min = "
1102 << minFlatness <<
" average = " << sumFlatness / nSummed
1112 Info<<
" *There are " << nWarped
1113 <<
" faces with ratio between projected and actual area < "
1114 << warnFlatness <<
endl;
1116 Info<<
" Minimum ratio (minimum flatness, maximum warpage) = "
1117 << minFlatness <<
endl;
1126 Info<<
" All face flatness OK." <<
endl;
1137 const scalar planarCosAngle,
1152 label nConcaveCells = 0;
1156 const cell& cFaces =
c[celli];
1158 bool concave =
false;
1167 const label fI = cFaces[i];
1169 const point& fC = fCentres[fI];
1172 fN /=
max(
mag(fN), vSmall);
1176 if (fOwner[fI] != celli)
1188 const label fJ = cFaces[j];
1190 const point& pt = fCentres[fJ];
1199 pC /=
max(
mag(pC), vSmall);
1201 if ((pC & fN) > -planarCosAngle)
1223 if (nConcaveCells > 0)
1227 Info<<
" ***Concave cells (using face planes) found,"
1228 <<
" number of cells: " << nConcaveCells <<
endl;
1237 Info<<
" Concave cell check OK." <<
endl;
1269 label nMultipleCells =
false;
1273 for (
label facei = 0; facei <
internal; facei++)
1275 if (own[facei] >= nei[facei])
1299 label facei = curFaces[i];
1308 label nbrCelli = nei[facei];
1310 if (nbrCelli == celli)
1312 nbrCelli = own[facei];
1315 if (celli < nbrCelli)
1335 label prevCell = nbr[0];
1338 bool hasMultipleFaces =
false;
1342 const label thisCell = nbr[i];
1350 if (thisCell == prevCell)
1352 hasMultipleFaces =
true;
1356 setPtr->
insert(prevFace);
1357 setPtr->
insert(thisFace);
1360 else if (thisFace < prevFace)
1366 setPtr->
insert(thisFace);
1370 prevCell = thisCell;
1371 prevFace = thisFace;
1374 if (hasMultipleFaces)
1383 if ((report) && nMultipleCells > 0)
1385 Info<<
" <<Found " << nMultipleCells
1386 <<
" neighbouring cells with multiple in between faces." <<
endl;
1393 Info<<
" ***Faces not in upper triangular order." <<
endl;
1402 Info<<
" Upper triangular ordering OK." <<
endl;
1422 label nOpenCells = 0;
1431 const edgeList cellEdges =
c[celli].edges(
f);
1437 const edgeList curFaceEdges =
f[curFaces[facei]].edges();
1439 forAll(curFaceEdges, faceEdgeI)
1441 const edge& curEdge = curFaceEdges[faceEdgeI];
1443 forAll(cellEdges, cellEdgeI)
1445 if (cellEdges[cellEdgeI] == curEdge)
1447 edgeUsage[cellEdgeI]++;
1455 label nSingleEdges = 0;
1459 if (edgeUsage[edgeI] == 1)
1461 singleEdges[nSingleEdges] = cellEdges[edgeI];
1464 else if (edgeUsage[edgeI] != 2)
1473 if (nSingleEdges > 0)
1490 Info<<
" ***Open cells found, number of cells: " << nOpenCells
1491 <<
". This problem may be fixable using the zipUpMesh utility."
1501 Info<<
" Topological cell zip-up check OK." <<
endl;
1524 label nErrorFaces = 0;
1528 const face& curFace =
f[fI];
1545 const bool inserted = facePoints.
insert(curFace[fp]);
1561 if (nErrorFaces > 0)
1565 Info<<
" ***Faces with invalid vertex labels found, "
1566 <<
" number of faces: " << nErrorFaces <<
endl;
1575 Info<<
" Face vertices OK." <<
endl;
1595 label nFaceErrors = 0;
1596 label nCellErrors = 0;
1602 if (pf[pointi].empty())
1632 if (nFaceErrors > 0 || nCellErrors > 0)
1636 Info<<
" ***Unused points found in the mesh, "
1637 "number unused by faces: " << nFaceErrors
1638 <<
" number unused by cells: " << nCellErrors
1661 label& nBaffleFaces,
1669 const label nbFacei = iter.key();
1670 const label nCommon = iter();
1672 const face& curFace = mesh.
faces()[facei];
1673 const face& nbFace = mesh.
faces()[nbFacei];
1675 if (nCommon == nbFace.
size() || nCommon == curFace.
size())
1677 if (nbFace.
size() != curFace.
size())
1710 const label nbFacei = iter.key();
1711 const label nCommon = iter();
1713 const face& curFace = mesh.
faces()[facei];
1714 const face& nbFace = mesh.
faces()[nbFacei];
1719 && nCommon != nbFace.
size()
1720 && nCommon != curFace.
size()
1752 if (nbFace[nbPlus1] == curFace[fpPlus1])
1757 else if (nbFace[nbPlus1] == curFace[fpMin1])
1762 else if (nbFace[nbMin1] == curFace[fpMin1])
1782 if (curFp >= curFace.
size())
1788 curFp = curFace.
size()-1;
1793 if (curNb >= nbFace.
size())
1799 curNb = nbFace.
size()-1;
1801 }
while (curFace[curFp] == nbFace[curNb]);
1810 for (
label commonI = 0; commonI < nCommon; commonI++)
1814 if (curFp >= curFace.
size())
1820 curFp = curFace.
size()-1;
1825 if (curNb >= nbFace.
size())
1831 curNb = nbFace.
size()-1;
1834 if (curFace[curFp] != nbFace[curNb])
1874 label nBaffleFaces = 0;
1875 label nErrorDuplicate = 0;
1876 label nErrorOrder = 0;
1879 for (
label facei = 0; facei < mesh.
nFaces(); facei++)
1881 const face& curFace = mesh.
faces()[facei];
1885 nCommonPoints.
clear();
1889 const label pointi = curFace[fp];
1894 const label nbFacei = nbs[nbI];
1896 if (facei < nbFacei)
1902 if (fnd == nCommonPoints.
end())
1905 nCommonPoints.
insert(nbFacei, 1);
1946 Info<<
" Number of identical duplicate faces (baffle faces): "
1947 << nBaffleFaces <<
endl;
1950 if (nErrorDuplicate > 0 || nErrorOrder > 0)
1953 if (nErrorDuplicate > 0)
1955 Info<<
" <<Number of duplicate (not baffle) faces found: "
1957 <<
". This might indicate a problem." <<
endl;
1960 if (nErrorOrder > 0)
1962 Info<<
" <<Number of faces with non-consecutive shared points: "
1963 << nErrorOrder <<
". This might indicate a problem." <<
endl;
1972 Info<<
" Face-face connectivity OK." <<
endl;
#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.
bool insert(const Key &key)
Insert a new entry.
bool insert(const Key &, const T &newElmt)
Insert a new hashedEntry.
iterator find(const Key &)
Find and return an iterator set at the hashedEntry.
void clear()
Clear all entries from table.
void size(const label)
Override size to be inconsistent with allocated storage.
void setSize(const label)
Reset size of List.
A list that is sorted upon construction or when explicitly requested with the sort() method.
const labelList & indices() const
Return the list of sorted indices. Updated every sort.
void sort()
(stable) sort the list (if changed after construction time)
label rcIndex(const label i) const
Return the reverse circular index, i.e. the previous index.
label fcIndex(const label i) const
Return the forward circular index, i.e. the next index.
bool empty() const
Return true if the UList is empty (ie, size() is zero)
A cell is defined as a list of faces with extra functionality.
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Class to handle errors and exceptions in a simple, consistent stream-based manner.
A face is a list of labels corresponding to mesh vertices.
Cell-face mesh analysis engine.
const vectorField & faceCentres() const
virtual const faceList & faces() const =0
Return faces.
const labelListList & pointCells() const
const scalarField & cellVolumes() const
const vectorField & cellCentres() const
virtual const labelList & faceOwner() const =0
Face face-owner addressing.
label nInternalFaces() const
const labelListList & pointFaces() const
virtual const labelList & faceNeighbour() const =0
Face face-neighbour addressing.
virtual const pointField & points() const =0
Return mesh points.
const vectorField & faceAreas() const
bool isInternalFace(const label faceIndex) const
Return true if given face label is internal to the mesh.
const cellList & cells() const
A class for managing temporary objects.
T & ref() const
Return non-const reference or generate a fatal error.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
volScalarField scalarField(fieldObject, mesh)
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))
#define InfoInFunction
Report an information message using Foam::Info.
const dimensionedScalar c
Speed of light in a vacuum.
tmp< scalarField > faceConcavity(const scalar maxSin, const primitiveMesh &mesh, const pointField &p, const vectorField &faceAreas)
Generate face concavity field. Returns per face the (sin of the)
void cellClosedness(const primitiveMesh &mesh, const Vector< label > &meshD, const vectorField &areas, const scalarField &vols, scalarField &openness, scalarField &aratio)
Generate cell openness and cell aspect ratio field.
bool checkFacePyramids(const bool report, const scalar minPyrVol, const polyMesh &, const vectorField &cellCentres, const pointField &p, const labelList &checkFaces, const List< labelPair > &baffles, labelHashSet *)
Check face pyramid volumes.
tmp< scalarField > faceOrthogonality(const polyMesh &mesh, const vectorField &fAreas, const vectorField &cellCtrs)
Generate orthogonality field. (1 for fully orthogonal, < 1 for.
tmp< scalarField > faceSkewness(const polyMesh &mesh, const pointField &points, const vectorField &fCtrs, const vectorField &fAreas, const vectorField &cellCtrs)
Generate skewness field.
bool checkFaceFaces(const primitiveMesh &mesh, const bool report=false, labelHashSet *setPtr=nullptr)
Check face-face connectivity.
bool checkUpperTriangular(const primitiveMesh &mesh, const bool report=false, labelHashSet *setPtr=nullptr)
Check face ordering.
bool checkConcaveCells(const primitiveMesh &mesh, const scalar planarCosAngle, const bool report=false, labelHashSet *setPtr=nullptr)
Check for concave cells by the planes of faces.
bool checkFaceAngles(const bool report, const scalar maxConcave, const polyMesh &mesh, const vectorField &faceAreas, const pointField &p, const labelList &checkFaces, labelHashSet *setPtr)
Check convexity of angles in a face. See primitiveMesh for explanation.
bool checkDuplicateFaces(const primitiveMesh &mesh, const label, const Map< label > &, label &nBaffleFaces, labelHashSet *)
Check if all points on face are shared with another face.
bool checkFaceVertices(const primitiveMesh &mesh, const bool report=false, labelHashSet *setPtr=nullptr)
Check uniqueness of face vertices.
scalar boundaryFaceSkewness(const primitiveMesh &mesh, const pointField &p, const vectorField &fCtrs, const vectorField &fAreas, const label facei, const point &ownCc)
Skewness of single boundary face.
bool checkClosedCells(const primitiveMesh &mesh, const scalar closedThreshold, const scalar aspectThreshold, const bool report=false, labelHashSet *setPtr=nullptr, labelHashSet *highAspectSetPtr=nullptr, const Vector< label > &solutionD=Vector< label >::one)
Check cells for closedness.
bool checkCommonOrder(const primitiveMesh &mesh, const label, const Map< label > &, labelHashSet *)
Check that shared points are in consecutive order.
void facePyramidVolume(const primitiveMesh &mesh, const pointField &points, const vectorField &cellCtrs, scalarField &ownPyrVol, scalarField &neiPyrVol)
Generate face pyramid volume fields.
tmp< scalarField > cellDeterminant(const primitiveMesh &mesh, const Vector< label > &directions, const vectorField &faceAreas, const PackedBoolList &internalOrCoupledFace)
Generate cell determinant field.
tmp< scalarField > faceFlatness(const primitiveMesh &mesh, const pointField &p, const vectorField &fCtrs, const vectorField &faceAreas)
Generate face flatness field. Compares the individual triangles'.
bool checkClosedBoundary(const primitiveMesh &mesh, const scalar closedThreshold, const bool report=false)
Check boundary for closedness.
bool checkFaceFlatness(const bool report, const scalar minFlatness, const polyMesh &, const vectorField &faceAreas, const vectorField &faceCentres, const pointField &p, const labelList &checkFaces, labelHashSet *setPtr)
Check for face areas v.s. sum of face-triangle (from face-centre.
bool checkCellVolumes(const primitiveMesh &mesh, const bool report=false, labelHashSet *setPtr=nullptr)
Check for negative cell volumes.
bool checkFaceAreas(const primitiveMesh &mesh, const bool report=false, labelHashSet *setPtr=nullptr)
Check for negative face areas.
bool checkPoints(const primitiveMesh &mesh, const bool report=false, labelHashSet *setPtr=nullptr)
Check for unused points.
bool checkCellsZipUp(const primitiveMesh &mesh, const bool report=false, labelHashSet *setPtr=nullptr)
Check cell zip-up.
pyramid< point, const point &, const face & > pyramidPointFaceRef
dimensionedScalar det(const dimensionedSphericalTensor &dt)
errorManipArg< error, int > exit(error &err, const int errNo=1)
dimensionedScalar asin(const dimensionedScalar &ds)
Type gSum(const FieldField< Field, Type > &f)
scalar radToDeg(const scalar rad)
Convert radians to degrees.
scalar degToRad(const scalar deg)
Convert degrees to radians.
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.
errorManip< error > abort(error &err)
dimensionedScalar sin(const dimensionedScalar &ds)
layerAndWeight min(const layerAndWeight &a, const layerAndWeight &b)
dimensionedScalar pow(const dimensionedScalar &ds, const dimensionedScalar &expt)
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
dimensioned< scalar > mag(const dimensioned< Type > &)
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
dimensionSet cmptMag(const dimensionSet &)
void cmptMax(FieldField< Field, typename FieldField< Field, Type >::cmptType > &cf, const FieldField< Field, Type > &f)
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurrence of given element and return index,.
static const label labelMax
Cmpt cmptSum(const VectorSpace< Form, Cmpt, Ncmpts > &vs)
dimensionedTensor skew(const dimensionedTensor &dt)
static iteratorEnd end()
iteratorEnd set to beyond the end of any HashTable