55 Foam::label Foam::cyclicPolyPatch::findMaxArea
62 scalar maxAreaSqr = -GREAT;
66 scalar areaSqr =
magSqr(faces[facei].areaNormal(
points));
68 if (maxAreaSqr < areaSqr)
83 const cyclicPolyPatch& half0 = *
this;
87 half0Areas[facei] = half0[facei].areaNormal(half0.points());
91 const cyclicPolyPatch& half1 = neighbPatch();
95 half1Areas[facei] = half1[facei].areaNormal(half1.points());
119 if (
debug && owner())
121 fileName casePath(boundaryMesh().
mesh().time().
path());
123 fileName nm0(casePath/
name()+
"_faces.obj");
124 Pout<<
"cyclicPolyPatch::calcTransforms : Writing " <<
name()
125 <<
" faces to OBJ file " << nm0 <<
endl;
126 writeOBJ(nm0, half0, half0.points());
128 const cyclicPolyPatch& half1 = neighbPatch();
130 fileName nm1(casePath/half1.name()+
"_faces.obj");
131 Pout<<
"cyclicPolyPatch::calcTransforms : Writing " << half1.
name()
132 <<
" faces to OBJ file " << nm1 <<
endl;
133 writeOBJ(nm1, half1, half1.points());
136 OFstream str(casePath/
name()+
"_to_" + half1.name() +
".obj");
138 Pout<<
"cyclicPolyPatch::calcTransforms :"
139 <<
" Writing coupled face centres as lines to " << str.
name()
143 const point&
p0 = half0Ctrs[i];
144 str <<
"v " <<
p0.x() <<
' ' <<
p0.y() <<
' ' <<
p0.z() <<
nl;
146 const point& p1 = half1Ctrs[i];
147 str <<
"v " << p1.
x() <<
' ' << p1.y() <<
' ' << p1.z() <<
nl;
149 str <<
"l " << vertI-1 <<
' ' << vertI <<
nl;
157 if (half0Ctrs.size() != half1Ctrs.size())
160 <<
"For patch " <<
name()
161 <<
" there are " << half0Ctrs.size()
162 <<
" face centres, for the neighbour patch " << neighbPatch().name()
163 <<
" there are " << half1Ctrs.size()
170 <<
"Patch " <<
name()
171 <<
" has transform type " << transformTypeNames[
transform()]
172 <<
", neighbour patch " << neighbPatchName()
173 <<
" has transform type "
174 << neighbPatch().transformTypeNames[neighbPatch().transform()]
181 if (half0Ctrs.size() > 0)
186 scalar maxAreaDiff = -GREAT;
187 label maxAreaFacei = -1;
191 scalar magSf =
mag(half0Areas[facei]);
192 scalar nbrMagSf =
mag(half1Areas[facei]);
193 scalar avSf = (magSf + nbrMagSf)/2.0;
195 if (magSf < ROOTVSMALL && nbrMagSf < ROOTVSMALL)
200 half0Normals[facei] =
point(1, 0, 0);
201 half1Normals[facei] = half0Normals[facei];
205 scalar areaDiff =
mag(magSf - nbrMagSf)/avSf;
207 if (areaDiff > maxAreaDiff)
209 maxAreaDiff = areaDiff;
210 maxAreaFacei = facei;
213 if (areaDiff > matchTolerance())
217 <<
" area does not match neighbour by "
219 <<
"% -- possible face ordering problem." <<
endl
220 <<
"patch:" <<
name()
221 <<
" my area:" << magSf
222 <<
" neighbour area:" << nbrMagSf
223 <<
" matching tolerance:" << matchTolerance()
225 <<
"Mesh face:" << start()+facei
226 <<
" fc:" << half0Ctrs[facei]
228 <<
"Neighbour fc:" << half1Ctrs[facei]
230 <<
"If you are certain your matching is correct"
231 <<
" you can increase the 'matchTolerance' setting"
232 <<
" in the patch dictionary in the boundary file."
234 <<
"Rerun with cyclic debug flag set"
239 half0Normals[facei] = half0Areas[facei] / magSf;
240 half1Normals[facei] = half1Areas[facei] / nbrMagSf;
249 Pout<<
"cyclicPolyPatch::calcTransforms :"
250 <<
" patch:" <<
name()
251 <<
" Max area error:" << 100*maxAreaDiff <<
"% at face:"
252 << maxAreaFacei <<
" at:" << half0Ctrs[maxAreaFacei]
253 <<
" coupled face at:" << half1Ctrs[maxAreaFacei]
264 vector n0 = findFaceMaxRadius(half0Ctrs);
265 vector n1 = -findFaceMaxRadius(half1Ctrs);
271 Pout<<
"cyclicPolyPatch::calcTransforms :"
272 <<
" patch:" <<
name()
273 <<
" Specified rotation :"
274 <<
" n0:" << n0 <<
" n1:" << n1
284 (n0 ^ rotationAxis_),
290 (-n1 ^ rotationAxis_),
293 const tensor revT(E1.T() & E0);
329 Pout<<
"cyclicPolyPatch::calcTransforms :"
330 <<
" patch:" <<
name()
331 <<
" Specified separation vector : "
332 << separationVector_ <<
endl;
336 const scalar avgTol =
average(half0Tols);
339 mag(separationVector_ + neighbPatch().separationVector_)
344 <<
"Specified separation vector " << separationVector_
345 <<
" differs by that of neighbouring patch "
346 << neighbPatch().separationVector_
347 <<
" by more than tolerance " << avgTol <<
endl
348 <<
"patch:" <<
name()
349 <<
" neighbour:" << neighbPatchName()
357 separation().size() != 1
358 ||
mag(separation()[0] - separationVector_) > avgTol
362 <<
"Specified separationVector " << separationVector_
363 <<
" differs from computed separation vector "
364 << separation() <<
endl
365 <<
"This probably means your geometry is not consistent"
366 <<
" with the specified separation and might lead"
367 <<
" to problems." <<
endl
368 <<
"Continuing with specified separation vector "
369 << separationVector_ <<
endl
370 <<
"patch:" <<
name()
371 <<
" neighbour:" << neighbPatchName()
390 void Foam::cyclicPolyPatch::getCentresAndAnchors
402 half0Ctrs = pp0.faceCentres();
403 anchors0 = getAnchorPoints(pp0, pp0.points(),
transform());
404 half1Ctrs = pp1.faceCentres();
408 Pout<<
"cyclicPolyPatch::getCentresAndAnchors :"
409 <<
" patch:" <<
name() <<
nl
410 <<
"half0 untransformed faceCentres (avg) : "
412 <<
"half1 untransformed faceCentres (avg) : "
416 if (half0Ctrs.size())
422 vector n0 = findFaceMaxRadius(half0Ctrs);
423 vector n1 = -findFaceMaxRadius(half1Ctrs);
429 Pout<<
"cyclicPolyPatch::getCentresAndAnchors :"
430 <<
" patch:" <<
name()
431 <<
" Specified rotation :"
432 <<
" n0:" << n0 <<
" n1:" << n1
443 (n0 ^ rotationAxis_),
449 (-n1 ^ rotationAxis_),
452 const tensor revT(E1.T() & E0);
461 half0Ctrs[facei] - rotationCentre_
468 anchors0[facei] - rotationCentre_
481 Pout<<
"cyclicPolyPatch::getCentresAndAnchors :"
482 <<
" patch:" <<
name()
483 <<
"Specified translation : " << separationVector_
490 half0Ctrs -= separationVector_;
491 anchors0 -= separationVector_;
501 label max0I = findMaxArea(pp0.points(), pp0);
502 const vector n0 = pp0[max0I].unitNormal(pp0.points());
504 label max1I = findMaxArea(pp1.points(), pp1);
505 const vector n1 = pp1[max1I].unitNormal(pp1.points());
507 if (
mag(n0 & n1) < 1-matchTolerance())
511 Pout<<
"cyclicPolyPatch::getCentresAndAnchors :"
512 <<
" patch:" <<
name()
513 <<
" Detected rotation :"
514 <<
" n0:" << n0 <<
" n1:" << n1 <<
endl;
539 const point ctr0(
sum(pp0.localPoints())/pp0.nPoints());
540 const point ctr1(
sum(pp1.localPoints())/pp1.nPoints());
544 Pout<<
"cyclicPolyPatch::getCentresAndAnchors :"
545 <<
" patch:" <<
name()
546 <<
" Detected translation :"
547 <<
" n0:" << n0 <<
" n1:" << n1
548 <<
" ctr0:" << ctr0 <<
" ctr1:" << ctr1 <<
endl;
551 half0Ctrs += ctr1 - ctr0;
552 anchors0 += ctr1 - ctr0;
560 tols = matchTolerance()*calcFaceTol(pp1, pp1.points(), half1Ctrs);
571 const vectorField n((faceCentres - rotationCentre_) ^ rotationAxis_);
575 label facei =
findMax(magRadSqr);
579 Info<<
"findFaceMaxRadius(const pointField&) : patch: " <<
name() <<
nl
580 <<
" rotFace = " << facei <<
nl
581 <<
" point = " << faceCentres[facei] <<
nl
582 <<
" distance = " <<
Foam::sqrt(magRadSqr[facei])
599 const word& patchType,
604 neighbPatchName_(
word::null),
607 rotationCentre_(
Zero),
608 separationVector_(
Zero),
609 coupledPointsPtr_(nullptr),
610 coupledEdgesPtr_(nullptr)
624 const word& neighbPatchName,
626 const vector& rotationAxis,
627 const point& rotationCentre,
628 const vector& separationVector
632 neighbPatchName_(neighbPatchName),
634 rotationAxis_(rotationAxis),
635 rotationCentre_(rotationCentre),
636 separationVector_(separationVector),
637 coupledPointsPtr_(nullptr),
638 coupledEdgesPtr_(nullptr)
651 const word& patchType
655 neighbPatchName_(
dict.getOrDefault(
"neighbourPatch",
word::null)),
659 rotationCentre_(
Zero),
660 separationVector_(
Zero),
661 coupledPointsPtr_(nullptr),
662 coupledEdgesPtr_(nullptr)
667 <<
"No \"neighbourPatch\" provided." <<
endl
668 <<
"Is your mesh uptodate with split cyclics?" <<
endl
669 <<
"Run foamUpgradeCyclics to convert mesh and fields"
673 if (neighbPatchName_ ==
name)
676 <<
"Neighbour patch name " << neighbPatchName_
677 <<
" cannot be the same as this patch " <<
name
685 dict.readEntry(
"rotationAxis", rotationAxis_);
686 dict.readEntry(
"rotationCentre", rotationCentre_);
688 scalar magRot =
mag(rotationAxis_);
692 <<
"Illegal rotationAxis " << rotationAxis_ <<
endl
693 <<
"Please supply a non-zero vector."
696 rotationAxis_ /= magRot;
702 dict.readEntry(
"separationVector", separationVector_);
723 neighbPatchName_(pp.neighbPatchName_),
724 coupleGroup_(pp.coupleGroup_),
726 rotationAxis_(pp.rotationAxis_),
727 rotationCentre_(pp.rotationCentre_),
728 separationVector_(pp.separationVector_),
729 coupledPointsPtr_(nullptr),
730 coupledEdgesPtr_(nullptr)
740 const label nrbPatchID,
745 neighbPatchName_(pp.neighbPatchName_),
746 coupleGroup_(pp.coupleGroup_),
747 neighbPatchID_(nrbPatchID),
748 rotationAxis_(pp.rotationAxis_),
749 rotationCentre_(pp.rotationCentre_),
750 separationVector_(pp.separationVector_),
751 coupledPointsPtr_(nullptr),
752 coupledEdgesPtr_(nullptr)
765 const label newStart,
766 const word& neighbName
770 neighbPatchName_(neighbName),
771 coupleGroup_(pp.coupleGroup_),
773 rotationAxis_(pp.rotationAxis_),
774 rotationCentre_(pp.rotationCentre_),
775 separationVector_(pp.separationVector_),
776 coupledPointsPtr_(nullptr),
777 coupledEdgesPtr_(nullptr)
779 if (neighbName ==
name())
782 <<
"Neighbour patch name " << neighbName
783 <<
" cannot be the same as this patch " <<
name()
802 neighbPatchName_(pp.neighbPatchName_),
803 coupleGroup_(pp.coupleGroup_),
805 rotationAxis_(pp.rotationAxis_),
806 rotationCentre_(pp.rotationCentre_),
807 separationVector_(pp.separationVector_),
808 coupledPointsPtr_(nullptr),
809 coupledEdgesPtr_(nullptr)
826 if (neighbPatchName_.empty())
829 label
patchID = coupleGroup_.findOtherPatchID(*
this);
833 return neighbPatchName_;
839 if (neighbPatchID_ == -1)
841 neighbPatchID_ = this->boundaryMesh().findPatchID(neighbPatchName());
843 if (neighbPatchID_ == -1)
846 <<
"Illegal neighbourPatch name " << neighbPatchName()
847 <<
endl <<
"Valid patch names are "
848 << this->boundaryMesh().names()
853 const cyclicPolyPatch& nbrPatch = refCast<const cyclicPolyPatch>
855 this->boundaryMesh()[neighbPatchID_]
858 if (nbrPatch.neighbPatchName() !=
name())
861 <<
"Patch " <<
name()
862 <<
" specifies neighbour patch " << neighbPatchName()
863 <<
endl <<
" but that in return specifies "
864 << nbrPatch.neighbPatchName()
868 return neighbPatchID_;
887 else if (separated())
914 forwardT().size() == 1
928 else if (separated())
932 separation().size() == 1
934 : separation()[facei]
988 neighbPatch().faceCentres(),
989 neighbPatch().faceAreas(),
990 neighbPatch().faceCellCentres()
1032 if (!coupledPointsPtr_)
1034 const faceList& nbrLocalFaces = neighbPatch().localFaces();
1035 const labelList& nbrMeshPoints = neighbPatch().meshPoints();
1044 forAll(*
this, patchFacei)
1046 const face& fA = localFaces()[patchFacei];
1047 const face& fB = nbrLocalFaces[patchFacei];
1051 label patchPointA = fA[indexA];
1053 if (coupledPoint[patchPointA] == -1)
1055 label indexB = (fB.size() - indexA) % fB.size();
1058 if (meshPoints()[patchPointA] != nbrMeshPoints[fB[indexB]])
1060 coupledPoint[patchPointA] = fB[indexB];
1067 edgeList& connected = *coupledPointsPtr_;
1070 label connectedI = 0;
1074 if (coupledPoint[i] != -1)
1076 connected[connectedI++] = edge(i, coupledPoint[i]);
1080 connected.setSize(connectedI);
1086 boundaryMesh().
mesh().time().
path()
1087 /
name() +
"_coupledPoints.obj"
1091 Pout<<
"Writing file " << str.
name() <<
" with coordinates of "
1092 <<
"coupled points" <<
endl;
1096 const point& a =
points()[meshPoints()[connected[i][0]]];
1097 const point&
b =
points()[nbrMeshPoints[connected[i][1]]];
1099 str<<
"v " << a.x() <<
' ' << a.y() <<
' ' << a.z() <<
nl;
1100 str<<
"v " <<
b.x() <<
' ' <<
b.y() <<
' ' <<
b.z() <<
nl;
1103 str<<
"l " << vertI-1 <<
' ' << vertI <<
nl;
1107 return *coupledPointsPtr_;
1113 if (!coupledEdgesPtr_)
1115 const edgeList& pointCouples = coupledPoints();
1118 Map<label> aToB(2*pointCouples.size());
1120 for (
const edge&
e : pointCouples)
1122 aToB.insert(
e[0],
e[1]);
1126 EdgeMap<label> edgeMap(nEdges());
1128 forAll(*
this, patchFacei)
1130 const labelList& fEdges = faceEdges()[patchFacei];
1132 for (
const label edgeI : fEdges)
1134 const edge&
e = edges()[edgeI];
1137 const auto fnd0 = aToB.cfind(
e[0]);
1140 const auto fnd1 = aToB.cfind(
e[1]);
1143 edgeMap.insert(edge(fnd0(), fnd1()), edgeI);
1151 const cyclicPolyPatch& neighbPatch = this->neighbPatch();
1152 const labelList& nbrMp = neighbPatch.meshPoints();
1156 coupledEdgesPtr_ =
new edgeList(edgeMap.size());
1157 edgeList& coupledEdges = *coupledEdgesPtr_;
1160 forAll(neighbPatch, patchFacei)
1162 const labelList& fEdges = neighbPatch.faceEdges()[patchFacei];
1164 for (
const label edgeI : fEdges)
1166 const edge&
e = neighbPatch.edges()[edgeI];
1169 auto iter = edgeMap.find(
e);
1173 const label edgeA = iter.val();
1174 const edge& eA = edges()[edgeA];
1179 edge(
mp[eA[0]],
mp[eA[1]])
1180 != edge(nbrMp[
e[0]], nbrMp[
e[1]])
1183 coupledEdges[coupleI++] = edge(edgeA, edgeI);
1187 edgeMap.erase(iter);
1191 coupledEdges.setSize(coupleI);
1198 const edge&
e = coupledEdges[i];
1200 if (
e[0] < 0 ||
e[1] < 0)
1203 <<
"Problem : at position " << i
1204 <<
" illegal couple:" <<
e
1213 boundaryMesh().
mesh().time().
path()
1214 /
name() +
"_coupledEdges.obj"
1218 Pout<<
"Writing file " << str.
name() <<
" with centres of "
1219 <<
"coupled edges" <<
endl;
1221 for (
const edge&
e : coupledEdges)
1224 const point&
b = neighbPatch.edges()[
e[1]].centre
1226 neighbPatch.localPoints()
1229 str<<
"v " << a.x() <<
' ' << a.y() <<
' ' << a.z() <<
nl;
1230 str<<
"v " <<
b.x() <<
' ' <<
b.y() <<
' ' <<
b.z() <<
nl;
1233 str<<
"l " << vertI-1 <<
' ' << vertI <<
nl;
1237 return *coupledEdgesPtr_;
1251 ownerPatchPtr_.reset
1265 PstreamBuffers& pBufs,
1273 Pout<<
"order : of " << pp.size()
1274 <<
" faces of patch:" <<
name()
1275 <<
" neighbour:" << neighbPatchName()
1281 rotation.setSize(pp.size());
1296 faceMap[patchFacei] = patchFacei;
1309 getCentresAndAnchors
1322 Pout<<
"half0 transformed faceCentres (avg) : "
1324 <<
"half1 untransformed faceCentres (avg) : "
1338 if (!matchedAll ||
debug)
1343 boundaryMesh().
mesh().time().
path()
1344 /neighbPatch().
name()+
"_faces.obj"
1346 Pout<<
"cyclicPolyPatch::order : Writing neighbour"
1347 <<
" faces to OBJ file " << nm0 <<
endl;
1352 boundaryMesh().
mesh().time().
path()
1353 /
name()+
"_faces.obj"
1355 Pout<<
"cyclicPolyPatch::order : Writing my"
1356 <<
" faces to OBJ file " << nm1 <<
endl;
1361 boundaryMesh().
mesh().time().
path()
1362 /
name() +
"_faceCentres.obj"
1364 Pout<<
"cyclicPolyPatch::order : "
1365 <<
"Dumping currently found cyclic match as lines between"
1366 <<
" corresponding face centres to file " << ccStr.
name()
1380 const point&
c1 = half1Ctrs[i];
1389 <<
"Patch:" <<
name() <<
" : "
1390 <<
"Cannot match vectors to faces on both sides of patch"
1392 <<
" Perhaps your faces do not match?"
1393 <<
" The obj files written contain the current match." <<
endl
1394 <<
" Continuing with incorrect face ordering from now on!"
1408 label newFacei =
faceMap[oldFacei];
1410 const point& wantedAnchor = anchors0[newFacei];
1412 rotation[newFacei] = getRotation
1420 if (rotation[newFacei] == -1)
1423 <<
"in patch " <<
name()
1425 <<
"Cannot find point on face " << pp[oldFacei]
1426 <<
" with vertices "
1427 << UIndirectList<point>(pp.points(), pp[oldFacei])
1428 <<
" that matches point " << wantedAnchor
1429 <<
" when matching the halves of processor patch " <<
name()
1430 <<
"Continuing with incorrect face ordering from now on!"
1437 ownerPatchPtr_.clear();
1443 if (
faceMap[facei] != facei || rotation[facei] != 0)
1457 if (!neighbPatchName_.empty())