26 const wedgePolyPatch& wpp
29 const polyBoundaryMesh&
patches =
mesh.boundaryMesh();
31 scalar wppCosAngle = wpp.cosAngle();
39 && isA<wedgePolyPatch>(
patches[patchi])
42 const auto&
pp = refCast<const wedgePolyPatch>(
patches[patchi]);
45 scalar ppCosAngle = wpp.centreNormal() &
pp.n();
49 pp.size() == wpp.size()
50 &&
mag(
pp.axis() & wpp.axis()) >= (1-1
e-3)
51 &&
mag(ppCosAngle - wppCosAngle) >= 1
e-3
66 const Vector<label>& directions,
71 EdgeMap<label> edgesInError;
77 const polyBoundaryMesh&
patches =
mesh.boundaryMesh();
80 if (
patches[patchi].size() && isA<wedgePolyPatch>(
patches[patchi]))
82 const auto&
pp = refCast<const wedgePolyPatch>(
patches[patchi]);
84 scalar wedgeAngle =
acos(
pp.cosAngle());
88 Info<<
" Wedge " <<
pp.name() <<
" with angle "
89 <<
radToDeg(wedgeAngle) <<
" degrees"
96 if (oppositePatchi == -1)
100 Info<<
" ***Cannot find opposite wedge for wedge "
107 refCast<const wedgePolyPatch>(
patches[oppositePatchi]);
110 if (
mag(opp.axis() &
pp.axis()) < (1-1
e-3))
114 Info<<
" ***Wedges do not have the same axis."
115 <<
" Encountered " <<
pp.axis()
116 <<
" on patch " <<
pp.name()
117 <<
" which differs from " << opp.axis()
118 <<
" on opposite wedge patch" << opp.axis()
129 const face&
f =
pp[i];
133 label p1 =
f.nextLabel(fp);
134 edgesInError.insert(edge(
p0, p1), -1);
143 const point& pt =
p[
pp.meshPoints()[i]];
144 scalar d =
mag((pt -
p0) &
pp.n());
150 Info<<
" ***Wedge patch " <<
pp.name() <<
" not planar."
151 <<
" Point " << pt <<
" is not in patch plane by "
164 label nEdgesInError = 0;
168 const face&
f = fcs[facei];
173 label p1 =
f.nextLabel(fp);
177 scalar magD =
mag(d);
179 if (magD > ROOTVSMALL)
184 label nEmptyDirs = 0;
185 label nNonEmptyDirs = 0;
186 for (direction cmpt=0; cmpt<vector::nComponents; cmpt++)
188 if (
mag(d[cmpt]) > 1
e-6)
190 if (directions[cmpt] == 0)
205 else if (nEmptyDirs == 1)
208 if (nNonEmptyDirs > 0)
210 if (edgesInError.insert(edge(
p0, p1), facei))
216 else if (nEmptyDirs > 1)
219 if (edgesInError.insert(edge(
p0, p1), facei))
229 label nErrorEdges =
returnReduce(nEdgesInError, sumOp<label>());
235 Info<<
" ***Number of edges not aligned with or perpendicular to "
236 <<
"non-empty directions: " << nErrorEdges <<
endl;
241 setPtr->reserve(2*nEdgesInError);
246 setPtr->insert(iter.key().first());
247 setPtr->insert(iter.key().second());
257 Info<<
" All edges aligned with or perpendicular to "
258 <<
"non-empty directions." <<
endl;
268 class transformPositionList
275 const coupledPolyPatch& cpp,
276 UList<pointField>&
pts
282 List<pointField> newPts(
pts.size());
285 newPts[facei].resize(
pts[facei].size());
300 if (facePts.size() > index)
302 ptsAtIndex[facei] = facePts[index];
314 cpp.transformPosition(ptsAtIndex);
320 if (facePts.size() > index)
322 facePts[index] = ptsAtIndex[facei];
330 std::move(newPts.begin(), newPts.end(),
pts.begin());
338 const polyMesh&
mesh,
345 const polyBoundaryMesh&
patches =
mesh.boundaryMesh();
349 List<pointField> nbrPoints(fcs.size() -
mesh.nInternalFaces());
356 const auto& cpp = refCast<const coupledPolyPatch>(
patches[patchi]);
360 label bFacei = cpp.start() + i -
mesh.nInternalFaces();
361 const face&
f = cpp[i];
362 nbrPoints[bFacei].setSize(
f.size());
366 nbrPoints[bFacei][fp] =
p0;
371 syncTools::syncBoundaryFaceList
376 transformPositionList()
380 label nErrorFaces = 0;
381 scalar avgMismatch = 0;
382 label nCoupledPoints = 0;
388 const auto& cpp = refCast<const coupledPolyPatch>(
patches[patchi]);
405 label bFacei = cpp.start() + i -
mesh.nInternalFaces();
406 const face&
f = cpp[i];
408 if (
f.size() != nbrPoints[bFacei].size())
411 <<
"Local face size : " <<
f.size()
412 <<
" does not equal neighbour face size : "
413 << nbrPoints[bFacei].size()
414 <<
abort(FatalError);
421 scalar d =
mag(
p0 - nbrPoints[bFacei][j]);
423 if (d > smallDist[i])
427 setPtr->insert(cpp.start()+i);
444 reduce(nErrorFaces, sumOp<label>());
445 reduce(avgMismatch, maxOp<scalar>());
446 reduce(nCoupledPoints, sumOp<label>());
448 if (nCoupledPoints > 0)
450 avgMismatch /= nCoupledPoints;
457 Info<<
" **Error in coupled point location: "
459 <<
" faces have their 0th or consecutive vertex not opposite"
460 <<
" their coupled equivalent. Average mismatch "
461 << avgMismatch <<
"."
470 Info<<
" Coupled point location match (average "
471 << avgMismatch <<
") OK." <<
endl;
480 const polyMesh&
mesh,
482 const fileName& fName,
483 const scalarField& weights,
484 const faceList& localFaces,
485 const labelList& meshPoints,
486 const Map<label>& meshPointMap,
489 faceList& mergedFaces,
490 pointField& mergedPoints,
491 autoPtr<globalIndex>& globalFaces,
492 autoPtr<globalIndex>& globalPoints
505 uniqueMeshPointLabels,
514 globalFaces().gather(weights, mergedWeights);
516 if (Pstream::master())
526 wr.write(
"weightsSum", mergedWeights);
534 const polyMesh&
mesh,
535 const bool allGeometry,
536 autoPtr<surfaceWriter>& surfWriter,
537 autoPtr<coordSetWriter>& setWriter
540 label noFailedChecks = 0;
542 Info<<
"\nChecking geometry..." <<
endl;
545 const boundBox& globalBb =
mesh.bounds();
547 Info<<
" Overall domain bounding box "
548 << globalBb.min() <<
" " << globalBb.max() <<
endl;
552 scalar minDistSqr =
magSqr(1
e-6 * globalBb.span());
555 const Vector<label> validDirs = (
mesh.geometricD() + Vector<label>::one)/2;
556 Info<<
" Mesh has " <<
mesh.nGeometricD()
557 <<
" geometric (non-empty/wedge) directions " << validDirs <<
endl;
560 const Vector<label> solDirs = (
mesh.solutionD() + Vector<label>::one)/2;
561 Info<<
" Mesh has " <<
mesh.nSolutionD()
562 <<
" solution (non-empty) directions " << solDirs <<
endl;
564 if (
mesh.nGeometricD() < 3)
566 pointSet nonAlignedPoints(
mesh,
"nonAlignedEdges",
mesh.nPoints()/100);
576 &&
mesh.checkEdgeAlignment(
true, validDirs, &nonAlignedPoints)
583 nonAlignedPoints.size(),
589 Info<<
" <<Writing " << nNonAligned
590 <<
" points on non-aligned edges to set "
591 << nonAlignedPoints.name() <<
endl;
592 nonAlignedPoints.instance() =
mesh.pointsInstance();
593 nonAlignedPoints.write();
594 if (setWriter && setWriter->enabled())
602 if (
mesh.checkClosedBoundary(
true)) noFailedChecks++;
606 cellSet aspectCells(
mesh,
"highAspectRatioCells",
mesh.nCells()/100+1);
609 mesh.checkClosedCells
624 Info<<
" <<Writing " << nNonClosed
625 <<
" non closed cells to set " <<
cells.name() <<
endl;
626 cells.instance() =
mesh.pointsInstance();
628 if (surfWriter && surfWriter->enabled())
635 label nHighAspect =
returnReduce(aspectCells.size(), sumOp<label>());
639 Info<<
" <<Writing " << nHighAspect
640 <<
" cells with high aspect ratio to set "
641 << aspectCells.name() <<
endl;
642 aspectCells.instance() =
mesh.pointsInstance();
644 if (surfWriter && surfWriter->enabled())
652 faceSet faces(
mesh,
"zeroAreaFaces",
mesh.nFaces()/100+1);
653 if (
mesh.checkFaceAreas(
true, &faces))
657 label nFaces =
returnReduce(faces.size(), sumOp<label>());
661 Info<<
" <<Writing " << nFaces
662 <<
" zero area faces to set " << faces.name() <<
endl;
663 faces.instance() =
mesh.pointsInstance();
665 if (surfWriter && surfWriter->enabled())
683 Info<<
" <<Writing " << nCells
684 <<
" zero volume cells to set " <<
cells.name() <<
endl;
685 cells.instance() =
mesh.pointsInstance();
687 if (surfWriter && surfWriter->enabled())
696 faceSet faces(
mesh,
"nonOrthoFaces",
mesh.nFaces()/100+1);
697 if (
mesh.checkFaceOrthogonality(
true, &faces))
702 label nFaces =
returnReduce(faces.size(), sumOp<label>());
706 Info<<
" <<Writing " << nFaces
707 <<
" non-orthogonal faces to set " << faces.name() <<
endl;
708 faces.instance() =
mesh.pointsInstance();
710 if (surfWriter && surfWriter->enabled())
718 faceSet faces(
mesh,
"wrongOrientedFaces",
mesh.nFaces()/100 + 1);
719 if (
mesh.checkFacePyramids(
true, -SMALL, &faces))
723 label nFaces =
returnReduce(faces.size(), sumOp<label>());
727 Info<<
" <<Writing " << nFaces
728 <<
" faces with incorrect orientation to set "
729 << faces.name() <<
endl;
730 faces.instance() =
mesh.pointsInstance();
732 if (surfWriter && surfWriter->enabled())
741 faceSet faces(
mesh,
"skewFaces",
mesh.nFaces()/100+1);
742 if (
mesh.checkFaceSkewness(
true, &faces))
746 label nFaces =
returnReduce(faces.size(), sumOp<label>());
750 Info<<
" <<Writing " << nFaces
751 <<
" skew faces to set " << faces.name() <<
endl;
752 faces.instance() =
mesh.pointsInstance();
754 if (surfWriter && surfWriter->enabled())
763 faceSet faces(
mesh,
"coupledFaces",
mesh.nFaces()/100 + 1);
768 label nFaces =
returnReduce(faces.size(), sumOp<label>());
772 Info<<
" <<Writing " << nFaces
773 <<
" faces with incorrectly matched 0th (or consecutive)"
775 << faces.name() <<
endl;
776 faces.instance() =
mesh.pointsInstance();
778 if (surfWriter && surfWriter->enabled())
788 faceSet faces(
mesh,
"lowQualityTetFaces",
mesh.nFaces()/100+1);
791 polyMeshTetDecomposition::checkFaceTets
794 polyMeshTetDecomposition::minTetQuality,
802 label nFaces =
returnReduce(faces.size(), sumOp<label>());
806 Info<<
" <<Writing " << nFaces
807 <<
" faces with low quality or negative volume "
808 <<
"decomposition tets to set " << faces.name() <<
endl;
809 faces.instance() =
mesh.pointsInstance();
811 if (surfWriter && surfWriter->enabled())
823 if (
mesh.checkEdgeLength(
true, minDistSqr, &
points))
832 <<
" points on short edges to set " <<
points.name()
836 if (setWriter && setWriter->enabled())
845 if (
mesh.checkPointNearness(
false, minDistSqr, &
points))
853 pointSet nearPoints(
mesh,
"nearPoints",
points);
855 <<
" near (closer than " <<
Foam::sqrt(minDistSqr)
856 <<
" apart) points to set " << nearPoints.
name() <<
endl;
857 nearPoints.instance() =
mesh.pointsInstance();
859 if (setWriter && setWriter->enabled())
869 faceSet faces(
mesh,
"concaveFaces",
mesh.nFaces()/100 + 1);
870 if (
mesh.checkFaceAngles(
true, 10, &faces))
874 label nFaces =
returnReduce(faces.size(), sumOp<label>());
878 Info<<
" <<Writing " << nFaces
879 <<
" faces with concave angles to set " << faces.name()
881 faces.instance() =
mesh.pointsInstance();
883 if (surfWriter && surfWriter->enabled())
893 faceSet faces(
mesh,
"warpedFaces",
mesh.nFaces()/100 + 1);
894 if (
mesh.checkFaceFlatness(
true, 0.8, &faces))
898 label nFaces =
returnReduce(faces.size(), sumOp<label>());
902 Info<<
" <<Writing " << nFaces
903 <<
" warped faces to set " << faces.name() <<
endl;
904 faces.instance() =
mesh.pointsInstance();
906 if (surfWriter && surfWriter->enabled())
916 cellSet
cells(
mesh,
"underdeterminedCells",
mesh.nCells()/100);
917 if (
mesh.checkCellDeterminant(
true, &
cells))
923 Info<<
" <<Writing " << nCells
924 <<
" under-determined cells to set " <<
cells.name() <<
endl;
925 cells.instance() =
mesh.pointsInstance();
927 if (surfWriter && surfWriter->enabled())
937 if (
mesh.checkConcaveCells(
true, &
cells))
943 Info<<
" <<Writing " << nCells
944 <<
" concave cells to set " <<
cells.name() <<
endl;
945 cells.instance() =
mesh.pointsInstance();
947 if (surfWriter && surfWriter->enabled())
956 faceSet faces(
mesh,
"lowWeightFaces",
mesh.nFaces()/100);
957 if (
mesh.checkFaceWeight(
true, 0.05, &faces))
961 label nFaces =
returnReduce(faces.size(), sumOp<label>());
963 Info<<
" <<Writing " << nFaces
964 <<
" faces with low interpolation weights to set "
965 << faces.name() <<
endl;
966 faces.instance() =
mesh.pointsInstance();
968 if (surfWriter && surfWriter->enabled())
977 faceSet faces(
mesh,
"lowVolRatioFaces",
mesh.nFaces()/100);
978 if (
mesh.checkVolRatio(
true, 0.01, &faces))
982 label nFaces =
returnReduce(faces.size(), sumOp<label>());
984 Info<<
" <<Writing " << nFaces
985 <<
" faces with low volume ratio cells to set "
986 << faces.name() <<
endl;
987 faces.instance() =
mesh.pointsInstance();
989 if (surfWriter && surfWriter->enabled())
998 const polyBoundaryMesh&
pbm =
mesh.boundaryMesh();
1000 const word tmName(
mesh.time().timeName());
1001 const word procAndTime(
Foam::name(Pstream::myProcNo()) +
"_" + tmName);
1003 autoPtr<surfaceWriter> patchWriter;
1006 patchWriter.reset(
new surfaceWriters::vtkWriter());
1009 surfaceWriter& wr = (surfWriter ? *surfWriter : *patchWriter);
1013 const fileName outputDir
1015 mesh.time().globalPath()/functionObject::outputPrefix
1016 /
mesh.regionName()/
"checkMesh"
1021 if (isA<cyclicAMIPolyPatch>(
pbm[patchi]))
1024 refCast<const cyclicAMIPolyPatch>(
pbm[patchi]);
1028 Info<<
"Calculating AMI weights between owner patch: "
1029 << cpp.name() <<
" and neighbour patch: "
1030 << cpp.neighbPatch().name() <<
endl;
1038 autoPtr<globalIndex> globalFaces;
1039 autoPtr<globalIndex> globalPoints;
1044 outputDir / cpp.name() +
"-src_" + tmName,
1045 ami.srcWeightsSum(),
1056 if (isA<cyclicACMIPolyPatch>(
pbm[patchi]))
1059 refCast<const cyclicACMIPolyPatch>(
pbm[patchi]);
1062 globalFaces().gather(
pp.mask(), mergedMask);
1064 if (Pstream::master())
1070 (outputDir / cpp.name() +
"-src_" + tmName),
1074 wr.write(
"mask", mergedMask);
1080 const auto& nbrPp = cpp.neighbPatch();
1085 autoPtr<globalIndex> globalFaces;
1086 autoPtr<globalIndex> globalPoints;
1093 / nbrPp.name() +
"-tgt_" + tmName
1095 ami.tgtWeightsSum(),
1098 nbrPp.meshPointMap(),
1106 if (isA<cyclicACMIPolyPatch>(
pbm[patchi]))
1109 refCast<const cyclicACMIPolyPatch>(
pbm[patchi]);
1112 globalFaces().gather
1114 pp.neighbPatch().mask(),
1118 if (Pstream::master())
1126 / nbrPp.name() +
"-tgt_" + tmName
1131 wr.write(
"mask", mergedMask);
1138 else if (isA<mappedPatchBase>(
pbm[patchi]))
1140 const auto&
pp =
pbm[patchi];
1141 const auto& cpp = refCast<const mappedPatchBase>(
pp);
1147 autoPtr<globalIndex> globalFaces;
1148 autoPtr<globalIndex> globalPoints;
1153 outputDir /
pp.name() +
"-src_" + tmName,
1154 ami.srcWeightsSum(),
1165 if (cpp.sameWorld())
1168 const polyPatch& nbrPp = cpp.samplePolyPatch();
1173 autoPtr<globalIndex> globalFaces;
1174 autoPtr<globalIndex> globalPoints;
1180 outputDir / nbrPp.name() +
"-tgt_" + tmName,
1181 ami.tgtWeightsSum(),
1184 nbrPp.meshPointMap(),
1196 return noFailedChecks;
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
const polyBoundaryMesh & pbm
const word & name() const noexcept
Return const reference to name.
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
const volScalarField & p0
const polyBoundaryMesh & patches
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
return returnReduce(nRefine-oldNRefine, sumOp< label >())
List< label > labelList
A List of labels.
label checkGeometry(const polyMesh &mesh, const bool allGeometry, autoPtr< surfaceWriter > &surfWriter, autoPtr< coordSetWriter > &setWriter)
bool checkCoupledPoints(const polyMesh &, const bool report, labelHashSet *)
Check 0th vertex on coupled faces.
messageStream Info
Information stream (stdout output on master, null elsewhere).
List< face > faceList
List of faces.
bool checkWedges(const polyMesh &, const bool report, const Vector< label > &, labelHashSet *)
Check wedge orientation.
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Ostream & endl(Ostream &os)
Add newline and flush stream.
dimensionedScalar sqrt(const dimensionedScalar &ds)
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
void reduce(T &value, BinaryOp bop, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm)
Reduce inplace (cf. MPI Allreduce).
void mergeAndWrite(const polyMesh &mesh, surfaceWriter &writer, const word &name, const indirectPrimitivePatch &setPatch, const fileName &outputDir)
Generate merged surface on master and write. Needs input patch.
AMIInterpolation AMIPatchToPatchInterpolation
Patch-to-patch interpolation == Foam::AMIInterpolation.
errorManip< error > abort(error &err)
vector point
Point is a vector.
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
void collectAndWriteAMIWeights(const polyMesh &mesh, surfaceWriter &wr, const fileName &fName, const scalarField &weights, const faceList &localFaces, const labelList &meshPoints, const Map< label > &meshPointMap, faceList &mergedFaces, pointField &mergedPoints, autoPtr< globalIndex > &globalFaces, autoPtr< globalIndex > &globalPoints)
Collect AMI weights to master and write.
label findOppositeWedge(const polyMesh &, const wedgePolyPatch &)
vectorField pointField
pointField is a vectorField.
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
dimensionedScalar acos(const dimensionedScalar &ds)
constexpr scalar radToDeg(const scalar rad) noexcept
Conversion from radians to degrees.
#define forAll(list, i)
Loop across all elements in list.
#define forAllConstIters(container, iter)
Iterate across all elements of the container object with const access.
Unit conversion functions.