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])
78 half0Areas[facei] = half0[facei].normal(half0.
points());
85 half1Areas[facei] = half1[facei].normal(half1.
points());
99 Pout<<
"calcTransforms() : patch: " <<
name() <<
nl 100 <<
" forwardT = " << forwardT() <<
nl 101 <<
" reverseT = " << reverseT() <<
nl 102 <<
" separation = " << separation() <<
nl 103 <<
" collocated = " << collocated() <<
nl <<
endl;
120 <<
"Patch " <<
name()
121 <<
" has transform type " << transformTypeNames[
transform()]
122 <<
", neighbour patch " << neighbPatchName()
123 <<
" has transform type " 124 << neighbPatch().transformTypeNames[neighbPatch().transform()]
137 if (rotationAngleDefined_)
139 const tensor T(rotationAxis_*rotationAxis_);
143 0, -rotationAxis_.z(), rotationAxis_.y(),
144 rotationAxis_.z(), 0, -rotationAxis_.x(),
145 -rotationAxis_.y(), rotationAxis_.x(), 0
152 +
sin(rotationAngle_)*S
159 +
sin(-rotationAngle_)*S
164 const vector transformedAreaPos =
gSum(half1Areas & revTPos);
165 const vector transformedAreaNeg =
gSum(half1Areas & revTNeg);
167 const scalar magArea0 =
mag(area0) + ROOTVSMALL;
171 const scalar errorPos =
mag(transformedAreaPos + area0);
172 const scalar errorNeg =
mag(transformedAreaNeg + area0);
174 const scalar normErrorPos = errorPos/magArea0;
175 const scalar normErrorNeg = errorNeg/magArea0;
177 if (errorPos > errorNeg && normErrorNeg < matchTolerance())
180 rotationAngle_ *= -1;
187 const scalar areaError =
min(normErrorPos, normErrorNeg);
189 if (areaError > matchTolerance())
192 <<
"Patch areas are not consistent within " 193 << 100*matchTolerance()
194 <<
" % indicating a possible error in the specified " 195 <<
"angle of rotation" <<
nl 196 <<
" owner patch : " <<
name() <<
nl 197 <<
" neighbour patch : " << neighbPatch().name()
201 <<
" area error : " << 100*areaError <<
" %" 202 <<
" match tolerance : " << matchTolerance()
208 scalar theta =
radToDeg(rotationAngle_);
210 Pout<<
"cyclicAMIPolyPatch::calcTransforms: patch:" 212 <<
" Specified rotation:" 213 <<
" swept angle: " << theta <<
" [deg]" 214 <<
" reverse transform: " << revT
222 if (half0Ctrs.
size())
224 n0 = findFaceNormalMaxRadius(half0Ctrs);
226 if (half1Ctrs.
size())
228 n1 = -findFaceNormalMaxRadius(half1Ctrs);
234 n0 /=
mag(n0) + VSMALL;
235 n1 /=
mag(n1) + VSMALL;
242 (n0 ^ rotationAxis_),
248 (-n1 ^ rotationAxis_),
257 Pout<<
"cyclicAMIPolyPatch::calcTransforms: patch:" 259 <<
" Specified rotation:" 260 <<
" n0:" << n0 <<
" n1:" << n1
261 <<
" swept angle: " << theta <<
" [deg]" 262 <<
" reverse transform: " << revT
278 Pout<<
"cyclicAMIPolyPatch::calcTransforms : patch:" <<
name()
279 <<
" Specified translation : " << separationVector_
299 <<
" Assuming cyclic AMI pairs are colocated" <<
endl;
314 <<
" forwardT = " << forwardT() <<
nl 315 <<
" reverseT = " << reverseT() <<
nl 316 <<
" separation = " << separation() <<
nl 317 <<
" collocated = " << collocated() <<
nl <<
endl;
337 neighbPatch().meshPoints()
348 transformPosition(nbrPoints);
380 AMILowWeightCorrection_,
387 Pout<<
"cyclicAMIPolyPatch : " <<
name()
388 <<
" constructed AMI with " <<
nl 389 <<
" " <<
"srcAddress:" << AMIPtr_().srcAddress().size()
391 <<
" " <<
"tgAddress :" << AMIPtr_().tgtAddress().size()
415 neighbPatch().faceCentres(),
416 neighbPatch().faceAreas(),
417 neighbPatch().faceCellCentres()
481 const word& patchType,
490 rotationAngleDefined_(
false),
492 separationVector_(
Zero),
495 AMIRequireMatch_(
true),
496 AMILowWeightCorrection_(-1.0),
511 const word& patchType
520 rotationAngleDefined_(
false),
522 separationVector_(
Zero),
525 AMIRequireMatch_(
true),
526 AMILowWeightCorrection_(dict.
lookupOrDefault(
"lowWeightCorrection", -1.0)),
535 ) <<
"No \"neighbourPatch\" or \"coupleGroup\" provided." 539 if (nbrPatchName_ == name)
544 ) <<
"Neighbour patch name " << nbrPatchName_
545 <<
" cannot be the same as this patch " << name
553 dict.
lookup(
"rotationAxis") >> rotationAxis_;
554 dict.
lookup(
"rotationCentre") >> rotationCentre_;
557 rotationAngleDefined_ =
true;
558 rotationAngle_ =
degToRad(rotationAngle_);
562 Info<<
"rotationAngle: " << rotationAngle_ <<
" [rad]" 567 scalar magRot =
mag(rotationAxis_);
573 ) <<
"Illegal rotationAxis " << rotationAxis_ <<
endl 574 <<
"Please supply a non-zero vector." 577 rotationAxis_ /= magRot;
583 dict.
lookup(
"separationVector") >> separationVector_;
630 const label newStart,
631 const word& nbrPatchName
635 nbrPatchName_(nbrPatchName),
650 if (nbrPatchName_ ==
name())
653 <<
"Neighbour patch name " << nbrPatchName_
654 <<
" cannot be the same as this patch " <<
name()
700 if (nbrPatchID_ == -1)
702 nbrPatchID_ = this->
boundaryMesh().findPatchID(neighbPatchName());
704 if (nbrPatchID_ == -1)
707 <<
"Illegal neighbourPatch name " << neighbPatchName()
708 <<
nl <<
"Valid patch names are " 715 refCast<const cyclicAMIPolyPatch>
723 <<
"Patch " <<
name()
724 <<
" specifies neighbour patch " << neighbPatchName()
725 <<
nl <<
" but that in return specifies " 736 return index() < neighbPatchID();
743 return refCast<const cyclicAMIPolyPatch>(pp);
750 const word surfType(surfDict_.lookupOrDefault<
word>(
"type",
"none"));
752 if (!surfPtr_.valid() && owner() && surfType !=
"none")
754 word surfName(surfDict_.lookupOrDefault(
"name", name()));
765 mesh.time().constant(),
784 <<
"AMI interpolator only available to owner patch" 788 if (!AMIPtr_.valid())
801 return AMI().applyLowWeightCorrection();
805 return neighbPatch().AMI().applyLowWeightCorrection();
824 else if (separated())
855 forwardT().size() == 1
869 else if (separated())
873 separation().size() == 1
875 : separation()[facei]
893 reverseT().size() == 1
907 else if (separated())
911 separation().size() == 1
913 : separation()[facei]
931 reverseT().size() == 1
997 reverseTransformPosition(prt, facei);
1000 reverseTransformDirection(nrt, facei);
1002 label nbrFacei = -1;
1006 nbrFacei = AMI().tgtPointFace
1017 nbrFacei = neighbPatch().AMI().srcPointFace
1039 if (!nbrPatchName_.empty())
1044 coupleGroup_.write(os);
1055 if (rotationAngleDefined_)
1065 os.
writeKeyword(
"separationVector") << separationVector_
1085 if (AMILowWeightCorrection_ > 0)
1087 os.
writeKeyword(
"lowWeightCorrection") << AMILowWeightCorrection_
1091 if (!surfDict_.empty())
virtual void clearGeom()
Clear geometry.
virtual bool order(PstreamBuffers &, const primitivePatch &, labelList &faceMap, labelList &rotation) const
Return new ordering for primitivePatch.
static bool valid(char)
Is this character valid for a word.
vector separationVector_
Translation vector.
dimensionedScalar acos(const dimensionedScalar &ds)
virtual void initOrder(PstreamBuffers &, const primitivePatch &) const
Initialize ordering for primitivePatch. Does not.
#define forAll(list, i)
Loop across all elements in list.
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.
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.
dictionary subOrEmptyDict(const word &, const bool mustRead=false) const
Find and return a sub-dictionary as a copy, or.
const List< Face > & localFaces() const
Return patch faces addressing into local point list.
virtual void resetAMI(const AMIPatchToPatchInterpolation::interpolationMethod &AMIMethod=AMIPatchToPatchInterpolation::imFaceAreaWeight) const
Reset the AMI interpolator.
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.
const Field< PointType > & points() const
Return reference to global points.
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 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.
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.
virtual void reverseTransformPosition(point &l, const label facei) const
Transform a patch-based position from this side to nbr side.
const bool AMIReverse_
Flag to indicate that slave patch should be reversed for AMI.
Type gSum(const FieldField< Field, Type > &f)
dimensionedScalar cos(const dimensionedScalar &ds)
virtual void write(Ostream &) const
Write the polyPatch data as a dictionary.
A class for handling words, derived from string.
bool readIfPresent(const word &, T &, bool recursive=false, bool patternMatch=true) const
Find an entry if present, and assign to T.
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
const scalar AMILowWeightCorrection_
Low weight correction threshold for AMI.
const autoPtr< searchableSurface > & surfPtr() const
Return a reference to the projection surface.
virtual label neighbPatchID() const
Neighbour patch ID.
point rotationCentre_
Point on axis of rotation for rotational cyclics.
virtual void updateMesh(PstreamBuffers &)
Update of the patch topology.
static const word null
An empty word.
virtual bool owner() const
Does this side own the patch?
virtual void updateMesh(PstreamBuffers &)
Update of the patch topology.
Cyclic patch for Arbitrary Mesh Interface (AMI)
virtual void transformPosition(pointField &) const
Transform patch-based positions from nbr side to this side.
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).
Templated 3D Vector derived from VectorSpace adding construction from 3 components, element access using x(), y() and z() member functions and the inner-product (dot-product) and cross product operators.
dimensioned< scalar > magSqr(const dimensioned< Type > &)
An Ostream is an abstract base class for all output systems (streams, files, token lists...
prefixOSstream Pout(cout,"Pout")
dimensionedScalar sin(const dimensionedScalar &ds)
addToRunTimeSelectionTable(ensightPart, ensightPartCells, istream)
Tensor< Cmpt > T() const
Return transpose.
defineTypeNameAndDebug(combustionModel, 0)
Ostream & writeKeyword(const keyType &)
Write the keyword followed by an appropriate indentation.
const bMesh & mesh() const
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 > &)
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.
virtual void write(Ostream &) const
Write the polyPatch data as a dictionary.
virtual void reverseTransformDirection(vector &d, const label facei) const
Transform a patch-based direction from this side to nbr side.
void setSize(const label)
Reset size of List.
#define WarningInFunction
Report a warning using Foam::Warning.
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
label pointFace(const label facei, const vector &n, point &p) const
Return face index on neighbour patch which shares point p.
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.
const AMIPatchToPatchInterpolation & AMI() const
Return a reference to the AMI interpolator.
dimensioned< scalar > mag(const dimensioned< Type > &)
Field< vector > vectorField
Specialisation of Field<T> for vector.
Mesh consisting of general polyhedral cells.
static const Vector< scalar > zero
const vectorField::subField faceCentres() const
Return face centres.
A patch is a list of labels that address the faces in the global face list.
fileName path() const
Return path.
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
T lookupOrDefault(const word &, const T &, bool recursive=false, bool patternMatch=true) const
Find and return a T,.
const word & neighbPatchName() const
Neighbour patch name.
word nbrPatchName_
Name of other half.
scalar rotationAngle_
Rotation angle.
virtual const cyclicAMIPolyPatch & neighbPatch() const
Return a reference to the neighbour patch.
dimensionSet transform(const dimensionSet &)
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.
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.