52 Foam::vector Foam::cyclicAMIPolyPatch::findFaceNormalMaxRadius
63 label facei =
findMax(magRadSqr);
66 <<
"Patch: " <<
name() <<
nl
67 <<
" rotFace = " << facei <<
nl
69 <<
" distance = " <<
Foam::sqrt(magRadSqr[facei])
89 <<
" has transform type " << transformTypeNames[
transform()]
90 <<
", neighbour patch " << neighbPatchName()
91 <<
" has transform type "
92 << neighbPatch().transformTypeNames[neighbPatch().transform()]
105 if (rotationAngleDefined_)
107 const tensor T(rotationAxis_*rotationAxis_);
111 0, -rotationAxis_.z(), rotationAxis_.y(),
112 rotationAxis_.z(), 0, -rotationAxis_.x(),
113 -rotationAxis_.y(), rotationAxis_.x(), 0
120 +
sin(rotationAngle_)*S
127 +
sin(-rotationAngle_)*S
132 const vector transformedAreaPos =
gSum(half1Areas & revTPos);
133 const vector transformedAreaNeg =
gSum(half1Areas & revTNeg);
135 const scalar magArea0 =
mag(area0) + ROOTVSMALL;
139 const scalar errorPos =
mag(transformedAreaPos + area0);
140 const scalar errorNeg =
mag(transformedAreaNeg + area0);
142 const scalar normErrorPos = errorPos/magArea0;
143 const scalar normErrorNeg = errorNeg/magArea0;
145 if (errorPos > errorNeg && normErrorNeg < matchTolerance())
148 rotationAngle_ *= -1;
155 const scalar areaError =
min(normErrorPos, normErrorNeg);
157 if (areaError > matchTolerance())
160 <<
"Patch areas are not consistent within "
161 << 100*matchTolerance()
162 <<
" % indicating a possible error in the specified "
163 <<
"angle of rotation" <<
nl
164 <<
" owner patch : " <<
name() <<
nl
165 <<
" neighbour patch : " << neighbPatch().name()
169 <<
" area error : " << 100*areaError <<
" %"
170 <<
" match tolerance : " << matchTolerance()
176 scalar theta =
radToDeg(rotationAngle_);
178 Pout<<
"cyclicAMIPolyPatch::calcTransforms: patch:"
180 <<
" Specified rotation:"
181 <<
" swept angle: " << theta <<
" [deg]"
182 <<
" reverse transform: " << revT
190 if (half0Ctrs.size())
192 n0 = findFaceNormalMaxRadius(half0Ctrs);
194 if (half1Ctrs.size())
196 n1 = -findFaceNormalMaxRadius(half1Ctrs);
199 reduce(n0, maxMagSqrOp<point>());
200 reduce(n1, maxMagSqrOp<point>());
210 (n0 ^ rotationAxis_),
216 (-n1 ^ rotationAxis_),
225 Pout<<
"cyclicAMIPolyPatch::calcTransforms: patch:"
227 <<
" Specified rotation:"
228 <<
" n0:" << n0 <<
" n1:" << n1
229 <<
" swept angle: " << theta <<
" [deg]"
230 <<
" reverse transform: " << revT
246 Pout<<
"cyclicAMIPolyPatch::calcTransforms : patch:" <<
name()
247 <<
" Specified translation : " << separationVector_
267 <<
" Assuming cyclic AMI pairs are colocated" <<
endl;
282 <<
" forwardT = " << forwardT() <<
nl
283 <<
" reverseT = " << reverseT() <<
nl
284 <<
" separation = " << separation() <<
nl
285 <<
" collocated = " << collocated() <<
nl <<
endl;
293 autoPtr<coordSystem::cylindrical> csPtr;
295 const label periodicID = periodicPatchID();
296 if (periodicID != -1)
299 const coupledPolyPatch& perPp
301 refCast<const coupledPolyPatch>
303 boundaryMesh()[periodicID]
306 if (!perPp.parallel())
310 if (isA<cyclicPolyPatch>(perPp))
313 refCast<const cyclicPolyPatch>(perPp).rotationAxis();
315 refCast<const cyclicPolyPatch>(perPp).rotationCentre();
317 else if (isA<cyclicAMIPolyPatch>(perPp))
320 refCast<const cyclicAMIPolyPatch>(perPp).rotationAxis();
322 refCast<const cyclicAMIPolyPatch>(perPp).rotationCentre();
327 <<
" have unsupported periodicPatch " << perPp.name()
331 csPtr.set(
new coordSystem::cylindrical(axisPoint, axis));
343 const word surfType(surfDict_.getOrDefault<
word>(
"type",
"none"));
345 if (!surfPtr_ && owner() && surfType !=
"none")
347 word surfName(surfDict_.getOrDefault(
"name",
name()));
387 const cyclicAMIPolyPatch& nbr = neighbPatch();
393 const Time& t = boundaryMesh().mesh().time();
394 OFstream
os(t.path()/
name() +
"_neighbourPatch-org.obj");
398 label patchSize0 = size();
399 label nbrPatchSize0 = nbr.size();
404 if (srcFaceIDs_.size())
406 patchSize0 = srcFaceIDs_.size();
408 if (tgtFaceIDs_.size())
410 nbrPatchSize0 = tgtFaceIDs_.size();
415 transformPosition(nbrPoints);
418 SubList<face>(nbr.localFaces(), nbrPatchSize0),
423 SubList<face>(localFaces(), patchSize0),
430 const Time& t = boundaryMesh().mesh().time();
431 OFstream osN(t.path()/
name() +
"_neighbourPatch-trans.obj");
434 OFstream osO(t.path()/
name() +
"_ownerPatch.obj");
439 AMIPtr_->upToDate() =
false;
440 AMIPtr_->calculate(patch0, nbrPatch0, surfPtr());
444 AMIPtr_->checkSymmetricWeights(
true);
453 const cyclicAMIPolyPatch& half0 = *
this;
457 half0Areas[facei] = half0[facei].areaNormal(half0.points());
460 const cyclicAMIPolyPatch& half1 = neighbPatch();
464 half1Areas[facei] = half1[facei].areaNormal(half1.points());
477 <<
"calcTransforms() : patch: " <<
name() <<
nl
478 <<
" forwardT = " << forwardT() <<
nl
479 <<
" reverseT = " << reverseT() <<
nl
480 <<
" separation = " << separation() <<
nl
481 <<
" collocated = " << collocated() <<
nl <<
endl;
490 AMIPtr_->upToDate() =
false;
530 restoreScaledGeometry();
536 AMIPtr_->upToDate() =
false;
596 AMIPtr_->upToDate() =
false;
612 const word& patchType,
614 const word& defaultAMIMethod
618 nbrPatchName_(
word::null),
622 rotationCentre_(
Zero),
623 rotationAngleDefined_(false),
625 separationVector_(
Zero),
626 periodicPatchName_(
word::null),
627 periodicPatchID_(-1),
631 createAMIFaces_(false),
632 moveFaceCentres_(false),
650 const word& patchType,
651 const word& defaultAMIMethod
655 nbrPatchName_(
dict.getOrDefault<
word>(
"neighbourPatch",
word::null)),
658 fraction_(
dict.getOrDefault<scalar>(
"fraction",
Zero)),
660 rotationCentre_(
Zero),
661 rotationAngleDefined_(false),
663 separationVector_(
Zero),
664 periodicPatchName_(
dict.getOrDefault<
word>(
"periodicPatch",
word::null)),
665 periodicPatchID_(-1),
670 dict.getOrDefault<
word>(
"AMIMethod", defaultAMIMethod),
672 dict.getOrDefault(
"flipNormals", false)
675 surfDict_(
dict.subOrEmptyDict(
"surface")),
677 createAMIFaces_(
dict.getOrDefault(
"createAMIFaces", false)),
678 moveFaceCentres_(false),
688 <<
"No \"neighbourPatch\" or \"coupleGroup\" provided."
696 <<
" cannot be the same as this patch " <<
name
723 <<
"Please supply a non-zero vector."
757 const cyclicAMIPolyPatch& pp,
758 const polyBoundaryMesh& bm
761 coupledPolyPatch(pp, bm),
762 nbrPatchName_(pp.nbrPatchName_),
763 coupleGroup_(pp.coupleGroup_),
765 fraction_(pp.fraction_),
766 rotationAxis_(pp.rotationAxis_),
767 rotationCentre_(pp.rotationCentre_),
768 rotationAngleDefined_(pp.rotationAngleDefined_),
769 rotationAngle_(pp.rotationAngle_),
770 separationVector_(pp.separationVector_),
771 periodicPatchName_(pp.periodicPatchName_),
772 periodicPatchID_(-1),
773 AMIPtr_(pp.AMIPtr_->clone()),
774 surfDict_(pp.surfDict_),
776 createAMIFaces_(pp.createAMIFaces_),
777 moveFaceCentres_(pp.moveFaceCentres_),
795 const label newStart,
796 const word& nbrPatchName
800 nbrPatchName_(nbrPatchName),
801 coupleGroup_(pp.coupleGroup_),
803 fraction_(pp.fraction_),
804 rotationAxis_(pp.rotationAxis_),
805 rotationCentre_(pp.rotationCentre_),
806 rotationAngleDefined_(pp.rotationAngleDefined_),
807 rotationAngle_(pp.rotationAngle_),
808 separationVector_(pp.separationVector_),
809 periodicPatchName_(pp.periodicPatchName_),
810 periodicPatchID_(-1),
811 AMIPtr_(pp.AMIPtr_->clone()),
812 surfDict_(pp.surfDict_),
814 createAMIFaces_(pp.createAMIFaces_),
815 moveFaceCentres_(pp.moveFaceCentres_),
826 <<
" cannot be the same as this patch " <<
name()
845 nbrPatchName_(pp.nbrPatchName_),
846 coupleGroup_(pp.coupleGroup_),
848 fraction_(pp.fraction_),
849 rotationAxis_(pp.rotationAxis_),
850 rotationCentre_(pp.rotationCentre_),
851 rotationAngleDefined_(pp.rotationAngleDefined_),
852 rotationAngle_(pp.rotationAngle_),
853 separationVector_(pp.separationVector_),
854 periodicPatchName_(pp.periodicPatchName_),
855 periodicPatchID_(-1),
856 AMIPtr_(pp.AMIPtr_->clone()),
857 surfDict_(pp.surfDict_),
859 createAMIFaces_(pp.createAMIFaces_),
860 moveFaceCentres_(pp.moveFaceCentres_),
879 forAll (addSourceFaces, faceI)
881 const labelList& nbrFaceIs = addSourceFaces[faceI];
885 label nbrFaceI = nbrFaceIs[j];
887 if (nbrFaceI < neighbPatch().size())
904 if (nbrPatchID_ == -1)
906 nbrPatchID_ = this->boundaryMesh().findPatchID(neighbPatchName());
908 if (nbrPatchID_ == -1)
911 <<
"Illegal neighbourPatch name " << neighbPatchName()
912 <<
nl <<
"Valid patch names are "
913 << this->boundaryMesh().names()
918 const cyclicAMIPolyPatch& nbrPatch =
919 refCast<const cyclicAMIPolyPatch>
921 this->boundaryMesh()[nbrPatchID_]
924 if (nbrPatch.neighbPatchName() !=
name())
927 <<
"Patch " <<
name()
928 <<
" specifies neighbour patch " << neighbPatchName()
929 <<
nl <<
" but that in return specifies "
930 << nbrPatch.neighbPatchName() <<
endl;
946 if (periodicPatchID_ == -1)
948 periodicPatchID_ = boundaryMesh().findPatchID(periodicPatchName_);
950 if (periodicPatchID_ == -1)
953 <<
"Illegal neighbourPatch name " << periodicPatchName_
954 <<
nl <<
"Valid patch names are "
955 << this->boundaryMesh().names()
959 return periodicPatchID_;
966 return index() < neighbPatchID();
973 return refCast<const cyclicAMIPolyPatch>(pp);
982 <<
"AMI interpolator only available to owner patch"
986 if (!AMIPtr_->upToDate())
999 return AMI().applyLowWeightCorrection();
1003 return neighbPatch().AMI().applyLowWeightCorrection();
1022 else if (separated())
1053 forwardT().size() == 1
1067 else if (separated())
1071 separation().size() == 1
1073 : separation()[facei]
1091 reverseT().size() == 1
1105 else if (separated())
1109 separation().size() == 1
1111 : separation()[facei]
1129 reverseT().size() == 1
1186 reverseTransformPosition(prt, facei);
1189 reverseTransformDirection(nrt, facei);
1191 label nbrFacei = -1;
1195 nbrFacei = AMI().tgtPointFace
1206 nbrFacei = neighbPatch().AMI().srcPointFace
1228 if (!nbrPatchName_.empty())
1241 if (rotationAngleDefined_)
1270 if (!surfDict_.empty())
1272 surfDict_.writeEntry(surfDict_.dictName(),
os);
1275 if (createAMIFaces_)