44 Foam::vector Foam::cyclicAMIPolyPatch::findFaceNormalMaxRadius
51 const vectorField n((faceCentres - rotationCentre_) ^ rotationAxis_);
59 Info<<
"findFaceMaxRadius(const pointField&) : patch: " <<
name() <<
nl 60 <<
" rotFace = " << facei <<
nl 61 <<
" point = " << faceCentres[facei] <<
nl 62 <<
" distance = " <<
Foam::sqrt(magRadSqr[facei])
83 <<
" has transform type " << transformTypeNames[
transform()]
84 <<
", neighbour patch " << neighbPatchName()
85 <<
" has transform type " 86 << neighbPatch().transformTypeNames[neighbPatch().transform()]
99 if (rotationAngleDefined_)
101 const tensor T(rotationAxis_*rotationAxis_);
105 0, -rotationAxis_.z(), rotationAxis_.y(),
106 rotationAxis_.z(), 0, -rotationAxis_.x(),
107 -rotationAxis_.y(), rotationAxis_.x(), 0
114 +
sin(rotationAngle_)*S
121 +
sin(-rotationAngle_)*S
126 const vector transformedAreaPos =
gSum(half1Areas & revTPos);
127 const vector transformedAreaNeg =
gSum(half1Areas & revTNeg);
129 const scalar magArea0 =
mag(area0) + ROOTVSMALL;
133 const scalar errorPos =
mag(transformedAreaPos + area0);
134 const scalar errorNeg =
mag(transformedAreaNeg + area0);
136 const scalar normErrorPos = errorPos/magArea0;
137 const scalar normErrorNeg = errorNeg/magArea0;
139 if (errorPos > errorNeg && normErrorNeg < matchTolerance())
142 rotationAngle_ *= -1;
149 const scalar areaError =
min(normErrorPos, normErrorNeg);
151 if (areaError > matchTolerance())
154 <<
"Patch areas are not consistent within " 155 << 100*matchTolerance()
156 <<
" % indicating a possible error in the specified " 157 <<
"angle of rotation" <<
nl 158 <<
" owner patch : " <<
name() <<
nl 159 <<
" neighbour patch : " << neighbPatch().name()
163 <<
" area error : " << 100*areaError <<
" %" 164 <<
" match tolerance : " << matchTolerance()
170 scalar theta =
radToDeg(rotationAngle_);
172 Pout<<
"cyclicAMIPolyPatch::calcTransforms: patch:" 174 <<
" Specified rotation:" 175 <<
" swept angle: " << theta <<
" [deg]" 176 <<
" reverse transform: " << revT
184 if (half0Ctrs.size())
186 n0 = findFaceNormalMaxRadius(half0Ctrs);
188 if (half1Ctrs.size())
190 n1 = -findFaceNormalMaxRadius(half1Ctrs);
193 reduce(n0, maxMagSqrOp<point>());
194 reduce(n1, maxMagSqrOp<point>());
196 n0 /=
mag(n0) + VSMALL;
197 n1 /=
mag(n1) + VSMALL;
204 (n0 ^ rotationAxis_),
210 (-n1 ^ rotationAxis_),
219 Pout<<
"cyclicAMIPolyPatch::calcTransforms: patch:" 221 <<
" Specified rotation:" 222 <<
" n0:" << n0 <<
" n1:" << n1
223 <<
" swept angle: " << theta <<
" [deg]" 224 <<
" reverse transform: " << revT
240 Pout<<
"cyclicAMIPolyPatch::calcTransforms : patch:" <<
name()
241 <<
" Specified translation : " << separationVector_
261 <<
" Assuming cyclic AMI pairs are colocated" <<
endl;
276 <<
" forwardT = " << forwardT() <<
nl 277 <<
" reverseT = " << reverseT() <<
nl 278 <<
" separation = " << separation() <<
nl 279 <<
" collocated = " << collocated() <<
nl <<
endl;
299 neighbPatch().meshPoints()
310 transformPosition(nbrPoints);
342 AMILowWeightCorrection_,
349 Pout<<
"cyclicAMIPolyPatch : " <<
name()
350 <<
" constructed AMI with " <<
nl 351 <<
" " <<
"srcAddress:" << AMIPtr_().srcAddress().size()
353 <<
" " <<
"tgAddress :" << AMIPtr_().tgtAddress().size()
366 half0Areas[facei] = half0[facei].normal(half0.
points());
373 half1Areas[facei] = half1[facei].normal(half1.
points());
387 Pout<<
"calcTransforms() : patch: " <<
name() <<
nl 388 <<
" forwardT = " << forwardT() <<
nl 389 <<
" reverseT = " << reverseT() <<
nl 390 <<
" separation = " << separation() <<
nl 391 <<
" collocated = " << collocated() <<
nl <<
endl;
413 neighbPatch().faceCentres(),
414 neighbPatch().faceAreas(),
415 neighbPatch().faceCellCentres()
479 const word& patchType,
488 rotationAngleDefined_(
false),
490 separationVector_(
Zero),
493 AMIRequireMatch_(
true),
494 AMILowWeightCorrection_(-1.0),
509 const word& patchType
518 rotationAngleDefined_(
false),
520 separationVector_(
Zero),
523 AMIRequireMatch_(
true),
524 AMILowWeightCorrection_(dict.
lookupOrDefault(
"lowWeightCorrection", -1.0)),
533 ) <<
"No \"neighbourPatch\" or \"coupleGroup\" provided." 537 if (nbrPatchName_ == name)
542 ) <<
"Neighbour patch name " << nbrPatchName_
543 <<
" cannot be the same as this patch " << name
551 dict.
lookup(
"rotationAxis") >> rotationAxis_;
552 dict.
lookup(
"rotationCentre") >> rotationCentre_;
555 rotationAngleDefined_ =
true;
556 rotationAngle_ =
degToRad(rotationAngle_);
560 Info<<
"rotationAngle: " << rotationAngle_ <<
" [rad]" 565 scalar magRot =
mag(rotationAxis_);
571 ) <<
"Illegal rotationAxis " << rotationAxis_ <<
endl 572 <<
"Please supply a non-zero vector." 575 rotationAxis_ /= magRot;
581 dict.
lookup(
"separationVector") >> separationVector_;
628 const label newStart,
629 const word& nbrPatchName
633 nbrPatchName_(nbrPatchName),
648 if (nbrPatchName_ ==
name())
651 <<
"Neighbour patch name " << nbrPatchName_
652 <<
" cannot be the same as this patch " <<
name()
698 if (nbrPatchID_ == -1)
700 nbrPatchID_ = this->
boundaryMesh().findPatchID(neighbPatchName());
702 if (nbrPatchID_ == -1)
705 <<
"Illegal neighbourPatch name " << neighbPatchName()
706 <<
nl <<
"Valid patch names are " 713 refCast<const cyclicAMIPolyPatch>
721 <<
"Patch " <<
name()
722 <<
" specifies neighbour patch " << neighbPatchName()
723 <<
nl <<
" but that in return specifies " 734 return index() < neighbPatchID();
741 return refCast<const cyclicAMIPolyPatch>(pp);
748 const word surfType(surfDict_.lookupOrDefault<
word>(
"type",
"none"));
750 if (!surfPtr_.valid() && owner() && surfType !=
"none")
752 word surfName(surfDict_.lookupOrDefault(
"name", name()));
763 mesh.time().constant(),
782 <<
"AMI interpolator only available to owner patch" 786 if (!AMIPtr_.valid())
799 return AMI().applyLowWeightCorrection();
803 return neighbPatch().AMI().applyLowWeightCorrection();
822 else if (separated())
853 forwardT().size() == 1
867 else if (separated())
871 separation().size() == 1
873 : separation()[facei]
891 reverseT().size() == 1
905 else if (separated())
909 separation().size() == 1
911 : separation()[facei]
929 reverseT().size() == 1
995 reverseTransformPosition(prt, facei);
998 reverseTransformDirection(nrt, facei);
1000 label nbrFacei = -1;
1004 nbrFacei = AMI().tgtPointFace
1015 nbrFacei = neighbPatch().AMI().srcPointFace
1037 if (!nbrPatchName_.empty())
1042 coupleGroup_.write(os);
1053 if (rotationAngleDefined_)
1063 os.
writeKeyword(
"separationVector") << separationVector_
1083 if (AMILowWeightCorrection_ > 0)
1085 os.
writeKeyword(
"lowWeightCorrection") << AMILowWeightCorrection_
1089 if (!surfDict_.empty())
virtual void clearGeom()
Clear geometry.
static bool valid(char)
Is this character valid for a word.
vector separationVector_
Translation vector.
dimensionedScalar acos(const dimensionedScalar &ds)
#define forAll(list, i)
Loop across all elements in list.
const AMIPatchToPatchInterpolation & AMI() const
Return a reference to the AMI interpolator.
fileName path() const
Return path.
virtual label neighbPatchID() const
Neighbour patch ID.
virtual void movePoints(const Field< PointType > &)
Correct patch after moving points.
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
virtual bool order(PstreamBuffers &, const primitivePatch &, labelList &faceMap, labelList &rotation) const
Return new ordering for primitivePatch.
scalar radToDeg(const scalar rad)
Conversion from radians to degrees.
A class for handling file names.
bool AMIRequireMatch_
Flag to indicate that patches should match/overlap.
errorManipArg< error, int > exit(error &err, const int errNo=1)
virtual void initUpdateMesh(PstreamBuffers &)
Initialise the update of the patch topology.
virtual void initGeometry(PstreamBuffers &)
Initialise the calculation of the patch geometry.
A list of keyword definitions, which are a keyword followed by any number of values (e...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
virtual void initUpdateMesh(PstreamBuffers &)
Initialise the update of the patch topology.
virtual void write(Ostream &) const
Write the polyPatch data as a dictionary.
void size(const label)
Override size to be inconsistent with allocated storage.
virtual void calcTransforms()
Recalculate the transformation tensors.
Addressing for all faces on surface of mesh. Can either be read from polyMesh or from triSurface...
dimensionedScalar sqrt(const dimensionedScalar &ds)
Ostream & endl(Ostream &os)
Add newline and flush stream.
virtual void transformPosition(pointField &) const
Transform patch-based positions from nbr side to this side.
bool applyLowWeightCorrection() const
Return true if applying the low weight correction.
The coupledPolyPatch is an abstract base class for patches that couple regions of the computational d...
vector rotationAxis_
Axis of rotation for rotational cyclics.
bool rotationAngleDefined_
Flag to show whether the rotation angle is defined.
virtual void reverseTransformDirection(vector &d, const label facei) const
Transform a patch-based direction from this side to nbr side.
Vector< scalar > vector
A scalar version of the templated Vector.
virtual void initMovePoints(PstreamBuffers &, const pointField &)
Initialise the patches for moving points.
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Macros for easy insertion into run-time selection tables.
scalar degToRad(const scalar deg)
Conversion from degrees to radians.
virtual void clearGeom()
Clear geometry.
interpolationMethod
Enumeration specifying interpolation method.
virtual void movePoints(PstreamBuffers &, const pointField &p)
Correct patches after moving points.
const dictionary surfDict_
Dictionary used during projection surface construction.
virtual void calcGeometry(PstreamBuffers &)
Calculate the patch geometry.
List< bool > boolList
Bool container classes.
const List< Face > & localFaces() const
Return patch faces addressing into local point list.
points setSize(newPointi)
const coupleGroupIdentifier coupleGroup_
Optional patchGroup to find neighbPatch.
A list of faces which address into the list of points.
A List obtained as a section of another List.
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))
vectorField pointField
pointField is a vectorField.
cyclicAMIPolyPatch(const word &name, const label size, const label start, const label index, const polyBoundaryMesh &bm, const word &patchType, const transformType transform=UNKNOWN)
Construct from (base couped patch) components.
const bool AMIReverse_
Flag to indicate that slave patch should be reversed for AMI.
const word & neighbPatchName() const
Neighbour patch name.
Type gSum(const FieldField< Field, Type > &f)
dimensionedScalar cos(const dimensionedScalar &ds)
A class for handling words, derived from string.
const autoPtr< searchableSurface > & surfPtr() const
Return a reference to the projection surface.
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
const scalar AMILowWeightCorrection_
Low weight correction threshold for AMI.
point rotationCentre_
Point on axis of rotation for rotational cyclics.
virtual void updateMesh(PstreamBuffers &)
Update of the patch topology.
bool readIfPresent(const word &, T &, bool recursive=false, bool patternMatch=true) const
Find an entry if present, and assign to T.
virtual void resetAMI(const AMIPatchToPatchInterpolation::interpolationMethod &AMIMethod=AMIPatchToPatchInterpolation::imFaceAreaWeight) const
Reset the AMI interpolator.
const Field< PointType > & points() const
Return reference to global points.
static const word null
An empty word.
virtual void updateMesh(PstreamBuffers &)
Update of the patch topology.
Cyclic patch for Arbitrary Mesh Interface (AMI)
errorManip< error > abort(error &err)
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
virtual ~cyclicAMIPolyPatch()
Destructor.
label findMax(const ListType &, const label start=0)
Find index of max element (and larger than given element).
dimensioned< scalar > magSqr(const dimensioned< Type > &)
An Ostream is an abstract base class for all output systems (streams, files, token lists...
dimensionedScalar sin(const dimensionedScalar &ds)
addToRunTimeSelectionTable(ensightPart, ensightPartCells, istream)
defineTypeNameAndDebug(combustionModel, 0)
virtual void write(Ostream &) const
Write the polyPatch data as a dictionary.
Ostream & writeKeyword(const keyType &)
Write the keyword followed by an appropriate indentation.
Buffers for inter-processor communications streams (UOPstream, UIPstream).
void T(FieldField< Field, Type > &f1, const FieldField< Field, Type > &f2)
dimensioned< Type > min(const dimensioned< Type > &, const dimensioned< Type > &)
PrimitivePatch< face, SubList, const pointField & > primitivePatch
Addressing for a faceList slice.
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
word name(const complex &)
Return a string representation of a complex.
virtual void initGeometry(PstreamBuffers &)
Initialise the calculation of the patch geometry.
Field< tensor > tensorField
Specialisation of Field<T> for tensor.
void setSize(const label)
Reset size of List.
virtual void initOrder(PstreamBuffers &, const primitivePatch &) const
Initialize ordering for primitivePatch. Does not.
vector point
Point is a vector.
T lookupOrDefault(const word &, const T &, bool recursive=false, bool patternMatch=true) const
Find and return a T,.
#define WarningInFunction
Report a warning using Foam::Warning.
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
virtual const cyclicAMIPolyPatch & neighbPatch() const
Return a reference to the neighbour patch.
prefixOSstream Pout(cout, "Pout")
virtual bool owner() const
Does this side own the patch?
Interpolation class dealing with transfer of data between two primitive patches with an arbitrary mes...
static autoPtr< searchableSurface > New(const word &surfaceType, const IOobject &io, const dictionary &dict)
Return a reference to the selected searchableSurface.
dimensioned< scalar > mag(const dimensioned< Type > &)
Field< vector > vectorField
Specialisation of Field<T> for vector.
Mesh consisting of general polyhedral cells.
const bMesh & mesh() const
A patch is a list of labels that address the faces in the global face list.
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
word nbrPatchName_
Name of other half.
Tensor< scalar > tensor
Tensor of scalars.
virtual void reverseTransformPosition(point &l, const label facei) const
Transform a patch-based position from this side to nbr side.
static const Vector< scalar > zero
scalar rotationAngle_
Rotation angle.
label pointFace(const label facei, const vector &n, point &p) const
Return face index on neighbour patch which shares point p.
dictionary subOrEmptyDict(const word &, const bool mustRead=false) const
Find and return a sub-dictionary as a copy, or.
dimensionSet transform(const dimensionSet &)
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.
virtual void movePoints(PstreamBuffers &pBufs, const pointField &)
Correct patches after moving points.
virtual void initMovePoints(PstreamBuffers &pBufs, const pointField &)
Initialise the patches for moving points.
const vectorField::subField faceCentres() const
Return face centres.