59 if (!
mesh.upToDatePoints(AMITime_))
65 <<
" mesh points are up to time " <<
mesh.pointsInstance()
66 <<
" patch:" << this->
name()
74 && (updated || prevTimeIndex_ !=
mesh.time().timeIndex())
79 Pout<<
"cyclicACMIPolyPatch::updateAreas() :"
80 <<
" patch:" << this->
name()
82 <<
" AMITime_:" << AMITime_.eventNo()
83 <<
" uptodate:" <<
mesh.upToDatePoints(AMITime_)
84 <<
" mesh.time().timeIndex():" <<
mesh.time().timeIndex()
85 <<
" prevTimeIndex_:" << prevTimeIndex_
92 <<
"Topology changes and scaling currently not supported."
93 <<
" Patch " << this->
name() <<
endl;
96 const scalar t =
mesh.time().timeOutputValue();
121 Pout<<
"cyclicACMIPolyPatch::updateAreas : scaling masks"
122 <<
" for " <<
name() <<
" mask " <<
gAverage(srcScaledMask_)
131 cpp.scalePatchFaceAreas(*
this, srcScaledMask_, thisSf_, thisNoSf_);
132 cpp.scalePatchFaceAreas(nbrCpp, tgtScaledMask_, nbrSf_, nbrNoSf_);
134 prevTimeIndex_ =
mesh.time().timeIndex();
135 AMITime_.setUpToDate();
148 return io.upToDate(AMITime_);
164 label nUncovered = 0;
166 for (
const scalar
sum : weightSum)
168 if (
sum < tolerance_)
172 else if (
sum > scalar(1) - tolerance_)
181 Info<<
"ACMI: Patch " <<
name <<
" uncovered/blended/covered = "
182 << nUncovered <<
", " << nTotal-nUncovered-nCovered
183 <<
", " << nCovered <<
endl;
197 const scalar maxTol = scalar(1) - tolerance_;
203 <<
"rescaling non-overlap patch areas for: "
209 <<
"Inconsistent sizes for patch: " << acmipp.
name()
210 <<
" - not manipulating patches" <<
nl
211 <<
" - size: " << size() <<
nl
212 <<
" - non-overlap patch size: " << noSf.
size() <<
nl
213 <<
" - mask size: " << mask.
size() <<
nl
214 <<
"This is OK for decomposition but"
215 <<
" should be considered fatal at run-time" <<
endl;
221 tmp<scalarField> scale
226 max(mask, tolerance_),
234 noSf[facei] = noFaceArea[facei]*scale()[facei];
237 const_cast<polyPatch&
>(nonOverlapPatch).areaFraction(scale);
240 if (!createAMIFaces_)
247 <<
"scaling coupled patch areas for: " << acmipp.
name() <<
endl;
257 Sf[facei] = faceArea[facei]*scale()[facei];
271 scalar&
sum = weightsSum[i];
273 for (scalar& w : wghts)
314 const polyPatch& nonOverlapPatch = this->nonOverlapPatch();
317 <<
"cyclicACMIPolyPatch::resetAMI : recalculating weights"
318 <<
" for " <<
name() <<
" and " << nonOverlapPatch.name()
321 const polyMesh&
mesh = boundaryMesh().mesh();
326 if (!
mesh.hasFaceAreas())
329 <<
"primitiveMesh must already have face geometry"
339 const auto& cache = AMI.cache();
341 if (cache.index0() == -1 && cache.index1() == -1)
346 reportCoverage(
"source", AMI.srcWeightsSum());
347 reportCoverage(
"target", AMI.tgtWeightsSum());
358 cache.setDirection(owner());
360 if (cache.applyLower())
363 reportCoverage(
"source", cache.cSrcWeightsSum0());
364 reportCoverage(
"target", cache.cTgtWeightsSum0());
369 else if (cache.applyUpper())
372 reportCoverage(
"source", cache.cSrcWeightsSum1());
373 reportCoverage(
"target", cache.cTgtWeightsSum1());
378 else if (cache.applyInterpolate())
380 srcMask_ = cache.cSrcWeightsSum0();
381 tgtMask_ = cache.cTgtWeightsSum0();
383 const auto srcMask1(cache.cSrcWeightsSum1());
384 const auto tgtMask1(cache.cTgtWeightsSum1());
386 srcMask_ += (srcMask1 - srcMask_)*cache.weight();
387 tgtMask_ += (tgtMask1 - tgtMask_)*cache.weight();
390 reportCoverage(
"source", srcMask_);
391 reportCoverage(
"target", tgtMask_);
404 <<
" non-overlap patch: " <<
patch.nonOverlapPatch().name()
405 <<
" size:" <<
patch.nonOverlapPatch().size()
411 <<
" non-overlap patch: " <<
patch.nonOverlapPatch().name()
412 <<
" size:" << patch.nonOverlapPatch().size()
421 if (!owner() || !canResetAMI())
426 const polyPatch& nonOverlapPatch = this->nonOverlapPatch();
428 const polyPatch& nbrNonOverlapPatch = nbrPatch.nonOverlapPatch();
435 thisSf_ = this->faceAreas();
436 thisNoSf_ = nonOverlapPatch.faceAreas();
437 nbrSf_ = nbrPatch.faceAreas();
438 nbrNoSf_ = nbrNonOverlapPatch.faceAreas();
451 nonOverlapPatch.primitivePatch::faceAreas()
457 nbrPatch.primitivePatch::faceAreas(),
458 nbrNonOverlapPatch.primitivePatch::faceAreas()
466 const auto& acmipp = *
this;
470 Info<<
"cyclicACMI PP: " << acmipp.
name()
473 <<
"cyclicACMI N-O PP: " << nonOverlapPatch.name()
476 <<
"cyclicACMI NBR PP: " << nbrPatch.name()
479 <<
"cyclicACMI NBR N-O PP: " << nbrNonOverlapPatch.name()
480 <<
" V:" <<
sum(
scalarField(vols, nbrNonOverlapPatch.faceCells()))
482 <<
"cyclicACMI PP+N-O AREA: "
483 <<
sum(faceAreas() + nonOverlapPatch.faceAreas()) <<
nl
484 <<
"cyclicACMI NBR PP+N-O AREA: "
485 <<
sum(nbrPatch.faceAreas() + nbrNonOverlapPatch.faceAreas())
500 if (!createAMIFaces_ && canResetAMI())
505 scalePatchFaceAreas();
528 if (!createAMIFaces_ && canResetAMI())
533 scalePatchFaceAreas();
539 PstreamBuffers& pBufs,
581 return srcScaledMask_;
597 return tgtScaledMask_;
614 const polyBoundaryMesh& bm,
615 const word& patchType,
617 const word& defaultAMIMethod
631 nonOverlapPatchName_(),
632 nonOverlapPatchID_(-1),
640 boundaryMesh().
mesh().pointsInstance(),
641 boundaryMesh().
mesh(),
644 IOobject::NO_REGISTER
663 const word& patchType,
664 const word& defaultAMIMethod
668 nonOverlapPatchName_(
dict.get<
word>(
"nonOverlapPatch")),
669 nonOverlapPatchID_(-1),
688 AMIPtr_->setRequireMatch(
false);
690 if (nonOverlapPatchName_ ==
name)
693 <<
"Non-overlapping patch name " << nonOverlapPatchName_
694 <<
" cannot be the same as this patch " <<
name
705 const cyclicACMIPolyPatch&
pp,
706 const polyBoundaryMesh& bm
709 cyclicAMIPolyPatch(
pp, bm),
710 nonOverlapPatchName_(
pp.nonOverlapPatchName_),
711 nonOverlapPatchID_(-1),
714 srcScalePtr_(
pp.srcScalePtr_.clone(*this)),
720 boundaryMesh().
mesh().pointsInstance(),
721 boundaryMesh().
mesh(),
724 IOobject::NO_REGISTER
743 const label newStart,
744 const word& nbrPatchName,
745 const word& nonOverlapPatchName
749 nonOverlapPatchName_(nonOverlapPatchName),
750 nonOverlapPatchID_(-1),
753 srcScalePtr_(
pp.srcScalePtr_.clone(*this)),
769 AMIPtr_->setRequireMatch(
false);
771 if (nonOverlapPatchName_ ==
name())
774 <<
"Non-overlapping patch name " << nonOverlapPatchName_
775 <<
" cannot be the same as this patch " <<
name()
786 const cyclicACMIPolyPatch&
pp,
787 const polyBoundaryMesh& bm,
793 cyclicAMIPolyPatch(
pp, bm, index, mapAddressing, newStart),
794 nonOverlapPatchName_(
pp.nonOverlapPatchName_),
795 nonOverlapPatchID_(-1),
798 srcScalePtr_(
pp.srcScalePtr_.clone(*this)),
804 boundaryMesh().
mesh().pointsInstance(),
805 boundaryMesh().
mesh(),
808 IOobject::NO_REGISTER
814 AMIPtr_->setRequireMatch(
false);
830 forAll(addSourceFaces, faceI)
832 if (fMask[faceI] > tolerance_)
834 const labelList& nbrFaceIs = addSourceFaces[faceI];
838 label nbrFaceI = nbrFaceIs[j];
840 if (nbrFaceI < neighbPatch().size())
856Foam::refPtr<Foam::labelListList>
863 dOverFaces.setSize(srcFaces.size());
866 if (fMask[faceI] > tolerance_)
868 dOverFaces[faceI].setSize(srcFaces[faceI].size());
870 forAll(dOverFaces[faceI], subFaceI)
872 dOverFaces[faceI][subFaceI] = srcFaces[faceI][subFaceI];
885 if (!owner() && srcScalePtr_)
888 <<
"Ignoring \"scale\" setting in slave patch " <<
name()
890 srcScalePtr_.clear();
891 tgtScalePtr_.clear();
900 if (nonOverlapPatchID_ == -1)
903 this->boundaryMesh().findPatchID(nonOverlapPatchName_);
905 if (nonOverlapPatchID_ == -1)
908 <<
"Illegal non-overlapping patch name " << nonOverlapPatchName_
909 <<
nl <<
"Valid patch names are "
910 << this->boundaryMesh().names()
914 if (nonOverlapPatchID_ < index())
917 <<
"Boundary ordering error: " <<
type()
918 <<
" patch must be defined prior to its non-overlapping patch"
920 <<
type() <<
" patch: " <<
name() <<
", ID:" << index() <<
nl
921 <<
"Non-overlap patch: " << nonOverlapPatchName_
922 <<
", ID:" << nonOverlapPatchID_ <<
nl
930 if (size() == noPp.size())
937 scalar ratio =
mag(magSf[facei]/(noMagSf[facei] + ROOTVSMALL));
939 if (ratio - 1 > tolerance_)
954 <<
"Inconsistent ACMI patches " <<
name() <<
" and "
955 << noPp.name() <<
". Patches should have identical topology"
960 return nonOverlapPatchID_;
990 os.writeEntry(
"nonOverlapPatch", nonOverlapPatchName_);
992 if (owner() && srcScalePtr_)
994 srcScalePtr_->writeData(
os);
Macros for easy insertion into run-time selection tables.
#define addToRunTimeSelectionTable(baseType, thisType, argNames)
Add to construction table with typeName as the key.
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
SubField< vector > subField
Defines the attributes of an object for which implicit objectRegistry management is supported,...
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
void setSize(label n)
Alias for resize().
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Top level data entry class for use in dictionaries. Provides a mechanism to specify a variable as a c...
const Field< point_type > & faceAreas() const
Buffers for inter-processor communications streams (UOPstream, UIPstream).
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
bool get(const label i) const
void size(const label n)
Older name for setAddressableSize.
Addressing for all faces on surface of mesh. Can either be read from polyMesh or from triSurface....
const bMesh & mesh() const
Cyclic patch for Arbitrarily Coupled Mesh Interface (ACMI).
virtual autoPtr< polyPatch > clone(const polyBoundaryMesh &bm) const
Construct and return a clone, resetting the boundary mesh.
virtual void updateMesh(PstreamBuffers &)
Update of the patch topology.
void setUpToDate(regIOobject &) const
Set object up to date with *this.
virtual void resetAMI() const
Reset the AMI interpolator, use current patch points.
virtual const scalarField & tgtMask() const
Return the mask/weighting for the target patch.
virtual void scalePatchFaceAreas()
Scale patch face areas to maintain physical area.
virtual void initMovePoints(PstreamBuffers &pBufs, const pointField &)
Initialise the patches for moving points.
virtual refPtr< labelListList > mapCollocatedFaces() const
Return collocated faces.
virtual void write(Ostream &) const
Write the polyPatch data as a dictionary.
const polyPatch & nonOverlapPatch() const
Return a const reference to the non-overlapping patch.
const scalarField & mask() const
Mask field where 1 = overlap(coupled), 0 = no-overlap.
virtual void clearGeom()
Clear geometry.
virtual void calcGeometry(PstreamBuffers &)
Calculate the patch geometry.
virtual void movePoints(PstreamBuffers &pBufs, const pointField &)
Correct patches after moving points.
virtual void newInternalProcFaces(label &, label &) const
Return number of new internal sub-faces and new proc faces.
virtual void initGeometry(PstreamBuffers &)
Initialise the calculation of the patch geometry.
virtual void initOrder(PstreamBuffers &, const primitivePatch &) const
Initialize ordering for primitivePatch. Does not.
virtual const cyclicACMIPolyPatch & neighbPatch() const
Return a reference to the neighbour patch.
virtual const scalarField & srcMask() const
Return the mask/weighting for the source patch.
bool upToDate(const regIOobject &) const
Return true if given object is up to date with *this.
virtual label nonOverlapPatchID() const
Non-overlapping patch ID.
cyclicACMIPolyPatch(const word &name, const label size, const label start, const label index, const polyBoundaryMesh &bm, const word &patchType, const transformType transform=UNKNOWN, const word &defaultAMIMethod=faceAreaWeightAMI::typeName)
Construct from (base coupled patch) components.
void reportCoverage(const word &name, const scalarField &weightSum) const
Report coverage statics, e.g. number of uncovered/blended/covered faces.
virtual bool order(PstreamBuffers &, const primitivePatch &, labelList &faceMap, labelList &rotation) const
Return new ordering for primitivePatch.
virtual void initUpdateMesh(PstreamBuffers &)
Initialise the update of the patch topology.
const word & nonOverlapPatchName() const
Non-overlapping patch name.
virtual void resetAMI(const UList< point > &points) const
Reset the AMI interpolator, supply patch points.
virtual bool updateAreas() const
Update the AMI and patch areas. Return true if anything.
Cyclic patch for Arbitrary Mesh Interface (AMI).
virtual void updateMesh(PstreamBuffers &)
Update of the patch topology.
virtual void resetAMI() const
Reset the AMI interpolator, use current patch points.
bool createAMIFaces_
Flag to indicate that new AMI faces will created.
virtual void initMovePoints(PstreamBuffers &pBufs, const pointField &)
Initialise the patches for moving points.
const scalarField & weightsSum() const
Helper function to return the weights sum.
const scalarListList & weights() const
Helper function to return the weights.
virtual bool owner() const
Does this side own the patch?
virtual void write(Ostream &) const
Write the polyPatch data as a dictionary.
bool canResetAMI() const
Flag to indicate whether the AMI can be reset.
virtual void clearGeom()
Clear geometry.
virtual void calcGeometry(PstreamBuffers &)
Calculate the patch geometry.
virtual void movePoints(PstreamBuffers &pBufs, const pointField &)
Correct patches after moving points.
virtual void initGeometry(PstreamBuffers &)
Initialise the calculation of the patch geometry.
virtual void initOrder(PstreamBuffers &, const primitivePatch &) const
Initialize ordering for primitivePatch. Does not refer to *this (except for name() and type() etc....
const AMIPatchToPatchInterpolation & AMI() const
Return a reference to the AMI interpolator.
static const scalar tolerance_
Tolerance used e.g. for area calculations/limits.
virtual bool order(PstreamBuffers &, const primitivePatch &, labelList &faceMap, labelList &rotation) const
Return new ordering for primitivePatch.
virtual void initUpdateMesh(PstreamBuffers &)
Initialise the update of the patch topology.
cyclicAMIPolyPatch(const word &name, const label size, const label start, const label index, const polyBoundaryMesh &bm, const word &patchType, const transformType transform=UNKNOWN, const word &defaultAMIMethod=faceAreaWeightAMI::typeName)
Construct from (base coupled patch) components.
autoPtr< AMIPatchToPatchInterpolation > AMIPtr_
AMI interpolation class.
virtual label neighbPatchID() const
Neighbour patch ID.
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
label index() const noexcept
The index of this patch in the boundaryMesh.
const word & name() const noexcept
The patch name.
A polyBoundaryMesh is a polyPatch list with registered IO, a reference to the associated polyMesh,...
const polyMesh & mesh() const noexcept
Return the mesh reference.
Mesh consisting of general polyhedral cells.
A patch is a list of labels that address the faces in the global face list.
const vectorField::subField faceAreas() const
Return face normals.
tmp< scalarField > areaFraction(const pointField &points) const
Calculate the area fraction as the ratio of the stored face area and the area given by the face point...
const polyBoundaryMesh & boundaryMesh() const noexcept
Return boundaryMesh reference.
label start() const noexcept
Return start label of this patch in the polyMesh face list.
const labelUList & faceCells() const
Return face-cell addressing.
const vectorField & faceCentres() const
const scalarField & cellVolumes() const
const vectorField & faceAreas() const
A class for managing references or pointers (no reference counting).
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
label eventNo() const noexcept
Event number at last update.
A class for managing temporary objects.
A class for handling words, derived from Foam::string.
Represents 0/1 range or concept. Used for tagged dispatch or clamping.
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
OBJstream os(runTime.globalPath()/outputName)
#define WarningInFunction
Report a warning using Foam::Warning.
#define DebugPout
Report an information message using Foam::Pout.
Namespace for handling debugging switches.
const std::string patch
OpenFOAM patch number as a std::string.
List< scalarList > scalarListList
List of scalarList.
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
Type gAverage(const FieldField< Field, Type > &f, const label comm)
The global arithmetic average of a FieldField.
List< T > uniqueSort(const UList< T > &input)
Return sorted list with removal of duplicates.
Type & refCast(U &obj)
A dynamic_cast (for references) to Type reference.
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
List< labelList > labelListList
List of labelList.
List< label > labelList
A List of labels.
const dimensionSet dimTime(0, 0, 1, 0, 0, 0, 0)
refinementData transform(const tensor &, const refinementData val)
No-op rotational transform for base types.
messageStream Info
Information stream (stdout output on master, null elsewhere).
PrimitivePatch< SubList< face >, const pointField & > primitivePatch
A PrimitivePatch with a SubList addressing for the faces, const reference for the point field.
dimensionSet clamp(const dimensionSet &a, const dimensionSet &range)
List< vector > vectorList
List of vector.
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
T returnReduce(const T &value, BinaryOp bop, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm)
Perform reduction on a copy, using specified binary operation.
Ostream & endl(Ostream &os)
Add newline and flush stream.
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).
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
AMIInterpolation AMIPatchToPatchInterpolation
Patch-to-patch interpolation == Foam::AMIInterpolation.
errorManip< error > abort(error &err)
Field< vector > vectorField
Specialisation of Field<T> for vector.
IOerror FatalIOError
Error stream (stdout output on all processes), with additional 'FOAM FATAL IO ERROR' header text and ...
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &f1, const label comm)
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
vectorField pointField
pointField is a vectorField.
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
errorManipArg< error, int > exit(error &err, const int errNo=1)
UList< label > labelUList
A UList of labels.
List< scalar > scalarList
List of scalar.
constexpr char nl
The newline '\n' character (0x0a).
#define forAll(list, i)
Loop across all elements in list.