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();
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_)
177 reduce(nUncovered, sumOp<label>());
178 reduce(nCovered, sumOp<label>());
179 label nTotal =
returnReduce(weightSum.size(), sumOp<label>());
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;
252 tmp<scalarField> scale(
max(tolerance_, mask));
257 Sf[facei] = faceArea[facei]*scale()[facei];
260 const_cast<cyclicACMIPolyPatch&
>(acmipp).areaFraction(scale);
271 scalar&
sum = weightsSum[i];
273 for (scalar& w : wghts)
282 const polyMesh&
mesh = boundaryMesh().mesh();
314 const polyPatch& nonOverlapPatch = this->nonOverlapPatch();
317 <<
"cyclicACMIPolyPatch::resetAMI : recalculating weights" 318 <<
" for " <<
name() <<
" and " << nonOverlapPatch.name()
321 const polyMesh&
mesh = boundaryMesh().mesh();
329 <<
"primitiveMesh must already have face geometry" 341 reportCoverage(
"source", AMI.srcWeightsSum());
342 reportCoverage(
"target", AMI.tgtWeightsSum());
348 srcMask_ =
clamp(AMI.srcWeightsSum(), zero_one{});
349 tgtMask_ =
clamp(AMI.tgtWeightsSum(), zero_one{});
355 const cyclicACMIPolyPatch&
patch = *
this;
357 <<
" non-overlap patch: " <<
patch.nonOverlapPatch().name()
358 <<
" size:" <<
patch.nonOverlapPatch().size()
362 const cyclicACMIPolyPatch&
patch = this->neighbPatch();
364 <<
" non-overlap patch: " <<
patch.nonOverlapPatch().name()
365 <<
" size:" <<
patch.nonOverlapPatch().size()
374 if (!owner() || !canResetAMI())
379 const polyPatch& nonOverlapPatch = this->nonOverlapPatch();
380 const cyclicACMIPolyPatch& nbrPatch = this->neighbPatch();
381 const polyPatch& nbrNonOverlapPatch = nbrPatch.nonOverlapPatch();
388 thisSf_ = this->faceAreas();
389 thisNoSf_ = nonOverlapPatch.faceAreas();
390 nbrSf_ = nbrPatch.faceAreas();
391 nbrNoSf_ = nbrNonOverlapPatch.faceAreas();
404 nonOverlapPatch.primitivePatch::faceAreas()
410 nbrPatch.primitivePatch::faceAreas(),
411 nbrNonOverlapPatch.primitivePatch::faceAreas()
415 boundaryMesh().mesh().setUpToDatePoints(AMITime_);
419 const auto& acmipp = *
this;
420 const auto&
mesh = boundaryMesh().mesh();
423 Info<<
"cyclicACMI PP: " << acmipp.
name()
426 <<
"cyclicACMI N-O PP: " << nonOverlapPatch.name()
429 <<
"cyclicACMI NBR PP: " << nbrPatch.name()
432 <<
"cyclicACMI NBR N-O PP: " << nbrNonOverlapPatch.name()
433 <<
" V:" <<
sum(
scalarField(vols, nbrNonOverlapPatch.faceCells()))
435 <<
"cyclicACMI PP+N-O AREA: " 436 <<
sum(faceAreas() + nonOverlapPatch.faceAreas()) <<
nl 437 <<
"cyclicACMI NBR PP+N-O AREA: " 438 <<
sum(nbrPatch.faceAreas() + nbrNonOverlapPatch.faceAreas())
453 if (!createAMIFaces_ && canResetAMI())
458 scalePatchFaceAreas();
481 if (!createAMIFaces_ && canResetAMI())
486 scalePatchFaceAreas();
492 PstreamBuffers& pBufs,
534 return srcScaledMask_;
550 return tgtScaledMask_;
567 const polyBoundaryMesh& bm,
568 const word& patchType,
570 const word& defaultAMIMethod
584 nonOverlapPatchName_(),
585 nonOverlapPatchID_(-1),
593 boundaryMesh().
mesh().pointsInstance(),
594 boundaryMesh().
mesh(),
597 IOobject::NO_REGISTER
603 AMIPtr_->setRequireMatch(
false);
616 const word& patchType,
617 const word& defaultAMIMethod
621 nonOverlapPatchName_(
dict.
get<
word>(
"nonOverlapPatch")),
622 nonOverlapPatchID_(-1),
641 AMIPtr_->setRequireMatch(
false);
643 if (nonOverlapPatchName_ ==
name)
646 <<
"Non-overlapping patch name " << nonOverlapPatchName_
647 <<
" cannot be the same as this patch " <<
name 663 nonOverlapPatchName_(
pp.nonOverlapPatchName_),
664 nonOverlapPatchID_(-1),
667 srcScalePtr_(
pp.srcScalePtr_.clone(*this)),
683 AMIPtr_->setRequireMatch(
false);
696 const label newStart,
697 const word& nbrPatchName,
698 const word& nonOverlapPatchName
702 nonOverlapPatchName_(nonOverlapPatchName),
703 nonOverlapPatchID_(-1),
706 srcScalePtr_(
pp.srcScalePtr_.clone(*this)),
722 AMIPtr_->setRequireMatch(
false);
724 if (nonOverlapPatchName_ ==
name())
727 <<
"Non-overlapping patch name " << nonOverlapPatchName_
728 <<
" cannot be the same as this patch " <<
name()
747 nonOverlapPatchName_(
pp.nonOverlapPatchName_),
748 nonOverlapPatchID_(-1),
751 srcScalePtr_(
pp.srcScalePtr_.clone(*this)),
783 forAll(addSourceFaces, faceI)
785 if (fMask[faceI] > tolerance_)
787 const labelList& nbrFaceIs = addSourceFaces[faceI];
791 label nbrFaceI = nbrFaceIs[j];
793 if (nbrFaceI < neighbPatch().size())
816 dOverFaces.
setSize(srcFaces.size());
819 if (fMask[faceI] > tolerance_)
821 dOverFaces[faceI].setSize(srcFaces[faceI].size());
823 forAll(dOverFaces[faceI], subFaceI)
825 dOverFaces[faceI][subFaceI] = srcFaces[faceI][subFaceI];
835 const polyPatch&
pp = this->boundaryMesh()[neighbPatchID()];
838 if (!owner() && srcScalePtr_)
841 <<
"Ignoring \"scale\" setting in slave patch " <<
name()
843 srcScalePtr_.clear();
844 tgtScalePtr_.clear();
847 return refCast<const cyclicACMIPolyPatch>(
pp);
853 if (nonOverlapPatchID_ == -1)
856 this->boundaryMesh().findPatchID(nonOverlapPatchName_);
858 if (nonOverlapPatchID_ == -1)
861 <<
"Illegal non-overlapping patch name " << nonOverlapPatchName_
862 <<
nl <<
"Valid patch names are " 863 << this->boundaryMesh().names()
867 if (nonOverlapPatchID_ < index())
870 <<
"Boundary ordering error: " <<
type()
871 <<
" patch must be defined prior to its non-overlapping patch" 873 <<
type() <<
" patch: " <<
name() <<
", ID:" << index() <<
nl 874 <<
"Non-overlap patch: " << nonOverlapPatchName_
875 <<
", ID:" << nonOverlapPatchID_ <<
nl 879 const polyPatch& noPp = this->boundaryMesh()[nonOverlapPatchID_];
883 if (size() == noPp.size())
890 scalar ratio =
mag(magSf[facei]/(noMagSf[facei] + ROOTVSMALL));
892 if (ratio - 1 > tolerance_)
907 <<
"Inconsistent ACMI patches " <<
name() <<
" and " 908 << noPp.name() <<
". Patches should have identical topology" 913 return nonOverlapPatchID_;
919 PstreamBuffers& pBufs,
945 if (owner() && srcScalePtr_)
947 srcScalePtr_->writeData(
os);
List< ReturnType > get(const UPtrList< T > &list, const AccessOp &aop)
List of values generated by applying the access operation to each list item.
List< T > uniqueSort(const UList< T > &input)
Return sorted list with removal of duplicates.
virtual void clearGeom()
Clear geometry.
List< scalar > scalarList
List of scalar.
virtual void resetAMI() const
Reset the AMI interpolator, use current patch points.
const Field< point_type > & faceAreas() const
Return face area vectors for patch.
Cyclic patch for Arbitrarily Coupled Mesh Interface (ACMI).
void size(const label n)
Older name for setAddressableSize.
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &f1)
virtual bool order(PstreamBuffers &, const primitivePatch &, labelList &faceMap, labelList &rotation) const
Return new ordering for primitivePatch.
virtual const cyclicACMIPolyPatch & neighbPatch() const
Return a reference to the neighbour patch.
virtual void initUpdateMesh(PstreamBuffers &)
Initialise the update of the patch topology.
errorManipArg< error, int > exit(error &err, const int errNo=1)
virtual void initUpdateMesh(PstreamBuffers &)
Initialise the update of the patch topology.
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
virtual void initGeometry(PstreamBuffers &)
Initialise the calculation of the patch geometry.
virtual bool updateAreas() const
Update the AMI and patch areas. Return true if anything.
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
AMIInterpolation AMIPatchToPatchInterpolation
Patch-to-patch interpolation == Foam::AMIInterpolation.
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
void setUpToDate()
Set as up-to-date.
virtual void write(Ostream &) const
Write the polyPatch data as a dictionary.
constexpr char nl
The newline '\n' character (0x0a)
label eventNo() const noexcept
Event number at last update.
virtual void updateMesh(PstreamBuffers &)
Update of the patch topology.
static const scalar tolerance_
Tolerance used e.g. for area calculations/limits.
Addressing for all faces on surface of mesh. Can either be read from polyMesh or from triSurface...
Ostream & endl(Ostream &os)
Add newline and flush stream.
void setUpToDate(regIOobject &) const
Set object up to date with *this.
Ostream & writeEntry(const keyType &key, const T &value)
Write a keyword/value entry.
const cellList & cells() const
virtual const scalarField & tgtMask() const
Return the mask/weighting for the target patch.
virtual void calcGeometry(PstreamBuffers &)
Calculate the patch geometry.
SubField is a Field obtained as a section of another Field, without its own allocation. SubField is derived from a SubList rather than a List.
T returnReduce(const T &value, const BinaryOp &bop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Perform reduction on a copy, using specified binary operation.
List< labelList > labelListList
List of labelList.
virtual void write(Ostream &) const
Write the polyPatch data as a dictionary.
A class for managing references or pointers (no reference counting)
void reportCoverage(const word &name, const scalarField &weightSum) const
Report coverage statics, e.g. number of uncovered/blended/covered faces.
Macros for easy insertion into run-time selection tables.
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
bool createAMIFaces_
Flag to indicate that new AMI faces will created.
#define forAll(list, i)
Loop across all elements in list.
virtual void calcGeometry(PstreamBuffers &)
Calculate the patch geometry.
const polyPatch & nonOverlapPatch() const
Return a const reference to the non-overlapping patch.
virtual void newInternalProcFaces(label &, label &) const
Return number of new internal sub-faces and new proc faces.
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
A list of faces which address into the list of points.
virtual void movePoints(PstreamBuffers &pBufs, const pointField &)
Correct patches after moving points.
vectorField pointField
pointField is a vectorField.
void setSize(const label n)
Alias for resize()
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
virtual const scalarField & srcMask() const
Return the mask/weighting for the source patch.
const polyBoundaryMesh & boundaryMesh() const noexcept
Return boundaryMesh reference.
virtual void scalePatchFaceAreas()
Scale patch face areas to maintain physical area.
const labelUList & faceCells() const
Return face-cell addressing.
const polyMesh & mesh() const noexcept
Return the mesh reference.
List< scalarList > scalarListList
List of scalarList.
A class for handling words, derived from Foam::string.
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
autoPtr< AMIPatchToPatchInterpolation > AMIPtr_
AMI interpolation class.
virtual void updateMesh(PstreamBuffers &)
Update of the patch topology.
virtual void initMovePoints(PstreamBuffers &pBufs, const pointField &)
Initialise the patches for moving points.
Cyclic patch for Arbitrary Mesh Interface (AMI)
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
const vectorField & cellCentres() const
errorManip< error > abort(error &err)
const scalarField & weightsSum() const
Helper function to return the weights sum.
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO...
virtual void clearGeom()
Clear geometry.
const word & name() const noexcept
The patch name.
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 vectorField::subField faceAreas() const
Return face normals.
int debug
Static debugging option.
virtual bool order(PstreamBuffers &, const primitivePatch &, labelList &faceMap, labelList &rotation) const
Return new ordering for primitivePatch.
OBJstream os(runTime.globalPath()/outputName)
virtual void initGeometry(PstreamBuffers &)
Initialise the calculation of the patch geometry.
defineTypeNameAndDebug(combustionModel, 0)
bool hasFaceAreas() const noexcept
Buffers for inter-processor communications streams (UOPstream, UIPstream).
PrimitivePatch< SubList< face >, const pointField & > primitivePatch
A PrimitivePatch with a SubList addressing for the faces, const reference for the point field...
bool upToDate(const regIOobject &) const
Return true if given object is up to date with *this.
const vectorField & faceCentres() const
virtual void initOrder(PstreamBuffers &, const primitivePatch &) const
Initialize ordering for primitivePatch. Does not refer to *this (except for name() and type() etc...
virtual void resetAMI() const
Reset the AMI interpolator, use current patch points.
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.
#define WarningInFunction
Report a warning using Foam::Warning.
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
Type gAverage(const FieldField< Field, Type > &f)
virtual bool owner() const
Does this side own the patch?
const vectorField & faceAreas() const
const std::string patch
OpenFOAM patch number as a std::string.
const dimensionSet dimTime(0, 0, 1, 0, 0, 0, 0)
#define DebugPout
Report an information message using Foam::Pout.
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
messageStream Info
Information stream (stdout output on master, null elsewhere)
SubField< vector > subField
Declare type of subField.
virtual refPtr< labelListList > mapCollocatedFaces() const
Return collocated faces.
Mesh consisting of general polyhedral cells.
IOobject io("surfaceFilmProperties", mesh.time().constant(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, IOobject::NO_REGISTER)
A patch is a list of labels that address the faces in the global face list.
dimensionSet transform(const dimensionSet &ds)
Return the argument; transformations do not change the dimensions.
virtual void initOrder(PstreamBuffers &, const primitivePatch &) const
Initialize ordering for primitivePatch. Does not.
Defines the attributes of an object for which implicit objectRegistry management is supported...
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
void reduce(T &value, const BinaryOp &bop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Reduce inplace (cf. MPI Allreduce) using linear/tree communication schedule.
const scalarListList & weights() const
Helper function to return the weights.
virtual label nonOverlapPatchID() const
Non-overlapping patch ID.
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
dimensionSet clamp(const dimensionSet &a, const dimensionSet &range)
addToRunTimeSelectionTable(functionObject, pointHistory, dictionary)
const scalarField & cellVolumes() const
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.
IOerror FatalIOError
Error stream (stdout output on all processes), with additional 'FOAM FATAL IO ERROR' header text and ...