Go to the documentation of this file.
51 label facei = changedFaces[i];
60 faceCentres_[facei] = (1.0/3.0)*(
p[
f[0]] +
p[
f[1]] +
p[
f[2]]);
61 faceAreas_[facei] = 0.5*((
p[
f[1]] -
p[
f[0]])^(
p[
f[2]] -
p[
f[0]]));
65 vector sumN = vector::zero;
67 vector sumAc = vector::zero;
90 faceCentres_[facei] = (1.0/3.0)*sumAc/(sumA + VSMALL);
91 faceAreas_[facei] = 0.5*sumN;
107 const labelList& own = mesh_.faceOwner();
108 const labelList& nei = mesh_.faceNeighbour();
119 label faceI = changedFaces[i];
120 cEst[own[faceI]] += faceCentres_[faceI];
121 nCellFaces[own[faceI]] += 1;
123 if (mesh_.isInternalFace(faceI))
125 cEst[nei[faceI]] += faceCentres_[faceI];
126 nCellFaces[nei[faceI]] += 1;
132 label cellI = changedCells[i];
133 cEst[cellI] /= nCellFaces[cellI];
138 label faceI = changedFaces[i];
143 faceAreas_[faceI] & (faceCentres_[faceI] - cEst[own[faceI]]),
148 vector pc = (3.0/4.0)*faceCentres_[faceI] + (1.0/4.0)*cEst[own[faceI]];
151 cellCentres_[own[faceI]] += pyr3Vol*pc;
154 cellVolumes_[own[faceI]] += pyr3Vol;
156 if (mesh_.isInternalFace(faceI))
161 faceAreas_[faceI] & (cEst[nei[faceI]] - faceCentres_[faceI]),
167 (3.0/4.0)*faceCentres_[faceI]
168 + (1.0/4.0)*cEst[nei[faceI]];
171 cellCentres_[nei[faceI]] += pyr3Vol*pc;
174 cellVolumes_[nei[faceI]] += pyr3Vol;
180 label cellI = changedCells[i];
182 cellCentres_[cellI] /= cellVolumes_[cellI];
183 cellVolumes_[cellI] *= (1.0/3.0);
193 const labelList& own = mesh_.faceOwner();
194 const labelList& nei = mesh_.faceNeighbour();
200 label faceI = changedFaces[i];
202 affectedCells.
insert(own[faceI]);
204 if (mesh_.isInternalFace(faceI))
206 affectedCells.
insert(nei[faceI]);
209 return affectedCells.
toc();
251 updateFaceCentresAndAreas(
p, changedFaces);
253 updateCellCentresAndVols(affectedCells(changedFaces), changedFaces);
260 const scalar orthWarn,
274 const scalar severeNonorthogonalityThreshold =
::cos(
degToRad(orthWarn));
276 scalar minDDotS = GREAT;
280 label severeNonOrth = 0;
282 label errorNonOrth = 0;
286 label faceI = checkFaces[i];
290 vector d = cellCentres[nei[faceI]] - cellCentres[own[faceI]];
291 const vector&
s = faceAreas[faceI];
293 scalar dDotS = (d &
s)/(
mag(d)*
mag(
s) + VSMALL);
295 if (dDotS < severeNonorthogonalityThreshold)
302 Pout<<
"Severe non-orthogonality for face " << faceI
303 <<
" between cells " << own[faceI]
304 <<
" and " << nei[faceI]
322 <<
"Severe non-orthogonality detected for face "
324 <<
" between cells " << own[faceI] <<
" and "
339 if (dDotS < minDDotS)
359 if (report && minDDotS < severeNonorthogonalityThreshold)
361 Info<<
"Number of non-orthogonality errors: " << errorNonOrth
362 <<
". Number of severely non-orthogonal faces: "
363 << severeNonOrth <<
"." <<
endl;
371 Info<<
"Mesh non-orthogonality Max: "
378 if (errorNonOrth > 0)
383 <<
"Error in non-orthogonality detected" <<
endl;
392 Info<<
"Non-orthogonality check OK.\n" <<
endl;
403 const scalar minPyrVol,
417 label nErrorPyrs = 0;
421 label faceI = checkFaces[i];
427 cellCentres[own[faceI]]
430 if (pyrVol > -minPyrVol)
434 Pout<<
"bool primitiveMeshGeometry::checkFacePyramids("
435 <<
"const bool, const scalar, const pointField&"
436 <<
", const labelList&, labelHashSet*): "
437 <<
"face " << faceI <<
" points the wrong way. " <<
endl
438 <<
"Pyramid volume: " << -pyrVol
439 <<
" Face " <<
f[faceI] <<
" area: " <<
f[faceI].mag(
p)
440 <<
" Owner cell: " << own[faceI] <<
endl
441 <<
"Owner cell vertex labels: "
461 if (pyrVol < minPyrVol)
465 Pout<<
"bool primitiveMeshGeometry::checkFacePyramids("
466 <<
"const bool, const scalar, const pointField&"
467 <<
", const labelList&, labelHashSet*): "
468 <<
"face " << faceI <<
" points the wrong way. " <<
endl
469 <<
"Pyramid volume: " << -pyrVol
470 <<
" Face " <<
f[faceI] <<
" area: " <<
f[faceI].mag(
p)
471 <<
" Neighbour cell: " << nei[faceI] <<
endl
472 <<
"Neighbour cell vertex labels: "
494 <<
"Error in face pyramids: faces pointing the wrong way!"
504 Info<<
"Face pyramids OK.\n" <<
endl;
515 const scalar internalSkew,
516 const scalar boundarySkew,
537 label faceI = checkFaces[i];
541 scalar dOwn =
mag(faceCentres[faceI] - cellCentres[own[faceI]]);
542 scalar dNei =
mag(faceCentres[faceI] - cellCentres[nei[faceI]]);
544 point faceIntersection =
545 cellCentres[own[faceI]]*dNei/(dOwn+dNei)
546 + cellCentres[nei[faceI]]*dOwn/(dOwn+dNei);
549 mag(faceCentres[faceI] - faceIntersection)
551 mag(cellCentres[nei[faceI]]-cellCentres[own[faceI]])
558 if (skewness > internalSkew)
562 Pout<<
"Severe skewness for face " << faceI
563 <<
" skewness = " << skewness <<
endl;
574 if (skewness > maxSkew)
584 vector faceNormal = faceAreas[faceI];
585 faceNormal /=
mag(faceNormal) + VSMALL;
587 vector dOwn = faceCentres[faceI] - cellCentres[own[faceI]];
589 vector dWall = faceNormal*(faceNormal & dOwn);
591 point faceIntersection = cellCentres[own[faceI]] + dWall;
594 mag(faceCentres[faceI] - faceIntersection)
595 /(2*
mag(dWall) + VSMALL);
600 if (skewness > boundarySkew)
604 Pout<<
"Severe skewness for boundary face " << faceI
605 <<
" skewness = " << skewness <<
endl;
616 if (skewness > maxSkew)
632 <<
" percent.\nThis may impair the quality of the result." <<
nl
633 << nWarnSkew <<
" highly skew faces detected."
643 Info<<
"Max skewness = " << 100*maxSkew
644 <<
" percent. Face skewness OK.\n" <<
endl;
655 const scalar warnWeight,
669 scalar minWeight = GREAT;
671 label nWarnWeight = 0;
675 label faceI = checkFaces[i];
679 const point& fc = faceCentres[faceI];
681 scalar dOwn =
mag(faceAreas[faceI] & (fc-cellCentres[own[faceI]]));
682 scalar dNei =
mag(faceAreas[faceI] & (cellCentres[nei[faceI]]-fc));
684 scalar weight =
min(dNei,dOwn)/(dNei+dOwn);
686 if (weight < warnWeight)
690 Pout<<
"Small weighting factor for face " << faceI
691 <<
" weight = " << weight <<
endl;
702 minWeight =
min(minWeight, weight);
709 if (minWeight < warnWeight)
714 << minWeight <<
'.' <<
nl
715 << nWarnWeight <<
" faces with small weights detected."
725 Info<<
"Min weight = " << minWeight
726 <<
" percent. Weights OK.\n" <<
endl;
749 if (maxDeg < -SMALL || maxDeg > 180+SMALL)
752 <<
"maxDeg should be [0..180] but is now " << maxDeg
760 scalar maxEdgeSin = 0.0;
764 label errorFaceI = -1;
768 label faceI = checkFaces[i];
770 const face&
f = fcs[faceI];
772 vector faceNormal = faceAreas[faceI];
773 faceNormal /=
mag(faceNormal) + VSMALL;
777 scalar magEPrev =
mag(ePrev);
778 ePrev /= magEPrev + VSMALL;
783 label fp1 =
f.fcIndex(fp0);
787 scalar magE10 =
mag(e10);
788 e10 /= magE10 + VSMALL;
790 if (magEPrev > SMALL && magE10 > SMALL)
792 vector edgeNormal = ePrev ^ e10;
793 scalar magEdgeNormal =
mag(edgeNormal);
795 if (magEdgeNormal < maxSin)
802 edgeNormal /= magEdgeNormal;
804 if ((edgeNormal & faceNormal) < SMALL)
806 if (faceI != errorFaceI)
818 maxEdgeSin =
max(maxEdgeSin, magEdgeNormal);
833 if (maxEdgeSin > SMALL)
835 scalar maxConcaveDegr =
838 Info<<
"There are " << nConcave
839 <<
" faces with concave angles between consecutive"
840 <<
" edges. Max concave angle = " << maxConcaveDegr
841 <<
" degrees.\n" <<
endl;
845 Info<<
"All angles in faces are convex or less than " << maxDeg
846 <<
" degrees concave.\n" <<
endl;
855 << nConcave <<
" face points with severe concave angle (> "
856 << maxDeg <<
" deg) found.\n"
1004 const scalar minTwist,
1013 if (minTwist < -1-SMALL || minTwist > 1+SMALL)
1016 <<
"minTwist should be [-1..1] but is now " << minTwist
1030 label faceI = checkFaces[i];
1032 const face&
f = fcs[faceI];
1034 scalar magArea =
mag(faceAreas[faceI]);
1036 if (
f.
size() > 3 && magArea > VSMALL)
1038 const vector nf = faceAreas[faceI] / magArea;
1040 const point& fc = faceCentres[faceI];
1049 p[
f.nextLabel(fpI)],
1054 scalar magTri =
mag(triArea);
1056 if (magTri > VSMALL && ((nf & triArea/magTri) < minTwist))
1076 Info<<
"There are " << nWarped
1077 <<
" faces with cosine of the angle"
1078 <<
" between triangle normal and face normal less than "
1079 << minTwist <<
nl <<
endl;
1083 Info<<
"All faces are flat in that the cosine of the angle"
1084 <<
" between triangle normal and face normal less than "
1085 << minTwist <<
nl <<
endl;
1094 << nWarped <<
" faces with severe warpage "
1095 <<
"(cosine of the angle between triangle normal and "
1096 <<
"face normal < " << minTwist <<
") found.\n"
1112 const scalar minArea,
1119 label nZeroArea = 0;
1123 label faceI = checkFaces[i];
1125 if (
mag(faceAreas[faceI]) < minArea)
1142 Info<<
"There are " << nZeroArea
1143 <<
" faces with area < " << minArea <<
'.' <<
nl <<
endl;
1147 Info<<
"All faces have area > " << minArea <<
'.' <<
nl <<
endl;
1156 << nZeroArea <<
" faces with area < " << minArea
1173 const scalar warnDet,
1183 scalar minDet = GREAT;
1184 scalar sumDet = 0.0;
1190 const cell& cFaces =
cells[affectedCells[i]];
1193 scalar magAreaSum = 0;
1197 label faceI = cFaces[cFaceI];
1199 scalar magArea =
mag(faceAreas[faceI]);
1201 magAreaSum += magArea;
1202 areaSum += faceAreas[faceI]*(faceAreas[faceI]/magArea);
1205 scalar scaledDet =
det(areaSum/magAreaSum)/0.037037037037037;
1207 minDet =
min(minDet, scaledDet);
1208 sumDet += scaledDet;
1211 if (scaledDet < warnDet)
1218 label faceI = cFaces[cFaceI];
1235 Info<<
"Cell determinant (1 = uniform cube) : average = "
1236 << sumDet / nSumDet <<
" min = " << minDet <<
endl;
1241 Info<<
"There are " << nWarnDet
1242 <<
" cells with determinant < " << warnDet <<
'.' <<
nl
1247 Info<<
"All faces have determinant > " << warnDet <<
'.' <<
nl
1257 << nWarnDet <<
" cells with determinant < " << warnDet
1274 const scalar orthWarn,
1295 const scalar minPyrVol,
1317 const scalar internalSkew,
1318 const scalar boundarySkew,
1341 const scalar warnWeight,
1346 return checkFaceWeights
1363 const scalar maxDeg,
1408 const scalar minTwist,
1414 return checkFaceTwist
1431 const scalar minArea,
1436 return checkFaceArea
1451 const scalar warnDet,
1457 return checkCellDeterminant
vectorField faceAreas_
Uptodate copy of face areas.
vectorField cellCentres_
Uptodate copy of cell centres.
Templated 3D tensor derived from VectorSpace adding construction from 9 components,...
labelList affectedCells(const labelList &changedFaces) const
Helper function: get affected cells from faces.
void checkFaceSkewness(const polyMeshGen &, scalarField &, const boolList *changedFacePtr=NULL)
Check face skewness.
List< Key > toc() const
Return the table of contents.
#define forAll(list, i)
Loop across all elements in list.
dimensionedScalar sin(const dimensionedScalar &ds)
const cellList & cells() const
Unit conversion functions.
Ostream & endl(Ostream &os)
Add newline and flush stream.
static bool checkFacePyramids(const bool report, const scalar minPyrVol, const primitiveMesh &, const vectorField &cellCentres, const pointField &p, const labelList &checkFaces, labelHashSet *)
dimensioned< scalar > mag(const dimensioned< Type > &)
static bool checkCellDeterminant(const bool report, const scalar minDet, const primitiveMesh &, const vectorField &faceAreas, const labelList &checkFaces, const labelList &affectedCells, labelHashSet *setPtr)
bool checkFaceAngles(const polyMeshGen &, const bool report=false, const scalar maxDeg=10, labelHashSet *setPtr=NULL, const boolList *changedFacePtr=NULL)
Check face angles.
A triangle primitive used to calculate face normals and swept volumes.
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Pre-declare SubField and related Field type.
vector normal() const
Return vector normal.
const primitiveMesh & mesh_
Reference to primitiveMesh.
vectorField faceCentres_
Uptodate copy of face centres.
virtual const labelList & faceOwner() const
Return face owner.
#define SeriousErrorInFunction
Report an error message using Foam::SeriousError.
void checkFaceDotProduct(const polyMeshGen &, scalarField &, const boolList *changedFacePtr=NULL)
Check for non-orthogonality.
static bool checkFaceAngles(const bool report, const scalar maxDeg, const primitiveMesh &mesh, const vectorField &faceAreas, const pointField &p, const labelList &checkFaces, labelHashSet *setPtr)
static bool checkFaceSkewness(const bool report, const scalar internalSkew, const scalar boundarySkew, const primitiveMesh &mesh, const vectorField &cellCentres, const vectorField &faceCentres, const vectorField &faceAreas, const labelList &checkFaces, labelHashSet *setPtr)
errorManip< error > abort(error &err)
const scalarField & cellVolumes() const
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.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
bool checkFacePyramids(const polyMeshGen &, const bool report=false, const scalar minPyrVol=-SMALL, labelHashSet *setPtr=NULL, const boolList *changedFacePtr=NULL)
Check face pyramid volume.
void correct()
Take over properties from mesh.
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
const vectorField & cellCentres() const
virtual const faceList & faces() const
Return raw faces.
primitiveMeshGeometry(const primitiveMesh &)
Construct from mesh.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
scalarField cellVolumes_
Uptodate copy of cell volumes.
prefixOSstream Pout(cout, "Pout")
static bool checkFaceArea(const bool report, const scalar minArea, const primitiveMesh &, const vectorField &faceAreas, const labelList &checkFaces, labelHashSet *setPtr)
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
bool isInternalFace(const label faceIndex) const
Return true if given face label is internal to the mesh.
dimensionedScalar acos(const dimensionedScalar &ds)
const vectorField & faceCentres() const
static bool checkFaceDotProduct(const bool report, const scalar orthWarn, const primitiveMesh &, const vectorField &cellCentres, const vectorField &faceAreas, const labelList &checkFaces, labelHashSet *setPtr)
static bool checkFaceWeights(const bool report, const scalar warnWeight, const primitiveMesh &mesh, const vectorField &cellCentres, const vectorField &faceCentres, const vectorField &faceAreas, const labelList &checkFaces, labelHashSet *setPtr)
void updateCellCentresAndVols(const labelList &changedCells, const labelList &changedFaces)
Update cell volumes and centres on selected cells. Requires.
bool insert(const Key &key)
Insert a new entry.
scalar radToDeg(const scalar rad)
Conversion from radians to degrees.
const dimensionedScalar c
Speed of light in a vacuum.
A List with indirect addressing.
A face is a list of labels corresponding to mesh vertices.
void updateFaceCentresAndAreas(const pointField &p, const labelList &changedFaces)
Update face areas and centres on selected faces.
dimensionedScalar det(const dimensionedSphericalTensor &dt)
static bool checkFaceTwist(const bool report, const scalar minTwist, const primitiveMesh &, const vectorField &faceAreas, const vectorField &faceCentres, const pointField &p, const labelList &checkFaces, labelHashSet *setPtr)
void size(const label)
Override size to be inconsistent with allocated storage.
defineTypeNameAndDebug(combustionModel, 0)
dimensioned< Type > min(const dimensioned< Type > &, const dimensioned< Type > &)
pyramid< point, const point &, const face & > pyramidPointFaceRef
#define WarningInFunction
Report a warning using Foam::Warning.
A cell is defined as a list of faces with extra functionality.
dimensionedScalar asin(const dimensionedScalar &ds)
virtual const labelList & faceNeighbour() const
Return face neighbour.
scalar degToRad(const scalar deg)
Conversion from degrees to radians.
dimensionedScalar cos(const dimensionedScalar &ds)
const vectorField & faceAreas() const
Cell-face mesh analysis engine.