45 patchNeighbourFieldPtr_(nullptr)
60 patchNeighbourFieldPtr_(nullptr)
65 <<
" patch type '" <<
p.type()
66 <<
"' not constraint type '" <<
typeName <<
"'"
67 <<
"\n for patch " <<
p.name()
73 if (cacheNeighbourField())
76 const auto* hasNeighbValue =
81 patchNeighbourFieldPtr_.reset
95 static_cast<const GeometricField<Type, fvPatchField, volMesh>&
>
100 if (!
fld.boundaryField().set(cyclicACMIPatch_.nonOverlapPatchID()))
103 <<
" patch " <<
p.name()
105 <<
" refers to non-overlap patch "
106 << cyclicACMIPatch_.cyclicACMIPatch().nonOverlapPatchName()
107 <<
" which is not constructed yet." <<
nl
108 <<
" Either supply an initial value or change the ordering"
130 const cyclicACMIFvPatchField<Type>& ptf,
132 const DimensionedField<Type, volMesh>& iF,
133 const fvPatchFieldMapper& mapper
136 cyclicACMILduInterfaceField(),
137 coupledFvPatchField<Type>(ptf,
p, iF, mapper),
138 cyclicACMIPatch_(
refCast<const cyclicACMIFvPatch>(
p)),
139 patchNeighbourFieldPtr_(nullptr)
152 <<
"\n patch type '" <<
p.type()
153 <<
"' not constraint type '" <<
typeName <<
"'"
154 <<
"\n for patch " <<
p.name()
159 if (debug && !ptf.all_ready())
162 <<
"Outstanding request(s) on patch " << cyclicACMIPatch_.name()
163 << abort(FatalError);
176 cyclicACMIPatch_(ptf.cyclicACMIPatch_),
177 patchNeighbourFieldPtr_(nullptr)
179 if (
debug && !ptf.all_ready())
182 <<
"Outstanding request(s) on patch " << cyclicACMIPatch_.name()
183 << abort(FatalError);
197 cyclicACMIPatch_(ptf.cyclicACMIPatch_),
198 patchNeighbourFieldPtr_(nullptr)
200 if (
debug && !ptf.all_ready())
203 <<
"Outstanding request(s) on patch " << cyclicACMIPatch_.name()
204 << abort(FatalError);
214 return cyclicACMIPatch_.coupled();
219bool Foam::cyclicACMIFvPatchField<Type>::all_ready()
const
227 recvRequests_.start(),
232 recvRequests1_.start(),
233 recvRequests1_.size()
237 recvRequests_.clear();
238 recvRequests1_.clear();
246 sendRequests_.start(),
251 sendRequests1_.start(),
252 sendRequests1_.size()
256 sendRequests_.clear();
257 sendRequests1_.clear();
272 recvRequests_.start(),
277 recvRequests1_.start(),
278 recvRequests1_.size()
282 recvRequests_.clear();
283 recvRequests1_.clear();
289 sendRequests_.start(),
294 sendRequests1_.start(),
295 sendRequests1_.size()
299 sendRequests_.clear();
300 sendRequests1_.clear();
311Foam::tmp<Foam::Field<Type>>
312Foam::cyclicACMIFvPatchField<Type>::getNeighbourField
318 <<
"cyclicACMIFvPatchField::getNeighbourField(const UList<Type>&) :"
319 <<
" field:" << this->internalField().name()
320 <<
" patch:" << this->
patch().name()
325 const auto& neighbPatch = cyclicACMIPatch_.neighbPatch();
326 const labelUList& nbrFaceCells = neighbPatch.faceCells();
330 cyclicACMIPatch_.interpolate
338 transform(tpnf.ref(), forwardT(), tpnf());
346bool Foam::cyclicACMIFvPatchField<Type>::cacheNeighbourField()
356Foam::tmp<Foam::Field<Type>>
357Foam::cyclicACMIFvPatchField<Type>::getPatchNeighbourField
359 const bool checkCommunicator
362 const auto& AMI = this->ownerAMI();
366 AMI.distributed() && cacheNeighbourField()
367 && (!checkCommunicator || AMI.comm() != -1)
373 <<
"Outstanding recv request(s) on patch "
374 << cyclicACMIPatch_.name()
375 <<
" field " << this->internalField().name()
380 if (!patchNeighbourFieldPtr_)
383 <<
"cyclicACMIFvPatchField::patchNeighbourField() :"
384 <<
" field:" << this->internalField().name()
385 <<
" patch:" << this->
patch().name()
386 <<
" calculating&caching patchNeighbourField"
390 patchNeighbourFieldPtr_.reset
392 getNeighbourField(this->primitiveField()).ptr()
398 <<
"cyclicACMIFvPatchField::patchNeighbourField() :"
399 <<
" field:" << this->internalField().name()
400 <<
" patch:" << this->
patch().name()
401 <<
" returning cached patchNeighbourField"
404 return patchNeighbourFieldPtr_();
410 <<
"cyclicACMIFvPatchField::evaluate() :"
411 <<
" field:" << this->internalField().name()
412 <<
" patch:" << this->
patch().name()
413 <<
" calculating up-to-date patchNeighbourField"
425 return this->getPatchNeighbourField(
true);
436 auto tpnf = this->getPatchNeighbourField(
false);
448 this->primitiveField()
453 fld.boundaryField()[cyclicACMIPatch_.neighbPatchID()]
465 this->primitiveField()
469 return fld.boundaryField()[cyclicACMIPatch_.nonOverlapPatchID()];
479 if (!this->updated())
481 this->updateCoeffs();
484 const auto& AMI = this->ownerAMI();
486 if (AMI.distributed() && cacheNeighbourField() && AMI.comm() != -1)
491 patchNeighbourFieldPtr_.reset(
nullptr);
497 <<
"cyclicACMIFvPatchField::initEvaluate() :"
498 <<
" field:" << this->internalField().name()
499 <<
" patch:" << this->
patch().name()
500 <<
" starting send&receive"
506 const labelUList& nbrFaceCells = neighbPatch.faceCells();
507 const Field<Type> pnf(this->primitiveField(), nbrFaceCells);
510 if (!recvRequests_.empty() || !recvRequests1_.empty())
513 <<
"Outstanding recv request(s) on patch "
514 << cyclicACMIPatch_.name()
515 <<
" field " << this->internalField().name()
520 sendRequests_.clear();
521 sendRequests1_.clear();
523 cyclicACMIPatch_.initInterpolate
546 if (!this->updated())
548 this->updateCoeffs();
551 const auto& AMI = this->ownerAMI();
553 if (AMI.distributed() && cacheNeighbourField() && AMI.comm() != -1)
559 <<
"Can only evaluate distributed AMI with nonBlocking"
563 patchNeighbourFieldPtr_.reset(
nullptr);
568 <<
"Outstanding recv request(s) on patch "
569 << cyclicACMIPatch_.name()
570 <<
" field " << this->internalField().name()
574 patchNeighbourFieldPtr_.reset
576 cyclicACMIPatch_.interpolate
587 recvRequests_.clear();
588 recvRequests1_.clear();
593 auto& pnf = *patchNeighbourFieldPtr_;
616 const auto& AMI = this->ownerAMI();
618 if (AMI.distributed() && AMI.comm() != -1)
624 <<
"Can only evaluate distributed AMI with nonBlocking"
629 <<
"cyclicACMIFvPatchField::initInterfaceMatrixUpdate() :"
630 <<
" field:" << this->internalField().name()
631 <<
" patch:" << this->patch().name()
632 <<
" starting send&receive"
636 lduAddr.
patchAddr(cyclicACMIPatch_.neighbPatchID());
641 transformCoupleField(pnf, cmpt);
644 if (!recvRequests_.empty() || !recvRequests1_.empty())
647 <<
"Outstanding recv request(s) on patch "
648 << cyclicACMIPatch_.name()
649 <<
" field " << this->internalField().name()
654 sendRequests_.clear();
655 sendRequests1_.clear();
657 cyclicACMIPatch_.initInterpolate
672 this->updatedMatrix(
false);
681 const lduAddressing& lduAddr,
689 DebugPout<<
"cyclicACMIFvPatchField::updateInterfaceMatrix() :"
690 <<
" field:" << this->internalField().name()
691 <<
" patch:" << this->patch().name()
700 const auto& AMI = this->ownerAMI();
702 if (AMI.distributed() && AMI.comm() != -1)
707 <<
"Can only evaluate distributed AMI with nonBlocking"
712 <<
"cyclicACMIFvPatchField::evaluate() :"
713 <<
" field:" << this->internalField().name()
714 <<
" patch:" << this->
patch().name()
715 <<
" consuming received coupled neighbourfield"
719 cyclicACMIPatch_.interpolate
729 recvRequests_.clear();
730 recvRequests1_.clear();
735 lduAddr.patchAddr(cyclicACMIPatch_.neighbPatchID());
740 transformCoupleField(pnf, cmpt);
742 pnf = cyclicACMIPatch_.interpolate(pnf);
763 const auto& AMI = this->ownerAMI();
765 if (AMI.distributed() && AMI.comm() != -1)
770 <<
"Can only evaluate distributed AMI with nonBlocking"
775 lduAddr.
patchAddr(cyclicACMIPatch_.neighbPatchID());
777 Field<Type> pnf(psiInternal, nbrFaceCells);
780 transformCoupleField(pnf);
783 if (!recvRequests_.empty() || !recvRequests1_.empty())
786 <<
"Outstanding recv request(s) on patch "
787 << cyclicACMIPatch_.name()
788 <<
" field " << this->internalField().name()
793 sendRequests_.clear();
794 sendRequests1_.clear();
796 cyclicACMIPatch_.initInterpolate
811 this->updatedMatrix(
false);
820 const lduAddressing& lduAddr,
822 const Field<Type>& psiInternal,
831 const auto& AMI = this->ownerAMI();
835 if (AMI.distributed() && AMI.comm() != -1)
840 <<
"Can only evaluate distributed AMI with nonBlocking"
845 cyclicACMIPatch_.interpolate
855 recvRequests_.clear();
856 recvRequests1_.clear();
861 lduAddr.patchAddr(cyclicACMIPatch_.neighbPatchID());
866 transformCoupleField(pnf);
868 pnf = cyclicACMIPatch_.interpolate(pnf);
883 const scalarField& mask = cyclicACMIPatch_.cyclicACMIPatch().mask();
901 if (this->cyclicACMIPatch().owner())
903 label index = this->patch().index();
905 const label globalPatchID =
933 label globalFaceI =
faceMap[j];
935 const scalar boundCorr = -bndCoeffs[subFaceI];
936 const scalar intCorr = -intCoeffs[subFaceI];
938 matrix.
upper()[globalFaceI] += boundCorr;
939 matrix.
diag()[u[globalFaceI]] -= intCorr;
940 matrix.
diag()[l[globalFaceI]] -= boundCorr;
944 matrix.
lower()[globalFaceI] += intCorr;
963 const label nbrPathID =
964 cyclicACMIPatch_.cyclicACMIPatch().neighbPatchID();
966 const label nbrGlobalPatchID =
984Foam::tmp<Foam::Field<Foam::scalar>>
985Foam::cyclicACMIFvPatchField<Type>::coeffs
992 const label index(this->
patch().index());
994 const label nSubFaces
996 matrix.lduMeshAssembly().cellBoundMap()[mat][index].size()
1000 auto& mapCoeffs = tmapCoeffs.ref();
1003 cyclicACMIPatch_.cyclicACMIPatch().AMI().srcWeights();
1005 const scalarField& mask = cyclicACMIPatch_.cyclicACMIPatch().mask();
1012 for(label i=0; i<w.size(); i++)
1014 if (mask[faceI] > tol)
1016 const label localFaceId =
1017 matrix.lduMeshAssembly().facePatchFaceMap()
1018 [mat][index][subFaceI];
1019 mapCoeffs[subFaceI] = w[i]*coeffs[localFaceId];
1050 if (patchNeighbourFieldPtr_)
1052 patchNeighbourFieldPtr_->writeEntry(
"neighbourValue",
os);
Info<< nl;Info<< "Write faMesh in vtk format:"<< nl;{ vtk::uindirectPatchWriter writer(aMesh.patch(), fileName(aMesh.time().globalPath()/vtkBaseFileName));writer.writeGeometry();globalIndex procAddr(aMesh.nFaces());labelList cellIDs;if(UPstream::master()) { cellIDs.resize(procAddr.totalSize());for(const labelRange &range :procAddr.ranges()) { auto slice=cellIDs.slice(range);slice=identity(range);} } writer.beginCellData(4);writer.writeProcIDs();writer.write("cellID", cellIDs);writer.write("area", aMesh.S().field());writer.write("normal", aMesh.faceAreaNormals());writer.beginPointData(1);writer.write("normal", aMesh.pointAreaNormals());Info<< " "<< writer.output().name()<< nl;}{ vtk::lineWriter writer(aMesh.points(), aMesh.edges(), fileName(aMesh.time().globalPath()/(vtkBaseFileName+"-edges")));writer.writeGeometry();writer.beginCellData(4);writer.writeProcIDs();{ Field< scalar > fld(faMeshTools::flattenEdgeField(aMesh.magLe(), true))
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
const Mesh & mesh() const noexcept
Return const reference to mesh.
static int localBoundaryConsistency() noexcept
Get flag for local boundary consistency checks.
Generic templated field type that is much like a Foam::List except that it is expected to hold numeri...
static const Field< Type > & null() noexcept
Return a null Field (reference to a nullObject). Behaves like an empty Field.
constexpr Field() noexcept
Default construct.
Generic GeometricField class.
A simple container of IOobject preferences. Can also be used for general handling of read/no-read/rea...
const word & name() const noexcept
Return the object name.
fileName objectPath() const
The complete path + object name.
void clear()
Clear the list, i.e. set size to zero.
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
void deepCopy(const UList< T > &list)
Copy elements of the given UList. Sizes must match!
void size(const label n)
Older name for setAddressableSize.
static bool finishedRequests(label pos, label len=-1)
Non-blocking comms: have all requests (from position onwards) finished? Corresponds to MPI_Testall().
commsTypes
Communications types.
@ nonBlocking
"nonBlocking" (immediate) : (MPI_Isend, MPI_Irecv)
@ buffered
"buffered" : (MPI_Bsend, MPI_Recv)
Abstract base class for coupled patches.
coupledFvPatchField(const fvPatch &, const DimensionedField< Type, volMesh > &)
Construct from patch and internal field.
virtual void evaluate(const Pstream::commsTypes commsType)
Evaluate the patch field.
virtual const labelUList & faceCells() const
Return faceCell addressing.
This boundary condition enforces a cyclic condition between a pair of boundaries, whereby communicati...
const cyclicACMIFvPatchField< Type > & neighbourPatchField() const
Return reference to neighbour patchField.
const fvPatchField< Type > & nonOverlapPatchField() const
Return reference to non-overlapping patchField.
virtual bool doTransform() const
Does the patch field perform the transformation.
virtual void initInterfaceMatrixUpdate(solveScalarField &result, const bool add, const lduAddressing &lduAddr, const label patchId, const solveScalarField &psiInternal, const scalarField &coeffs, const direction cmpt, const Pstream::commsTypes commsType) const
Initialise neighbour matrix update.
const cyclicACMIFvPatch & cyclicACMIPatch() const
Return local reference cast into the cyclic AMI patch.
virtual void updateInterfaceMatrix(solveScalarField &result, const bool add, const lduAddressing &lduAddr, const label patchId, const solveScalarField &psiInternal, const scalarField &coeffs, const direction cmpt, const Pstream::commsTypes commsType) const
Update result field based on interface functionality.
cyclicACMIFvPatchField(const fvPatch &, const DimensionedField< Type, volMesh > &)
Construct from patch and internal field.
virtual void initEvaluate(const Pstream::commsTypes commsType)
Initialise the evaluation of the patch field.
virtual bool coupled() const
Return true if coupled. Note that the underlying patch.
virtual void write(Ostream &os) const
Write.
virtual void updateCoeffs()
Update the coefficients associated with the patch field.
virtual void manipulateMatrix(fvMatrix< Type > &matrix)
Manipulate matrix.
virtual void evaluate(const Pstream::commsTypes commsType)
Evaluate the patch field.
virtual bool ready() const
Are all (receive) data available?
virtual tmp< Field< Type > > patchNeighbourField() const
Return neighbour coupled internal cell data.
virtual const tensorField & forwardT() const
Return face transformation tensor.
Cyclic patch for Arbitrarily Coupled Mesh Interface (ACMI).
virtual const cyclicACMIFvPatch & neighbPatch() const
Return neighbour fvPatch.
Abstract base class for cyclic ACMI coupled interfaces.
void transformCoupleField(Field< Type > &f) const
Transform given patch field.
cyclicACMILduInterfaceField()
Construct null.
static scalar tolerance()
Overlap tolerance.
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Smooth ATC in cells next to a set of patches supplied by type.
A special matrix type and solver, designed for finite volume solutions of scalar equations....
const FieldField< Field, Type > & internalCoeffs() const noexcept
fvBoundary scalar field containing pseudo-matrix coeffs for internal cells
const FieldField< Field, Type > & boundaryCoeffs() const noexcept
fvBoundary scalar field containing pseudo-matrix coeffs for boundary cells
const lduPrimitiveMeshAssembly & lduMeshAssembly()
Return optional lduAdressing.
const GeometricField< Type, fvPatchField, volMesh > & psi(const label i=0) const
Return psi.
const fvPatch & patch() const noexcept
Return the patch.
bool updated() const noexcept
True if the boundary condition has already been updated.
A FieldMapper for finite-volume patch fields.
Abstract base class with a fat-interface to all derived classes covering all possible ways in which t...
virtual void write(Ostream &) const
Write.
void writeValueEntry(Ostream &os) const
Write *this field as a "value" entry.
const Field< Type > & primitiveField() const noexcept
Return const-reference to the internal field values.
const DimensionedField< Type, volMesh > & internalField() const noexcept
Return const-reference to the dimensioned internal field.
virtual void updateWeightedCoeffs(const scalarField &weights)
Update the coefficients associated with the patch field.
bool readValueEntry(const dictionary &dict, IOobjectOption::readOption readOpt=IOobjectOption::LAZY_READ)
Read the "value" entry into *this.
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
The class contains the addressing required by the lduMatrix: upper, lower and losort.
virtual const labelUList & upperAddr() const =0
Return upper addressing.
virtual const labelUList & lowerAddr() const =0
Return lower addressing.
virtual const labelUList & patchAddr(const label patchNo) const =0
Return patch to internal addressing given patch number.
bool updatedMatrix() const noexcept
Whether matrix has been updated.
void addToInternalField(Field< Type > &result, const bool add, const labelUList &faceCells, const scalarField &coeffs, const Field< Type > &vals) const
Add/subtract weighted contributions to internal field.
const lduAddressing & lduAddr() const
Return the LDU addressing.
bool asymmetric() const noexcept
Matrix is asymmetric (ie, full).
const scalarField & diag() const
const scalarField & upper() const
const scalarField & lower() const
const labelListListList & cellBoundMap() const
Return patch local sub-face to nbrCellId map.
const labelListListList & faceBoundMap() const
Return boundary face map.
const labelListListList & facePatchFaceMap() const
Return patch local sub-face to local patch face map.
const labelListList & patchLocalToGlobalMap() const
Return patchLocalToGlobalMap.
A traits class, which is primarily used for primitives and vector-space.
bool fluxRequired(const word &name) const
Get flux-required for given name, or default.
A class for managing temporary objects.
T & ref() const
Return non-const reference to the contents of a non-null managed pointer.
#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 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 & refCast(U &obj)
A dynamic_cast (for references) to Type reference.
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh > > &tf1, const word &name, const dimensionSet &dimensions, const bool initCopy=false)
Global function forwards to reuseTmpDimensionedField::New.
List< label > labelList
A List of labels.
refinementData transform(const tensor &, const refinementData val)
No-op rotational transform for base types.
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
const word GlobalIOList< Tuple2< scalar, vector > >::typeName("scalarVectorTable")
Ostream & endl(Ostream &os)
Add newline and flush stream.
void add(DimensionedField< scalar, GeoMesh > &result, const dimensioned< scalar > &dt1, const DimensionedField< scalar, GeoMesh > &f2)
const Type * isA(const U &obj)
Attempt dynamic_cast to Type.
errorManip< error > abort(error &err)
Field< solveScalar > solveScalarField
IOerror FatalIOError
Error stream (stdout output on all processes), with additional 'FOAM FATAL IO ERROR' header text and ...
static constexpr const zero Zero
Global zero (0).
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
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).
dict add("bounds", meshBb)
#define forAll(list, i)
Loop across all elements in list.