45 patchNeighbourFieldPtr_(nullptr)
60 patchNeighbourFieldPtr_(nullptr)
62 if (!isA<cyclicACMIFvPatch>(
p))
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
83 new Field<Type>(*hasNeighbValue,
p.size())
95 static_cast<const GeometricField<Type, fvPatchField, volMesh>&
> 103 <<
" patch " <<
p.name()
105 <<
" refers to non-overlap patch " 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)
149 if (!isA<cyclicACMIFvPatch>(this->
patch()))
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()
171 const cyclicACMIFvPatchField<Type>& ptf
174 cyclicACMILduInterfaceField(),
175 coupledFvPatchField<Type>(ptf),
176 cyclicACMIPatch_(ptf.cyclicACMIPatch_),
177 patchNeighbourFieldPtr_(nullptr)
179 if (
debug && !ptf.all_ready())
182 <<
"Outstanding request(s) on patch " << cyclicACMIPatch_.
name()
191 const cyclicACMIFvPatchField<Type>& ptf,
192 const DimensionedField<Type, volMesh>& iF
195 cyclicACMILduInterfaceField(),
196 coupledFvPatchField<Type>(ptf, iF),
197 cyclicACMIPatch_(ptf.cyclicACMIPatch_),
198 patchNeighbourFieldPtr_(nullptr)
200 if (
debug && !ptf.all_ready())
203 <<
"Outstanding request(s) on patch " << cyclicACMIPatch_.
name()
214 return cyclicACMIPatch_.coupled();
227 recvRequests_.start(),
232 recvRequests_.
clear();
240 sendRequests_.start(),
245 sendRequests_.clear();
260 recvRequests_.start(),
265 recvRequests_.clear();
271 sendRequests_.start(),
276 sendRequests_.clear();
290 const UList<Type>& internalData
294 <<
"cyclicACMIFvPatchField::getNeighbourField(const UList<Type>&) :" 295 <<
" field:" << this->internalField().name()
296 <<
" patch:" << this->
patch().name()
301 const auto& neighbPatch = cyclicACMIPatch_.neighbPatch();
302 const labelUList& nbrFaceCells = neighbPatch.faceCells();
304 tmp<Field<Type>> tpnf
306 cyclicACMIPatch_.interpolate
308 Field<Type>(internalData, nbrFaceCells)
314 transform(tpnf.ref(), forwardT(), tpnf());
338 const auto& AMI = this->ownerAMI();
342 AMI.distributed() && cacheNeighbourField()
349 <<
"Outstanding recv request(s) on patch " 350 << cyclicACMIPatch_.name()
351 <<
" field " << this->internalField().name()
356 if (!patchNeighbourFieldPtr_)
359 <<
"cyclicACMIFvPatchField::patchNeighbourField() :" 360 <<
" field:" << this->internalField().name()
361 <<
" patch:" << this->
patch().name()
362 <<
" calculating&caching patchNeighbourField" 366 patchNeighbourFieldPtr_.reset
368 getNeighbourField(this->primitiveField()).ptr()
374 <<
"cyclicACMIFvPatchField::patchNeighbourField() :" 375 <<
" field:" << this->internalField().name()
376 <<
" patch:" << this->
patch().name()
377 <<
" returning cached patchNeighbourField" 380 return patchNeighbourFieldPtr_();
386 <<
"cyclicACMIFvPatchField::evaluate() :" 387 <<
" field:" << this->internalField().name()
388 <<
" patch:" << this->
patch().name()
389 <<
" calculating up-to-date patchNeighbourField" 392 return getNeighbourField(this->primitiveField());
401 return this->getPatchNeighbourField(
true);
412 auto tpnf = this->getPatchNeighbourField(
false);
424 this->primitiveField()
427 return refCast<const cyclicACMIFvPatchField<Type>>
429 fld.boundaryField()[cyclicACMIPatch_.neighbPatchID()]
441 this->primitiveField()
445 return fld.boundaryField()[cyclicACMIPatch_.nonOverlapPatchID()];
455 if (!this->updated())
457 this->updateCoeffs();
460 const auto& AMI = this->ownerAMI();
462 if (AMI.distributed() && cacheNeighbourField() && AMI.comm() != -1)
467 patchNeighbourFieldPtr_.reset(
nullptr);
473 <<
"cyclicACMIFvPatchField::initEvaluate() :" 474 <<
" field:" << this->internalField().name()
475 <<
" patch:" << this->
patch().name()
476 <<
" starting send&receive" 481 const cyclicACMIFvPatch& neighbPatch = cyclicACMIPatch_.neighbPatch();
482 const labelUList& nbrFaceCells = neighbPatch.faceCells();
483 const Field<Type> pnf(this->primitiveField(), nbrFaceCells);
486 if (!recvRequests_.empty())
489 <<
"Outstanding recv request(s) on patch " 490 << cyclicACMIPatch_.name()
491 <<
" field " << this->internalField().name()
496 sendRequests_.clear();
498 cyclicACMIPatch_.initInterpolate
516 if (!this->updated())
518 this->updateCoeffs();
521 const auto& AMI = this->ownerAMI();
523 if (AMI.distributed() && cacheNeighbourField() && AMI.comm() != -1)
529 <<
"Can only evaluate distributed AMI with nonBlocking" 533 patchNeighbourFieldPtr_.reset(
nullptr);
538 <<
"Outstanding recv request(s) on patch " 539 << cyclicACMIPatch_.name()
540 <<
" field " << this->internalField().name()
544 patchNeighbourFieldPtr_.reset
546 cyclicACMIPatch_.interpolate
555 recvRequests_.clear();
560 auto& pnf = *patchNeighbourFieldPtr_;
583 const auto& AMI = this->ownerAMI();
585 if (AMI.distributed() && AMI.comm() != -1)
591 <<
"Can only evaluate distributed AMI with nonBlocking" 596 <<
"cyclicACMIFvPatchField::initInterfaceMatrixUpdate() :" 597 <<
" field:" << this->internalField().name()
598 <<
" patch:" << this->
patch().name()
599 <<
" starting send&receive" 603 lduAddr.
patchAddr(cyclicACMIPatch_.neighbPatchID());
608 transformCoupleField(pnf, cmpt);
611 if (!recvRequests_.empty())
614 <<
"Outstanding recv request(s) on patch " 615 << cyclicACMIPatch_.name()
616 <<
" field " << this->internalField().name()
621 sendRequests_.clear();
623 cyclicACMIPatch_.initInterpolate
633 this->updatedMatrix(
false);
650 DebugPout<<
"cyclicACMIFvPatchField::updateInterfaceMatrix() :" 651 <<
" field:" << this->internalField().name()
652 <<
" patch:" << this->
patch().name()
661 const auto& AMI = this->ownerAMI();
663 if (AMI.distributed() && AMI.comm() != -1)
668 <<
"Can only evaluate distributed AMI with nonBlocking" 673 <<
"cyclicACMIFvPatchField::evaluate() :" 674 <<
" field:" << this->internalField().name()
675 <<
" patch:" << this->
patch().name()
676 <<
" consuming received coupled neighbourfield" 680 cyclicACMIPatch_.interpolate
688 recvRequests_.
clear();
693 lduAddr.
patchAddr(cyclicACMIPatch_.neighbPatchID());
698 transformCoupleField(pnf, cmpt);
700 pnf = cyclicACMIPatch_.interpolate(pnf);
703 this->addToInternalField(result, !
add, faceCells, coeffs, pnf);
705 this->updatedMatrix(
true);
721 const auto& AMI = this->ownerAMI();
723 if (AMI.distributed() && AMI.comm() != -1)
728 <<
"Can only evaluate distributed AMI with nonBlocking" 733 lduAddr.
patchAddr(cyclicACMIPatch_.neighbPatchID());
735 Field<Type> pnf(psiInternal, nbrFaceCells);
738 transformCoupleField(pnf);
741 if (!recvRequests_.empty())
744 <<
"Outstanding recv request(s) on patch " 745 << cyclicACMIPatch_.name()
746 <<
" field " << this->internalField().name()
751 sendRequests_.clear();
753 cyclicACMIPatch_.initInterpolate
763 this->updatedMatrix(
false);
783 const auto& AMI = this->ownerAMI();
787 if (AMI.distributed() && AMI.comm() != -1)
792 <<
"Can only evaluate distributed AMI with nonBlocking" 797 cyclicACMIPatch_.interpolate
805 recvRequests_.
clear();
810 lduAddr.
patchAddr(cyclicACMIPatch_.neighbPatchID());
812 pnf = Field<Type>(psiInternal, nbrFaceCells);
815 transformCoupleField(pnf);
817 pnf = cyclicACMIPatch_.interpolate(pnf);
820 this->addToInternalField(result, !
add, faceCells, coeffs, pnf);
822 this->updatedMatrix(
true);
832 const scalarField& mask = cyclicACMIPatch_.cyclicACMIPatch().mask();
850 if (this->cyclicACMIPatch().owner())
852 label index = this->
patch().index();
854 const label globalPatchID =
882 label globalFaceI =
faceMap[j];
884 const scalar boundCorr = -bndCoeffs[subFaceI];
885 const scalar intCorr = -intCoeffs[subFaceI];
887 matrix.
upper()[globalFaceI] += boundCorr;
888 matrix.
diag()[u[globalFaceI]] -= intCorr;
889 matrix.
diag()[l[globalFaceI]] -= boundCorr;
893 matrix.
lower()[globalFaceI] += intCorr;
901 if (matrix.
psi(mat).mesh().fluxRequired(this->internalField().
name()))
905 globalPatchID, intCoeffs*pTraits<Type>::one
909 globalPatchID, bndCoeffs*pTraits<Type>::one
912 const label nbrPathID =
913 cyclicACMIPatch_.cyclicACMIPatch().neighbPatchID();
915 const label nbrGlobalPatchID =
921 nbrGlobalPatchID, intCoeffs*pTraits<Type>::one
925 nbrGlobalPatchID, bndCoeffs*pTraits<Type>::one
936 fvMatrix<Type>& matrix,
937 const Field<scalar>& coeffs,
941 const label index(this->
patch().index());
943 const label nSubFaces
945 matrix.lduMeshAssembly().cellBoundMap()[mat][index].size()
948 auto tmapCoeffs = tmp<Field<scalar>>
::New(nSubFaces,
Zero);
949 auto& mapCoeffs = tmapCoeffs.ref();
952 cyclicACMIPatch_.cyclicACMIPatch().AMI().srcWeights();
954 const scalarField& mask = cyclicACMIPatch_.cyclicACMIPatch().mask();
961 for(label i=0; i<w.size(); i++)
963 if (mask[faceI] > tol)
965 const label localFaceId =
966 matrix.lduMeshAssembly().facePatchFaceMap()
967 [mat][index][subFaceI];
968 mapCoeffs[subFaceI] = w[i]*coeffs[localFaceId];
987 const scalarField& mask = cyclicACMIPatch_.cyclicACMIPatch().mask();
999 if (patchNeighbourFieldPtr_)
1001 patchNeighbourFieldPtr_->writeEntry(
"neighbourValue",
os);
bool readValueEntry(const dictionary &dict, IOobjectOption::readOption readOpt=IOobjectOption::LAZY_READ)
Read the "value" entry into *this.
List< scalar > scalarList
List of scalar.
const scalarField & diag() const
virtual void evaluate(const Pstream::commsTypes commsType)
Evaluate the patch field.
const labelListList & patchLocalToGlobalMap() const
Return patchLocalToGlobalMap.
errorManipArg< error, int > exit(error &err, const int errNo=1)
const fvPatchField< Type > & nonOverlapPatchField() const
Return reference to non-overlapping patchField.
Field< solveScalar > solveScalarField
commsTypes
Communications types.
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...
void checkCommunicator(int comm, int rank)
Fatal if communicator is outside the allocated range.
const fvPatch & patch() const noexcept
Return the patch.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
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.
virtual tmp< Field< Type > > patchNeighbourField() const
Return neighbour coupled internal cell data.
const lduPrimitiveMeshAssembly & lduMeshAssembly()
Return optional lduAdressing.
constexpr char nl
The newline '\n' character (0x0a)
Type & refCast(U &obj)
A dynamic_cast (for references) to Type reference.
virtual label nonOverlapPatchID() const
Return neighbour.
static const Field< Type > & null() noexcept
Return a null Field (reference to a nullObject). Behaves like an empty Field.
Ostream & endl(Ostream &os)
Add newline and flush stream.
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
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.
Abstract base class with a fat-interface to all derived classes covering all possible ways in which t...
Generic GeometricField class.
This boundary condition enforces a cyclic condition between a pair of boundaries, whereby communicati...
void writeValueEntry(Ostream &os) const
Write *this field as a "value" entry.
Smooth ATC in cells next to a set of patches supplied by type.
virtual void write(Ostream &) const
Write.
virtual const labelUList & lowerAddr() const =0
Return lower addressing.
virtual bool coupled() const
Return true if coupled. Note that the underlying patch.
UList< label > labelUList
A UList of labels.
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
#define forAll(list, i)
Loop across all elements in list.
static const char *const typeName
Typename for Field.
Cyclic patch for Arbitrarily Coupled Mesh Interface (ACMI)
const GeometricField< Type, fvPatchField, volMesh > & psi(const label i=0) const
Return psi.
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
virtual bool ready() const
Are all (receive) data available?
virtual void write(Ostream &os) const
Write.
void clear()
Clear the list, i.e. set size to zero.
List< scalarList > scalarListList
List of scalarList.
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
virtual const labelUList & upperAddr() const =0
Return upper addressing.
virtual const labelUList & patchAddr(const label patchNo) const =0
Return patch to internal addressing given patch number.
const scalarField & lower() const
A special matrix type and solver, designed for finite volume solutions of scalar equations. Face addressing is used to make all matrix assembly and solution loops vectorise.
const Field< Type > & primitiveField() const noexcept
Return const-reference to the internal field values.
const cyclicACMIFvPatchField< Type > & neighbourPatchField() const
Return reference to neighbour patchField.
virtual void evaluate(const Pstream::commsTypes commsType)
Evaluate the patch field.
cyclicACMIFvPatchField(const fvPatch &, const DimensionedField< Type, volMesh > &)
Construct from patch and internal field.
errorManip< error > abort(error &err)
Abstract base class for coupled patches.
Abstract base class for cyclic ACMI coupled interfaces.
const word & nonOverlapPatchName() const
Non-overlapping patch name.
bool asymmetric() const noexcept
Matrix is asymmetric (ie, full)
An Ostream is an abstract base class for all output systems (streams, files, token lists...
void add(FieldField< Field1, typename typeOfSum< Type1, Type2 >::type > &f, const FieldField< Field1, Type1 > &f1, const FieldField< Field2, Type2 > &f2)
refinementData transform(const tensor &, const refinementData val)
No-op rotational transform for base types.
int debug
Static debugging option.
virtual void updateCoeffs()
Update the coefficients associated with the patch field.
OBJstream os(runTime.globalPath()/outputName)
const labelListListList & faceBoundMap() const
Return boundary face map.
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.
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< ' ';}gmvFile<< nl;for(const word &name :lagrangianScalarNames){ IOField< scalar > fld(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
virtual void initEvaluate(const Pstream::commsTypes commsType)
Initialise the evaluation of the patch field.
const cyclicACMIPolyPatch & cyclicACMIPatch() const
Return local reference cast into the cyclic patch.
const scalarField & upper() const
const lduAddressing & lduAddr() const
Return the LDU addressing.
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
A simple container of IOobject preferences. Can also be used for general handling of read/no-read/rea...
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
const DimensionedField< Type, volMesh > & internalField() const noexcept
Return const-reference to the dimensioned internal field.
const std::string patch
OpenFOAM patch number as a std::string.
virtual void manipulateMatrix(fvMatrix< Type > &matrix)
Manipulate matrix.
#define DebugPout
Report an information message using Foam::Pout.
"nonBlocking" (immediate) : (MPI_Isend, MPI_Irecv)
const FieldField< Field, Type > & internalCoeffs() const noexcept
fvBoundary scalar field containing pseudo-matrix coeffs for internal cells
The class contains the addressing required by the lduMatrix: upper, lower and losort.
const FieldField< Field, Type > & boundaryCoeffs() const noexcept
fvBoundary scalar field containing pseudo-matrix coeffs for boundary cells
void deepCopy(const UList< T > &list)
Copy elements of the given UList. Sizes must match!
virtual const word & name() const
Return name.
A class for managing temporary objects.
"buffered" : (MPI_Bsend, MPI_Recv)
static int localBoundaryConsistency() noexcept
Get flag for local boundary consistency checks.
static scalar tolerance()
Overlap tolerance.
static bool finishedRequests(const label pos, label len=-1)
Non-blocking comms: have all requests (from position onwards) finished? Corresponds to MPI_Testall() ...
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)