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())
94 const GeometricField<Type, fvPatchField, volMesh>&
fld =
95 static_cast<const GeometricField<Type, fvPatchField, volMesh>&
> 102 <<
" patch " <<
p.name()
104 <<
" refers to non-overlap patch " 106 <<
" which is not constructed yet." <<
nl 107 <<
" Either supply an initial value or change the ordering" 118 GeometricField<Type, fvPatchField, volMesh>::
119 Boundary::localConsistency;
121 const int oldConsistency = consistency;
126 consistency = oldConsistency;
134 const cyclicACMIFvPatchField<Type>& ptf,
136 const DimensionedField<Type, volMesh>& iF,
137 const fvPatchFieldMapper& mapper
140 cyclicACMILduInterfaceField(),
141 coupledFvPatchField<Type>(ptf,
p, iF, mapper),
142 cyclicACMIPatch_(
refCast<const cyclicACMIFvPatch>(
p)),
143 patchNeighbourFieldPtr_(nullptr)
153 if (!isA<cyclicACMIFvPatch>(this->
patch()))
156 <<
"\n patch type '" << p.type()
157 <<
"' not constraint type '" <<
typeName <<
"'" 158 <<
"\n for patch " <<
p.name()
163 if (
debug && !ptf.all_ready())
166 <<
"Outstanding request(s) on patch " << cyclicACMIPatch_.
name()
175 const cyclicACMIFvPatchField<Type>& ptf
178 cyclicACMILduInterfaceField(),
179 coupledFvPatchField<Type>(ptf),
180 cyclicACMIPatch_(ptf.cyclicACMIPatch_),
181 patchNeighbourFieldPtr_(nullptr)
183 if (
debug && !ptf.all_ready())
186 <<
"Outstanding request(s) on patch " << cyclicACMIPatch_.
name()
195 const cyclicACMIFvPatchField<Type>& ptf,
196 const DimensionedField<Type, volMesh>& iF
199 cyclicACMILduInterfaceField(),
200 coupledFvPatchField<Type>(ptf, iF),
201 cyclicACMIPatch_(ptf.cyclicACMIPatch_),
202 patchNeighbourFieldPtr_(nullptr)
204 if (
debug && !ptf.all_ready())
207 <<
"Outstanding request(s) on patch " << cyclicACMIPatch_.
name()
218 return cyclicACMIPatch_.coupled();
231 recvRequests_.start(),
236 recvRequests_.
clear();
244 sendRequests_.start(),
249 sendRequests_.clear();
264 recvRequests_.start(),
269 recvRequests_.clear();
275 sendRequests_.start(),
280 sendRequests_.clear();
294 const Field<Type>& iField
298 <<
"cyclicACMIFvPatchField::patchNeighbourField(const Field<Type>&) :" 299 <<
" field:" << this->internalField().name()
300 <<
" patch:" << this->
patch().name()
305 const cyclicACMIFvPatch& neighbPatch = cyclicACMIPatch_.
neighbPatch();
306 const labelUList& nbrFaceCells = neighbPatch.faceCells();
308 tmp<Field<Type>> tpnf
310 cyclicACMIPatch_.interpolate
323 transform(tpnf.ref(), forwardT(), tpnf());
348 if (this->ownerAMI().distributed() && cacheNeighbourField())
353 <<
"Outstanding recv request(s) on patch " 354 << cyclicACMIPatch_.name()
355 <<
" field " << this->internalField().name()
360 if (!patchNeighbourFieldPtr_)
363 <<
"cyclicACMIFvPatchField::patchNeighbourField() :" 364 <<
" field:" << this->internalField().name()
365 <<
" patch:" << this->
patch().name()
366 <<
" calculating&caching patchNeighbourField" 370 patchNeighbourFieldPtr_.reset
372 patchNeighbourField(this->primitiveField()).ptr()
378 <<
"cyclicACMIFvPatchField::patchNeighbourField() :" 379 <<
" field:" << this->internalField().name()
380 <<
" patch:" << this->
patch().name()
381 <<
" returning cached patchNeighbourField" 384 return patchNeighbourFieldPtr_();
390 <<
"cyclicACMIFvPatchField::evaluate() :" 391 <<
" field:" << this->internalField().name()
392 <<
" patch:" << this->
patch().name()
393 <<
" calculating up-to-date patchNeighbourField" 396 return patchNeighbourField(this->primitiveField());
405 const GeometricField<Type, fvPatchField, volMesh>&
fld =
406 static_cast<const GeometricField<Type, fvPatchField, volMesh>&
> 408 this->primitiveField()
411 return refCast<const cyclicACMIFvPatchField<Type>>
413 fld.boundaryField()[cyclicACMIPatch_.neighbPatchID()]
425 this->primitiveField()
429 return fld.boundaryField()[cyclicACMIPatch_.nonOverlapPatchID()];
439 if (!this->updated())
441 this->updateCoeffs();
444 if (this->ownerAMI().distributed() && cacheNeighbourField())
449 patchNeighbourFieldPtr_.reset(
nullptr);
455 <<
"cyclicACMIFvPatchField::initEvaluate() :" 456 <<
" field:" << this->internalField().name()
457 <<
" patch:" << this->
patch().name()
458 <<
" starting send&receive" 463 const cyclicACMIFvPatch& neighbPatch = cyclicACMIPatch_.neighbPatch();
464 const labelUList& nbrFaceCells = neighbPatch.faceCells();
465 const Field<Type> pnf(this->primitiveField(), nbrFaceCells);
468 if (!recvRequests_.empty())
471 <<
"Outstanding recv request(s) on patch " 472 << cyclicACMIPatch_.name()
473 <<
" field " << this->internalField().name()
478 sendRequests_.clear();
480 cyclicACMIPatch_.initInterpolate
498 if (!this->updated())
500 this->updateCoeffs();
503 const auto& AMI = this->ownerAMI();
505 if (AMI.distributed() && cacheNeighbourField())
511 <<
"Can only evaluate distributed AMI with nonBlocking" 515 patchNeighbourFieldPtr_.reset(
nullptr);
520 <<
"Outstanding recv request(s) on patch " 521 << cyclicACMIPatch_.name()
522 <<
" field " << this->internalField().name()
526 patchNeighbourFieldPtr_.reset
528 cyclicACMIPatch_.interpolate
537 recvRequests_.clear();
540 auto& patchNeighbourField = patchNeighbourFieldPtr_.ref();
545 transform(patchNeighbourField, forwardT(), patchNeighbourField);
567 if (this->ownerAMI().distributed())
573 <<
"Can only evaluate distributed AMI with nonBlocking" 578 <<
"cyclicACMIFvPatchField::initInterfaceMatrixUpdate() :" 579 <<
" field:" << this->internalField().name()
580 <<
" patch:" << this->
patch().name()
581 <<
" starting send&receive" 585 lduAddr.
patchAddr(cyclicACMIPatch_.neighbPatchID());
590 transformCoupleField(pnf, cmpt);
593 if (!recvRequests_.empty())
596 <<
"Outstanding recv request(s) on patch " 597 << cyclicACMIPatch_.name()
598 <<
" field " << this->internalField().name()
603 sendRequests_.clear();
605 cyclicACMIPatch_.initInterpolate
615 this->updatedMatrix(
false);
632 DebugPout<<
"cyclicACMIFvPatchField::updateInterfaceMatrix() :" 633 <<
" field:" << this->internalField().name()
634 <<
" patch:" << this->
patch().name()
643 if (this->ownerAMI().distributed())
648 <<
"Can only evaluate distributed AMI with nonBlocking" 653 <<
"cyclicACMIFvPatchField::evaluate() :" 654 <<
" field:" << this->internalField().name()
655 <<
" patch:" << this->
patch().name()
656 <<
" consuming received coupled neighbourfield" 660 cyclicACMIPatch_.interpolate
668 recvRequests_.
clear();
673 lduAddr.
patchAddr(cyclicACMIPatch_.neighbPatchID());
678 transformCoupleField(pnf, cmpt);
680 pnf = cyclicACMIPatch_.interpolate(pnf);
683 this->addToInternalField(result, !
add, faceCells, coeffs, pnf);
685 this->updatedMatrix(
true);
701 const auto& AMI = this->ownerAMI();
703 if (AMI.distributed())
708 <<
"Can only evaluate distributed AMI with nonBlocking" 713 lduAddr.
patchAddr(cyclicACMIPatch_.neighbPatchID());
715 Field<Type> pnf(psiInternal, nbrFaceCells);
718 transformCoupleField(pnf);
721 if (!recvRequests_.empty())
724 <<
"Outstanding recv request(s) on patch " 725 << cyclicACMIPatch_.name()
726 <<
" field " << this->internalField().name()
731 sendRequests_.clear();
733 cyclicACMIPatch_.initInterpolate
743 this->updatedMatrix(
false);
763 const auto& AMI = this->ownerAMI();
767 if (AMI.distributed())
772 <<
"Can only evaluate distributed AMI with nonBlocking" 777 cyclicACMIPatch_.interpolate
785 recvRequests_.
clear();
790 lduAddr.
patchAddr(cyclicACMIPatch_.neighbPatchID());
792 pnf = Field<Type>(psiInternal, nbrFaceCells);
795 transformCoupleField(pnf);
797 pnf = cyclicACMIPatch_.interpolate(pnf);
800 this->addToInternalField(result, !
add, faceCells, coeffs, pnf);
802 this->updatedMatrix(
true);
812 const scalarField& mask = cyclicACMIPatch_.cyclicACMIPatch().mask();
830 if (this->cyclicACMIPatch().owner())
832 label index = this->
patch().index();
834 const label globalPatchID =
862 label globalFaceI =
faceMap[j];
864 const scalar boundCorr = -bndCoeffs[subFaceI];
865 const scalar intCorr = -intCoeffs[subFaceI];
867 matrix.
upper()[globalFaceI] += boundCorr;
868 matrix.
diag()[u[globalFaceI]] -= intCorr;
869 matrix.
diag()[l[globalFaceI]] -= boundCorr;
873 matrix.
lower()[globalFaceI] += intCorr;
881 if (matrix.
psi(mat).mesh().fluxRequired(this->internalField().
name()))
885 globalPatchID, intCoeffs*pTraits<Type>::one
889 globalPatchID, bndCoeffs*pTraits<Type>::one
892 const label nbrPathID =
893 cyclicACMIPatch_.cyclicACMIPatch().neighbPatchID();
895 const label nbrGlobalPatchID =
901 nbrGlobalPatchID, intCoeffs*pTraits<Type>::one
905 nbrGlobalPatchID, bndCoeffs*pTraits<Type>::one
916 fvMatrix<Type>& matrix,
917 const Field<scalar>& coeffs,
921 const label index(this->
patch().index());
923 const label nSubFaces
925 matrix.lduMeshAssembly().cellBoundMap()[mat][index].size()
928 auto tmapCoeffs = tmp<Field<scalar>>
::New(nSubFaces,
Zero);
929 auto& mapCoeffs = tmapCoeffs.ref();
932 cyclicACMIPatch_.cyclicACMIPatch().AMI().srcWeights();
934 const scalarField& mask = cyclicACMIPatch_.cyclicACMIPatch().mask();
941 for(label i=0; i<w.size(); i++)
943 if (mask[faceI] > tol)
945 const label localFaceId =
946 matrix.lduMeshAssembly().facePatchFaceMap()
947 [mat][index][subFaceI];
948 mapCoeffs[subFaceI] = w[i]*coeffs[localFaceId];
967 const scalarField& mask = cyclicACMIPatch_.cyclicACMIPatch().mask();
979 if (patchNeighbourFieldPtr_)
981 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...
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 cyclicACMIFvPatch & neighbPatch() const
Return neighbour fvPatch.
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
virtual const word & name() const
Return name.
A class for managing temporary objects.
"buffered" : (MPI_Bsend, MPI_Recv)
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)