diff --git a/src/finiteVolume/fields/fvPatchFields/constraint/cyclicAMI/cyclicAMIFvPatchField.C b/src/finiteVolume/fields/fvPatchFields/constraint/cyclicAMI/cyclicAMIFvPatchField.C index ae2ed8a07a..ec3f92a281 100644 --- a/src/finiteVolume/fields/fvPatchFields/constraint/cyclicAMI/cyclicAMIFvPatchField.C +++ b/src/finiteVolume/fields/fvPatchFields/constraint/cyclicAMI/cyclicAMIFvPatchField.C @@ -26,9 +26,11 @@ License \*---------------------------------------------------------------------------*/ +#include "cyclicAMIPolyPatch.H" +#include "mapDistributeBase.H" +#include "AMIInterpolation.H" #include "fvMatrix.H" #include "volFields.H" -//#include "cylicFvPatchField.H" // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // @@ -41,7 +43,10 @@ Foam::cyclicAMIFvPatchField::cyclicAMIFvPatchField : cyclicAMILduInterfaceField(), coupledFvPatchField(p, iF), - cyclicAMIPatch_(refCast(p)) + cyclicAMIPatch_(refCast(p)), + sendRequests_(0), + recvRequests_(0), + patchNeighbourFieldPtr_(nullptr) {} @@ -55,12 +60,15 @@ Foam::cyclicAMIFvPatchField::cyclicAMIFvPatchField : cyclicAMILduInterfaceField(), coupledFvPatchField(p, iF, dict, IOobjectOption::NO_READ), - cyclicAMIPatch_(refCast(p, dict)) + cyclicAMIPatch_(refCast(p, dict)), + sendRequests_(0), + recvRequests_(0), + patchNeighbourFieldPtr_(nullptr) { if (!isA(p)) { FatalIOErrorInFunction(dict) - << " patch type '" << p.type() + << "\n patch type '" << p.type() << "' not constraint type '" << typeName << "'" << "\n for patch " << p.name() << " of field " << this->internalField().name() @@ -68,12 +76,24 @@ Foam::cyclicAMIFvPatchField::cyclicAMIFvPatchField << exit(FatalIOError); } - // Use 'value' supplied, or set to coupled or internal field + // Handle neighbour value first, before any evaluate() + const auto* hasNeighbValue = + dict.findEntry("neighbourValue", keyType::LITERAL); + + if (hasNeighbValue) + { + patchNeighbourFieldPtr_.reset + ( + new Field(*hasNeighbValue, p.size()) + ); + } + + // Use 'value' supplied, or evaluate (if coupled) or set to internal field if (!this->readValueEntry(dict)) { if (this->coupled()) { - this->evaluate(Pstream::commsTypes::blocking); + this->evaluate(UPstream::commsTypes::nonBlocking); } else { @@ -94,8 +114,19 @@ Foam::cyclicAMIFvPatchField::cyclicAMIFvPatchField : cyclicAMILduInterfaceField(), coupledFvPatchField(ptf, p, iF, mapper), - cyclicAMIPatch_(refCast(p)) + cyclicAMIPatch_(refCast(p)), + sendRequests_(0), + recvRequests_(0), + patchNeighbourFieldPtr_(nullptr) { + if (ptf.patchNeighbourFieldPtr_) + { + patchNeighbourFieldPtr_.reset + ( + new Field(ptf.patchNeighbourFieldPtr_(), mapper) + ); + } + if (!isA(this->patch())) { FatalErrorInFunction @@ -106,6 +137,12 @@ Foam::cyclicAMIFvPatchField::cyclicAMIFvPatchField << " in file " << this->internalField().objectPath() << exit(FatalError); } + if (debug && !ptf.all_ready()) + { + FatalErrorInFunction + << "Outstanding request(s) on patch " << cyclicAMIPatch_.name() + << abort(FatalError); + } } @@ -117,8 +154,18 @@ Foam::cyclicAMIFvPatchField::cyclicAMIFvPatchField : cyclicAMILduInterfaceField(), coupledFvPatchField(ptf), - cyclicAMIPatch_(ptf.cyclicAMIPatch_) -{} + cyclicAMIPatch_(ptf.cyclicAMIPatch_), + sendRequests_(0), + recvRequests_(0), + patchNeighbourFieldPtr_(ptf.patchNeighbourFieldPtr_.clone()) +{ + if (debug && !ptf.all_ready()) + { + FatalErrorInFunction + << "Outstanding request(s) on patch " << cyclicAMIPatch_.name() + << abort(FatalError); + } +} template @@ -130,43 +177,111 @@ Foam::cyclicAMIFvPatchField::cyclicAMIFvPatchField : cyclicAMILduInterfaceField(), coupledFvPatchField(ptf, iF), - cyclicAMIPatch_(ptf.cyclicAMIPatch_) -{} + cyclicAMIPatch_(ptf.cyclicAMIPatch_), + sendRequests_(0), + recvRequests_(0), + patchNeighbourFieldPtr_(ptf.patchNeighbourFieldPtr_.clone()) +{ + if (debug && !ptf.all_ready()) + { + FatalErrorInFunction + << "Outstanding request(s) on patch " << cyclicAMIPatch_.name() + << abort(FatalError); + } +} // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // template -bool Foam::cyclicAMIFvPatchField::coupled() const +bool Foam::cyclicAMIFvPatchField::all_ready() const { - return cyclicAMIPatch_.coupled(); + int done = 0; + + if + ( + UPstream::finishedRequests + ( + recvRequests_.start(), + recvRequests_.size() + ) + ) + { + recvRequests_.clear(); + ++done; + } + + if + ( + UPstream::finishedRequests + ( + sendRequests_.start(), + sendRequests_.size() + ) + ) + { + sendRequests_.clear(); + ++done; + } + + return (done == 2); +} + + +template +bool Foam::cyclicAMIFvPatchField::ready() const +{ + if + ( + UPstream::finishedRequests + ( + recvRequests_.start(), + recvRequests_.size() + ) + ) + { + recvRequests_.clear(); + + if + ( + UPstream::finishedRequests + ( + sendRequests_.start(), + sendRequests_.size() + ) + ) + { + sendRequests_.clear(); + } + + return true; + } + + return false; } template Foam::tmp> -Foam::cyclicAMIFvPatchField::patchNeighbourField() const +Foam::cyclicAMIFvPatchField::patchNeighbourField +( + const Field& iField +) const { - const Field& iField = this->primitiveField(); - - // By pass polyPatch to get nbrId. Instead use cyclicAMIFvPatch virtual + // Bypass polyPatch to get nbrId. Instead use cyclicAMIFvPatch virtual // neighbPatch() const cyclicAMIFvPatch& neighbPatch = cyclicAMIPatch_.neighbPatch(); const labelUList& nbrFaceCells = neighbPatch.faceCells(); Field pnf(iField, nbrFaceCells); + Field defaultValues; - tmp> tpnf; if (cyclicAMIPatch_.applyLowWeightCorrection()) { - Field pnfInternal(iField, cyclicAMIPatch_.faceCells()); + defaultValues = Field(iField, cyclicAMIPatch_.faceCells()); + } - tpnf = cyclicAMIPatch_.interpolate(pnf, pnfInternal); - } - else - { - tpnf = cyclicAMIPatch_.interpolate(pnf); - } + tmp> tpnf = cyclicAMIPatch_.interpolate(pnf, defaultValues); if (doTransform()) { @@ -177,6 +292,40 @@ Foam::cyclicAMIFvPatchField::patchNeighbourField() const } +template +Foam::tmp> +Foam::cyclicAMIFvPatchField::patchNeighbourField() const +{ + if (this->ownerAMI().distributed()) + { + if (!this->ready()) + { + FatalErrorInFunction + << "Outstanding recv request(s) on patch " + << cyclicAMIPatch_.name() + << " field " << this->internalField().name() + << abort(FatalError); + } + + // Initialise if not done in construct-from-dictionary + if (!patchNeighbourFieldPtr_) + { + // Do interpolation and store result + patchNeighbourFieldPtr_.reset + ( + patchNeighbourField(this->primitiveField()).ptr() + ); + } + return patchNeighbourFieldPtr_(); + } + else + { + // Do interpolation + return patchNeighbourField(this->primitiveField()); + } +} + + template const Foam::cyclicAMIFvPatchField& Foam::cyclicAMIFvPatchField::neighbourPatchField() const @@ -194,6 +343,150 @@ Foam::cyclicAMIFvPatchField::neighbourPatchField() const } +template +void Foam::cyclicAMIFvPatchField::initEvaluate +( + const Pstream::commsTypes commsType +) +{ + if (!this->updated()) + { + this->updateCoeffs(); + } + + if (this->ownerAMI().distributed()) + { + if (commsType != UPstream::commsTypes::nonBlocking) + { + // Invalidate old field - or flag as fatal? + patchNeighbourFieldPtr_.reset(nullptr); + return; + } + + // Start sending + + // By-pass polyPatch to get nbrId. Instead use cyclicAMIFvPatch virtual + // neighbPatch() + const cyclicAMIFvPatch& neighbPatch = cyclicAMIPatch_.neighbPatch(); + const labelUList& nbrFaceCells = neighbPatch.faceCells(); + const Field pnf(this->primitiveField(), nbrFaceCells); + + const cyclicAMIPolyPatch& cpp = cyclicAMIPatch_.cyclicAMIPatch(); + + cpp.initInterpolate + ( + pnf, + sendRequests_, + sendBufs_, + recvRequests_, + recvBufs_ + ); + } +} + + +template +void Foam::cyclicAMIFvPatchField::evaluate +( + const Pstream::commsTypes commsType +) +{ + if (!this->updated()) + { + this->updateCoeffs(); + } + + const auto& AMI = this->ownerAMI(); + + if (AMI.distributed()) + { + // Calculate patchNeighbourField + if (commsType != UPstream::commsTypes::nonBlocking) + { + FatalErrorInFunction + << "Can only evaluate distributed AMI with nonBlocking" + << exit(FatalError); + } + + patchNeighbourFieldPtr_.reset(nullptr); + + const cyclicAMIPolyPatch& cpp = cyclicAMIPatch_.cyclicAMIPatch(); + + Field defaultValues; + if (AMI.applyLowWeightCorrection()) + { + defaultValues = this->patchInternalField(); + } + + patchNeighbourFieldPtr_.reset + ( + cpp.interpolate + ( + Field::null(), // Not used for distributed + recvRequests_, + recvBufs_, + defaultValues + ).ptr() + ); + auto& patchNeighbourField = patchNeighbourFieldPtr_.ref(); + + if (doTransform()) + { + // In-place transform + transform(patchNeighbourField, forwardT(), patchNeighbourField); + } + } + + // Use patchNeighbourField() and patchInternalField() to obtain face value + coupledFvPatchField::evaluate(commsType); +} + + +template +void Foam::cyclicAMIFvPatchField::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 +{ + if (this->ownerAMI().distributed()) + { + // Start sending + if (commsType != UPstream::commsTypes::nonBlocking) + { + FatalErrorInFunction + << "Can only evaluate distributed AMI with nonBlocking" + << exit(FatalError); + } + + const labelUList& nbrFaceCells = + lduAddr.patchAddr(cyclicAMIPatch_.neighbPatchID()); + + solveScalarField pnf(psiInternal, nbrFaceCells); + + // Transform according to the transformation tensors + transformCoupleField(pnf, cmpt); + + const cyclicAMIPolyPatch& cpp = cyclicAMIPatch_.cyclicAMIPatch(); + + cpp.initInterpolate + ( + pnf, + sendRequests_, + scalarSendBufs_, + recvRequests_, + scalarRecvBufs_ + ); + } +} + + template void Foam::cyclicAMIFvPatchField::updateInterfaceMatrix ( @@ -204,27 +497,63 @@ void Foam::cyclicAMIFvPatchField::updateInterfaceMatrix const solveScalarField& psiInternal, const scalarField& coeffs, const direction cmpt, - const Pstream::commsTypes + const Pstream::commsTypes commsType ) const { - const labelUList& nbrFaceCells = - lduAddr.patchAddr(cyclicAMIPatch_.neighbPatchID()); - - solveScalarField pnf(psiInternal, nbrFaceCells); - const labelUList& faceCells = lduAddr.patchAddr(patchId); - // Transform according to the transformation tensors - transformCoupleField(pnf, cmpt); + const auto& AMI = + ( + cyclicAMIPatch_.owner() + ? cyclicAMIPatch_.AMI() + : cyclicAMIPatch_.neighbPatch().AMI() + ); - if (cyclicAMIPatch_.applyLowWeightCorrection()) + solveScalarField pnf; + + if (this->ownerAMI().distributed()) { - solveScalarField pif(psiInternal, faceCells); - pnf = cyclicAMIPatch_.interpolate(pnf, pif); + if (commsType != UPstream::commsTypes::nonBlocking) + { + FatalErrorInFunction + << "Can only evaluate distributed AMI with nonBlocking" + << exit(FatalError); + } + + solveScalarField defaultValues; + if (AMI.applyLowWeightCorrection()) + { + defaultValues = solveScalarField(psiInternal, faceCells); + } + + const cyclicAMIPolyPatch& cpp = cyclicAMIPatch_.cyclicAMIPatch(); + + pnf = + cpp.interpolate + ( + solveScalarField::null(), // Not used for distributed + recvRequests_, + scalarRecvBufs_, + defaultValues + ); } else { - pnf = cyclicAMIPatch_.interpolate(pnf); + solveScalarField defaultValues; + if (cyclicAMIPatch_.applyLowWeightCorrection()) + { + defaultValues = solveScalarField(psiInternal, faceCells); + } + + const labelUList& nbrFaceCells = + lduAddr.patchAddr(cyclicAMIPatch_.neighbPatchID()); + + pnf = solveScalarField(psiInternal, nbrFaceCells); + + // Transform according to the transformation tensors + transformCoupleField(pnf, cmpt); + + pnf = cyclicAMIPatch_.interpolate(pnf, defaultValues); } // Multiply the field by coefficients and add into the result @@ -232,6 +561,51 @@ void Foam::cyclicAMIFvPatchField::updateInterfaceMatrix } +template +void Foam::cyclicAMIFvPatchField::initInterfaceMatrixUpdate +( + Field& result, + const bool add, + const lduAddressing& lduAddr, + const label patchId, + const Field& psiInternal, + const scalarField& coeffs, + const Pstream::commsTypes commsType +) const +{ + const auto& AMI = this->ownerAMI(); + + if (AMI.distributed()) + { + if (commsType != UPstream::commsTypes::nonBlocking) + { + FatalErrorInFunction + << "Can only evaluate distributed AMI with nonBlocking" + << exit(FatalError); + } + + const labelUList& nbrFaceCells = + lduAddr.patchAddr(cyclicAMIPatch_.neighbPatchID()); + + Field pnf(psiInternal, nbrFaceCells); + + // Transform according to the transformation tensors + transformCoupleField(pnf); + + const cyclicAMIPolyPatch& cpp = cyclicAMIPatch_.cyclicAMIPatch(); + + cpp.initInterpolate + ( + pnf, + sendRequests_, + sendBufs_, + recvRequests_, + recvBufs_ + ); + } +} + + template void Foam::cyclicAMIFvPatchField::updateInterfaceMatrix ( @@ -241,28 +615,59 @@ void Foam::cyclicAMIFvPatchField::updateInterfaceMatrix const label patchId, const Field& psiInternal, const scalarField& coeffs, - const Pstream::commsTypes + const Pstream::commsTypes commsType ) const { - const labelUList& nbrFaceCells = - lduAddr.patchAddr(cyclicAMIPatch_.neighbPatchID()); + const labelUList& faceCells = lduAddr.patchAddr(patchId); - Field pnf(psiInternal, nbrFaceCells); + const auto& AMI = this->ownerAMI(); - // Transform according to the transformation tensors - transformCoupleField(pnf); + Field pnf; - if (cyclicAMIPatch_.applyLowWeightCorrection()) + if (AMI.distributed()) { - Field pif(psiInternal, cyclicAMIPatch_.faceCells()); - pnf = cyclicAMIPatch_.interpolate(pnf, pif); + if (commsType != UPstream::commsTypes::nonBlocking) + { + FatalErrorInFunction + << "Can only evaluate distributed AMI with nonBlocking" + << exit(FatalError); + } + + const cyclicAMIPolyPatch& cpp = cyclicAMIPatch_.cyclicAMIPatch(); + + Field defaultValues; + if (AMI.applyLowWeightCorrection()) + { + defaultValues = Field(psiInternal, faceCells); + } + + pnf = + cpp.interpolate + ( + Field::null(), // Not used for distributed + recvRequests_, + recvBufs_, + defaultValues + ); } else { - pnf = cyclicAMIPatch_.interpolate(pnf); - } + const labelUList& nbrFaceCells = + lduAddr.patchAddr(cyclicAMIPatch_.neighbPatchID()); - const labelUList& faceCells = lduAddr.patchAddr(patchId); + Field pnf(psiInternal, nbrFaceCells); + + // Transform according to the transformation tensors + transformCoupleField(pnf); + + Field defaultValues; + if (cyclicAMIPatch_.applyLowWeightCorrection()) + { + defaultValues = Field(psiInternal, faceCells); + } + + pnf = cyclicAMIPatch_.interpolate(pnf, defaultValues); + } // Multiply the field by coefficients and add into the result this->addToInternalField(result, !add, faceCells, coeffs, pnf); @@ -277,10 +682,9 @@ void Foam::cyclicAMIFvPatchField::manipulateMatrix const direction cmpt ) { - if (this->cyclicAMIPatch().owner()) { - label index = this->patch().index(); + const label index = this->patch().index(); const label globalPatchID = matrix.lduMeshAssembly().patchLocalToGlobalMap()[mat][index]; @@ -376,7 +780,8 @@ Foam::cyclicAMIFvPatchField::coeffs matrix.lduMeshAssembly().cellBoundMap()[mat][index].size() ); - Field mapCoeffs(nSubFaces, Zero); + auto tmapCoeffs = tmp>::New(nSubFaces, Zero); + auto& mapCoeffs = tmapCoeffs.ref(); const scalarListList& srcWeight = cyclicAMIPatch_.cyclicAMIPatch().AMI().srcWeights(); @@ -394,7 +799,7 @@ Foam::cyclicAMIFvPatchField::coeffs } } - return tmp>(new Field(mapCoeffs)); + return tmapCoeffs; } @@ -408,7 +813,7 @@ void Foam::cyclicAMIFvPatchField::collectStencilData List& expandedData ) { - expandedData.setSize(stencil.size()); + expandedData.resize_nocopy(stencil.size()); if (mapPtr) { Type2 work(data); @@ -417,7 +822,7 @@ void Foam::cyclicAMIFvPatchField::collectStencilData forAll(stencil, facei) { const labelList& slots = stencil[facei]; - expandedData[facei].append + expandedData[facei].push_back ( UIndirectList(work, slots) ); @@ -428,7 +833,7 @@ void Foam::cyclicAMIFvPatchField::collectStencilData forAll(stencil, facei) { const labelList& slots = stencil[facei]; - expandedData[facei].append + expandedData[facei].push_back ( UIndirectList(data, slots) ); @@ -442,8 +847,12 @@ void Foam::cyclicAMIFvPatchField::write(Ostream& os) const { fvPatchField::write(os); fvPatchField::writeValueEntry(os); + + if (patchNeighbourFieldPtr_) + { + patchNeighbourFieldPtr_->writeEntry("neighbourValue", os); + } } // ************************************************************************* // - diff --git a/src/finiteVolume/fields/fvPatchFields/constraint/cyclicAMI/cyclicAMIFvPatchField.H b/src/finiteVolume/fields/fvPatchFields/constraint/cyclicAMI/cyclicAMIFvPatchField.H index 0a9e7e2bea..a843f3c175 100644 --- a/src/finiteVolume/fields/fvPatchFields/constraint/cyclicAMI/cyclicAMIFvPatchField.H +++ b/src/finiteVolume/fields/fvPatchFields/constraint/cyclicAMI/cyclicAMIFvPatchField.H @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2019 OpenCFD Ltd. + Copyright (C) 2019-2023 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -41,16 +41,24 @@ Usage { type cyclicAMI; + value ; + neighbourValue ; } \endverbatim Note The outer boundary of the patch pairs must be similar, i.e. if the owner - patch is transformed to the neighbour patch, the outer perimiter of each + patch is transformed to the neighbour patch, the outer perimeter of each patch should be identical (or very similar). + The \c neighbourValue is only needed when running distributed, + i.e. the neighbour cells are on a different processor from the owner cells. + It guarantees consistent restart e.g. when doing a snGrad and avoids + additional communication. + See also Foam::AMIInterpolation + Foam::processorFvPatchField SourceFiles cyclicAMIFvPatchField.C @@ -79,14 +87,55 @@ class cyclicAMIFvPatchField virtual public cyclicAMILduInterfaceField, public coupledFvPatchField { - // Private data + // Private Data //- Local reference cast into the cyclic patch const cyclicAMIFvPatch& cyclicAMIPatch_; + // Sending and receiving (distributed AMI) + + //- Current range of send requests (non-blocking) + mutable labelRange sendRequests_; + + //- Current range of recv requests (non-blocking) + mutable labelRange recvRequests_; + + //- Send buffers + mutable PtrList> sendBufs_; + + //- Receive buffers_ + mutable PtrList> recvBufs_; + + //- Scalar send buffers + mutable PtrList> scalarSendBufs_; + + //- Scalar receive buffers + mutable PtrList> scalarRecvBufs_; + + //- Neighbour coupled internal cell data + mutable autoPtr> patchNeighbourFieldPtr_; + + // Private Member Functions + //- Return the AMI corresponding to the owner side + const AMIPatchToPatchInterpolation& ownerAMI() const + { + return + ( + cyclicAMIPatch_.owner() + ? cyclicAMIPatch_.AMI() + : cyclicAMIPatch_.neighbPatch().AMI() + ); + } + + //- All receive/send requests have completed + virtual bool all_ready() const; + + //- Return neighbour coupled internal cell data + tmp> patchNeighbourField(const Field&) const; + //- Return neighbour side field given internal fields template tmp> neighbourSideField @@ -103,7 +152,6 @@ class cyclicAMIFvPatchField const label ) const; - template void collectStencilData ( @@ -178,28 +226,54 @@ public: } - // Member functions + // Member Functions - // Access - - //- Return local reference cast into the cyclic AMI patch - const cyclicAMIFvPatch& cyclicAMIPatch() const - { - return cyclicAMIPatch_; - } + //- Return local reference cast into the cyclic AMI patch + const cyclicAMIFvPatch& cyclicAMIPatch() const noexcept + { + return cyclicAMIPatch_; + } - // Evaluation functions + // Coupling - //- Return true if coupled. Note that the underlying patch - // is not coupled() - the points don't align. - virtual bool coupled() const; + //- Return true if coupled. Note that the underlying patch + // is not coupled() - the points don't align. + virtual bool coupled() const { return cyclicAMIPatch_.coupled(); } - //- Return neighbour coupled internal cell data - virtual tmp> patchNeighbourField() const; + //- Are all (receive) data available? + virtual bool ready() const; - //- Return reference to neighbour patchField - const cyclicAMIFvPatchField& neighbourPatchField() const; + //- Return neighbour coupled internal cell data + virtual tmp> patchNeighbourField() const; + + //- Return reference to neighbour patchField + const cyclicAMIFvPatchField& neighbourPatchField() const; + + + // Evaluation + + //- Initialise the evaluation of the patch field + virtual void initEvaluate(const Pstream::commsTypes commsType); + + //- Evaluate the patch field + virtual void evaluate(const Pstream::commsTypes commsType); + + + // Coupled interface functionality + + //- Initialise neighbour matrix update + 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; //- Update result field based on interface functionality virtual void updateInterfaceMatrix @@ -214,6 +288,18 @@ public: const Pstream::commsTypes commsType ) const; + //- Initialise neighbour matrix update + virtual void initInterfaceMatrixUpdate + ( + Field& result, + const bool add, + const lduAddressing& lduAddr, + const label patchId, + const Field& psiInternal, + const scalarField& coeffs, + const Pstream::commsTypes commsType + ) const; + //- Update result field based on interface functionality virtual void updateInterfaceMatrix ( @@ -236,7 +322,7 @@ public: ); - // Cyclic AMI coupled interface functions + // Coupled interface functions //- Does the patch field perform the transformation virtual bool doTransform() const diff --git a/src/finiteVolume/fields/fvPatchFields/constraint/cyclicAMI/cyclicAMIFvPatchFields.C b/src/finiteVolume/fields/fvPatchFields/constraint/cyclicAMI/cyclicAMIFvPatchFields.C index 7140ad6f24..bf86d3201b 100644 --- a/src/finiteVolume/fields/fvPatchFields/constraint/cyclicAMI/cyclicAMIFvPatchFields.C +++ b/src/finiteVolume/fields/fvPatchFields/constraint/cyclicAMI/cyclicAMIFvPatchFields.C @@ -26,8 +26,11 @@ License \*---------------------------------------------------------------------------*/ #include "cyclicAMIFvPatchFields.H" -#include "addToRunTimeSelectionTable.H" +#include "cyclicAMIPolyPatch.H" +#include "mapDistributeBase.H" +#include "AMIInterpolation.H" #include "volFields.H" +#include "addToRunTimeSelectionTable.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/src/finiteVolume/fields/fvPatchFields/constraint/cyclicAMI/cyclicAMIFvPatchFields.H b/src/finiteVolume/fields/fvPatchFields/constraint/cyclicAMI/cyclicAMIFvPatchFields.H index ab55a78298..4a1cd83713 100644 --- a/src/finiteVolume/fields/fvPatchFields/constraint/cyclicAMI/cyclicAMIFvPatchFields.H +++ b/src/finiteVolume/fields/fvPatchFields/constraint/cyclicAMI/cyclicAMIFvPatchFields.H @@ -25,8 +25,8 @@ License \*---------------------------------------------------------------------------*/ -#ifndef cyclicAMIFvPatchFields_H -#define cyclicAMIFvPatchFields_H +#ifndef Foam_cyclicAMIFvPatchFields_H +#define Foam_cyclicAMIFvPatchFields_H #include "cyclicAMIFvPatchField.H" #include "fieldTypes.H" diff --git a/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.C b/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.C index 7f8588a57a..d1e15a0b50 100644 --- a/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.C +++ b/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.C @@ -762,25 +762,27 @@ bool Foam::AMIInterpolation::calculate if (srcTotalSize == 0) { - DebugInfo<< "AMI: no source faces present - no addressing constructed" + DebugInfo + << "AMI: no source faces present - no addressing constructed" << endl; return false; } - Info<< indent - << "AMI: Patch source faces: " << srcTotalSize << nl - << "AMI: Patch target faces: " << tgtTotalSize << endl; - singlePatchProc_ = calcDistribution(srcPatch, tgtPatch); - if (debug) + Info<< indent << "AMI: Patch source faces: " << srcTotalSize << nl + << indent << "AMI: Patch target faces: " << tgtTotalSize << nl; + + if (distributed()) { - Info<< "AMIInterpolation:" << nl - << " singlePatchProc:" << singlePatchProc_ << nl - << endl; + Info<< indent << "AMI: distributed" << endl; } + DebugInfo + << "AMI: patch proc:" << singlePatchProc_ + << endl; + return true; } diff --git a/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.H b/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.H index 54fc75c676..666492ad38 100644 --- a/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.H +++ b/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.H @@ -506,6 +506,30 @@ public: // Low-level + //- Weighted sum of contributions + template + static void weightedSum + ( + const scalar lowWeightCorrection, + const labelListList& allSlots, + const scalarListList& allWeights, + const scalarField& weightsSum, + const UList& fld, + const CombineOp& cop, + List& result, + const UList& defaultValues + ); + + //- Weighted sum of contributions + template + void weightedSum + ( + const bool interpolateToSource, + const UList& fld, + List& result, + const UList& defaultValues + ) const; + //- Interpolate from target to source with supplied op //- to combine existing value with remote value and weight template diff --git a/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolationTemplates.C b/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolationTemplates.C index 418bf48cc8..535b35ca56 100644 --- a/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolationTemplates.C +++ b/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolationTemplates.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2017 OpenFOAM Foundation - Copyright (C) 2015-2018 OpenCFD Ltd. + Copyright (C) 2015-2023 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -31,6 +31,78 @@ License // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // +template +void Foam::AMIInterpolation::weightedSum +( + const scalar lowWeightCorrection, + const labelListList& allSlots, + const scalarListList& allWeights, + const scalarField& weightsSum, + const UList& fld, + const CombineOp& cop, + List& result, + const UList& defaultValues +) +{ + if (lowWeightCorrection > 0) + { + forAll(result, facei) + { + if (weightsSum[facei] < lowWeightCorrection) + { + result[facei] = defaultValues[facei]; + } + else + { + const labelList& slots = allSlots[facei]; + const scalarList& weights = allWeights[facei]; + + forAll(slots, i) + { + cop(result[facei], facei, fld[slots[i]], weights[i]); + } + } + } + } + else + { + forAll(result, facei) + { + const labelList& slots = allSlots[facei]; + const scalarList& weights = allWeights[facei]; + + forAll(slots, i) + { + cop(result[facei], facei, fld[slots[i]], weights[i]); + } + } + } +} + + +template +void Foam::AMIInterpolation::weightedSum +( + const bool interpolateToSource, + const UList& fld, + List& result, + const UList& defaultValues +) const +{ + weightedSum + ( + lowWeightCorrection_, + (interpolateToSource ? srcAddress_ : tgtAddress_), + (interpolateToSource ? srcWeights_ : tgtWeights_), + (interpolateToSource ? srcWeightsSum_ : tgtWeightsSum_), + fld, + multiplyWeightedOp>(plusEqOp()), + result, + defaultValues + ); +} + + template void Foam::AMIInterpolation::interpolateToTarget ( @@ -51,69 +123,43 @@ void Foam::AMIInterpolation::interpolateToTarget << " supplied field = " << fld.size() << abort(FatalError); } - - if (lowWeightCorrection_ > 0) + else if + ( + (lowWeightCorrection_ > 0) + && (defaultValues.size() != tgtAddress_.size()) + ) { - if (defaultValues.size() != tgtAddress_.size()) - { - FatalErrorInFunction - << "Employing default values when sum of weights falls below " - << lowWeightCorrection_ - << " but supplied default field size is not equal to target " - << "patch size" << nl - << " default values = " << defaultValues.size() << nl - << " target patch = " << tgtAddress_.size() << nl - << abort(FatalError); - } + FatalErrorInFunction + << "Employing default values when sum of weights falls below " + << lowWeightCorrection_ + << " but supplied default field size is not equal to target " + << "patch size" << nl + << " default values = " << defaultValues.size() << nl + << " target patch = " << tgtAddress_.size() << nl + << abort(FatalError); } result.setSize(tgtAddress_.size()); + List work; if (distributed()) { const mapDistribute& map = srcMapPtr_(); - - List work(fld); + work = fld; // deep copy map.distribute(work); - - forAll(result, facei) - { - if (tgtWeightsSum_[facei] < lowWeightCorrection_) - { - result[facei] = defaultValues[facei]; - } - else - { - const labelList& faces = tgtAddress_[facei]; - const scalarList& weights = tgtWeights_[facei]; - - forAll(faces, i) - { - cop(result[facei], facei, work[faces[i]], weights[i]); - } - } - } } - else - { - forAll(result, facei) - { - if (tgtWeightsSum_[facei] < lowWeightCorrection_) - { - result[facei] = defaultValues[facei]; - } - else - { - const labelList& faces = tgtAddress_[facei]; - const scalarList& weights = tgtWeights_[facei]; - forAll(faces, i) - { - cop(result[facei], facei, fld[faces[i]], weights[i]); - } - } - } - } + weightedSum + ( + lowWeightCorrection_, + tgtAddress_, + tgtWeights_, + tgtWeightsSum_, + (distributed() ? work : fld), + cop, + result, + defaultValues + ); } @@ -137,69 +183,43 @@ void Foam::AMIInterpolation::interpolateToSource << " supplied field = " << fld.size() << abort(FatalError); } - - if (lowWeightCorrection_ > 0) + else if + ( + (lowWeightCorrection_ > 0) + && (defaultValues.size() != srcAddress_.size()) + ) { - if (defaultValues.size() != srcAddress_.size()) - { - FatalErrorInFunction - << "Employing default values when sum of weights falls below " - << lowWeightCorrection_ - << " but supplied default field size is not equal to source " - << "patch size" << nl - << " default values = " << defaultValues.size() << nl - << " source patch = " << srcAddress_.size() << nl - << abort(FatalError); - } + FatalErrorInFunction + << "Employing default values when sum of weights falls below " + << lowWeightCorrection_ + << " but number of default values is not equal to source " + << "patch size" << nl + << " default values = " << defaultValues.size() << nl + << " source patch = " << srcAddress_.size() << nl + << abort(FatalError); } result.setSize(srcAddress_.size()); + List work; if (distributed()) { const mapDistribute& map = tgtMapPtr_(); - - List work(fld); + work = fld; // deep copy map.distribute(work); - - forAll(result, facei) - { - if (srcWeightsSum_[facei] < lowWeightCorrection_) - { - result[facei] = defaultValues[facei]; - } - else - { - const labelList& faces = srcAddress_[facei]; - const scalarList& weights = srcWeights_[facei]; - - forAll(faces, i) - { - cop(result[facei], facei, work[faces[i]], weights[i]); - } - } - } } - else - { - forAll(result, facei) - { - if (srcWeightsSum_[facei] < lowWeightCorrection_) - { - result[facei] = defaultValues[facei]; - } - else - { - const labelList& faces = srcAddress_[facei]; - const scalarList& weights = srcWeights_[facei]; - forAll(faces, i) - { - cop(result[facei], facei, fld[faces[i]], weights[i]); - } - } - } - } + weightedSum + ( + lowWeightCorrection_, + srcAddress_, + srcWeights_, + srcWeightsSum_, + (distributed() ? work : fld), + cop, + result, + defaultValues + ); } diff --git a/src/meshTools/AMIInterpolation/patches/cyclicAMI/cyclicAMIPolyPatch/cyclicAMIPolyPatch.C b/src/meshTools/AMIInterpolation/patches/cyclicAMI/cyclicAMIPolyPatch/cyclicAMIPolyPatch.C index 226cf694b9..1c0268b575 100644 --- a/src/meshTools/AMIInterpolation/patches/cyclicAMI/cyclicAMIPolyPatch/cyclicAMIPolyPatch.C +++ b/src/meshTools/AMIInterpolation/patches/cyclicAMI/cyclicAMIPolyPatch/cyclicAMIPolyPatch.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2016-2021 OpenCFD Ltd. + Copyright (C) 2016-2023 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -294,30 +294,29 @@ Foam::cyclicAMIPolyPatch::cylindricalCS() const if (periodicID != -1) { // Get the periodic patch - const coupledPolyPatch& perPp - ( - refCast - ( - boundaryMesh()[periodicID] - ) - ); + const coupledPolyPatch& perPp = + refCast(boundaryMesh()[periodicID]); + if (!perPp.parallel()) { vector axis(Zero); point axisPoint(Zero); - if (isA(perPp)) + + if + ( + const cyclicPolyPatch* cpp = isA(perPp) + ) { - axis = - refCast(perPp).rotationAxis(); - axisPoint = - refCast(perPp).rotationCentre(); + axis = cpp->rotationAxis(); + axisPoint = cpp->rotationCentre(); } - else if (isA(perPp)) + else if + ( + const cyclicAMIPolyPatch* cpp = isA(perPp) + ) { - axis = - refCast(perPp).rotationAxis(); - axisPoint = - refCast(perPp).rotationCentre(); + axis = cpp->rotationAxis(); + axisPoint = cpp->rotationCentre(); } else { diff --git a/src/meshTools/AMIInterpolation/patches/cyclicAMI/cyclicAMIPolyPatch/cyclicAMIPolyPatch.H b/src/meshTools/AMIInterpolation/patches/cyclicAMI/cyclicAMIPolyPatch/cyclicAMIPolyPatch.H index 9c19f0b15d..094ee1bff5 100644 --- a/src/meshTools/AMIInterpolation/patches/cyclicAMI/cyclicAMIPolyPatch/cyclicAMIPolyPatch.H +++ b/src/meshTools/AMIInterpolation/patches/cyclicAMI/cyclicAMIPolyPatch/cyclicAMIPolyPatch.H @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2018-2021 OpenCFD Ltd. + Copyright (C) 2018-2023 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -47,9 +47,10 @@ SourceFiles \*---------------------------------------------------------------------------*/ -#ifndef cyclicAMIPolyPatch_H -#define cyclicAMIPolyPatch_H +#ifndef Foam_cyclicAMIPolyPatch_H +#define Foam_cyclicAMIPolyPatch_H +#include "AMIInterpolation.H" #include "coupledPolyPatch.H" #include "AMIPatchToPatchInterpolation.H" #include "polyBoundaryMesh.H" @@ -87,7 +88,7 @@ class cyclicAMIPolyPatch protected: - // Protected data + // Protected Data //- Name of other half mutable word nbrPatchName_; @@ -286,7 +287,7 @@ public: } //- Construct and return a clone, resetting the face list - // and boundary mesh + //- and boundary mesh virtual autoPtr clone ( const polyBoundaryMesh& bm, @@ -467,7 +468,7 @@ public: ) const; //- Transform a patch-based direction from this side to - // nbr side + //- nbr side virtual void reverseTransformDirection ( vector& d, @@ -512,6 +513,38 @@ public: ) const; + // Interpolations (non-blocking). Subject to change + + template + void initInterpolateUntransformed + ( + const Field& fld, + labelRange& sendRequests, + PtrList>& sendBuffers, + labelRange& recvRequests, + PtrList>& recvBuffers + ) const; + + template + void initInterpolate + ( + const Field& fld, + labelRange& sendRequests, + PtrList>& sendBuffers, + labelRange& recvRequests, + PtrList>& recvBuffers + ) const; + + template + tmp> interpolate + ( + const Field& localFld, + const labelRange& requests, // The receive requests + const PtrList>& recvBuffers, + const UList& defaultValues + ) const; + + //- Calculate the patch geometry virtual void calcGeometry ( diff --git a/src/meshTools/AMIInterpolation/patches/cyclicAMI/cyclicAMIPolyPatch/cyclicAMIPolyPatchTemplates.C b/src/meshTools/AMIInterpolation/patches/cyclicAMI/cyclicAMIPolyPatch/cyclicAMIPolyPatchTemplates.C index ca7282c03a..636c77f01a 100644 --- a/src/meshTools/AMIInterpolation/patches/cyclicAMI/cyclicAMIPolyPatch/cyclicAMIPolyPatchTemplates.C +++ b/src/meshTools/AMIInterpolation/patches/cyclicAMI/cyclicAMIPolyPatch/cyclicAMIPolyPatchTemplates.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2021 OpenCFD Ltd. + Copyright (C) 2021-2023 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -53,96 +53,96 @@ Foam::tmp> Foam::cyclicAMIPolyPatch::interpolate const UList& defaultValues ) const { - if (pTraits::rank == 0) + autoPtr cs; + + // Similar to doTransform. + // - could also check if !std::is_same:value + + if (is_vectorspace::value) + { + cs.reset(cylindricalCS()); + } + + if (!cs) { return interpolateUntransformed(fld, defaultValues); } else { - autoPtr cs(cylindricalCS()); - if (!cs) - { - return interpolateUntransformed(fld, defaultValues); - } - else - { - const cyclicAMIPolyPatch& nbrPp = this->neighbPatch(); + const cyclicAMIPolyPatch& nbrPp = this->neighbPatch(); - if (debug) + if (debug) + { + Pout<< "cyclicAMIPolyPatch::interpolate :" + << " patch:" << this->name() + << " size:" << this->size() + << " nbrPatch:" << nbrPp.name() + << " size:" << nbrPp.size() + << endl; + } + + if (fld.size() != nbrPp.size()) + { + FatalErrorInFunction + << "Patch:" << this->name() + << " size:" << this->size() + << " neighbour patch:" << nbrPp.name() + << " size:" << nbrPp.size() + << " fld size:" << fld.size() + << exit(FatalError); + } + + + Field localFld(fld.size()); + + // Transform to cylindrical coords + { + const tensorField nbrT(cs().R(nbrPp.faceCentres())); + Foam::invTransform(localFld, nbrT, fld); + } + + if (debug&2) + { + const vectorField::subField nbrFc(nbrPp.faceCentres()); + + Pout<< "On patch:" << this->name() + << " size:" << this->size() + << " fc:" << gAverage(this->faceCentres()) + << " getting remote data from:" << nbrPp.name() + << " size:" << nbrPp.size() + << " fc:" << gAverage(nbrFc) + << endl; + + forAll(fld, i) { - Pout<< "cyclicAMIPolyPatch::interpolate :" - << " patch:" << this->name() - << " size:" << this->size() - << " nbrPatch:" << nbrPp.name() - << " size:" << nbrPp.size() + Pout<< "At:" << nbrFc[i] << nl + << " cart:" << fld[i] << nl + << " cyli:" << localFld[i] << nl << endl; } - - if (fld.size() != nbrPp.size()) - { - FatalErrorInFunction - << "Patch:" << this->name() - << " size:" << this->size() - << " neighbour patch:" << nbrPp.name() - << " size:" << nbrPp.size() - << " fld size:" << fld.size() - << exit(FatalError); - } - - - auto tlocalFld(tmp>::New(fld.size())); - Field& localFld = tlocalFld.ref(); - - // Transform to cylindrical coords - { - tmp nbrT(cs().R(nbrPp.faceCentres())); - localFld = Foam::invTransform(nbrT(), fld); - } - - if (debug&2) - { - const vectorField::subField nbrFc(nbrPp.faceCentres()); - - Pout<< "On patch:" << this->name() - << " size:" << this->size() - << " fc:" << gAverage(this->faceCentres()) - << " getting remote data from:" << nbrPp.name() - << " size:" << nbrPp.size() - << " fc:" << gAverage(nbrFc) - << endl; - - forAll(fld, i) - { - Pout<< "At:" << nbrFc[i] << nl - << " cart:" << fld[i] << nl - << " cyli:" << localFld[i] << nl - << endl; - } - } - - - const tmp T(cs().R(this->faceCentres())); - - List localDeflt(defaultValues.size()); - if (defaultValues.size() == size()) - { - // Transform default values into cylindrical coords (using - // *this faceCentres) - // We get in UList (why? Copied from cyclicAMI). Convert to - // Field so we can use transformField routines. - const SubField defaultSubFld(defaultValues); - const Field& defaultFld(defaultSubFld); - localDeflt = Foam::invTransform(T(), defaultFld); - } - - // Do the actual interpolation and interpolate back to cartesian - // coords - return Foam::transform - ( - T, - interpolateUntransformed(localFld, localDeflt) - ); } + + + const tensorField ownT(cs().R(this->faceCentres())); + + Field localDeflt(defaultValues.size()); + if (defaultValues.size() == size()) + { + // Transform default values into cylindrical coords (using + // *this faceCentres) + // We get in UList (why? Copied from cyclicAMI). Convert to + // Field so we can use transformField routines. + const SubField defaultSubFld(defaultValues); + const Field& defaultFld(defaultSubFld); + Foam::invTransform(localDeflt, ownT, defaultFld); + } + + // Do the actual interpolation and interpolate back to cartesian + return Foam::transform + ( + ownT, + interpolateUntransformed(localFld, localDeflt) + ); } } @@ -158,6 +158,160 @@ Foam::tmp> Foam::cyclicAMIPolyPatch::interpolate } +template +void Foam::cyclicAMIPolyPatch::initInterpolateUntransformed +( + const Field& fld, + labelRange& sendRequests, + PtrList>& sendBuffers, + labelRange& recvRequests, + PtrList>& recvBuffers +) const +{ + const auto& AMI = (owner() ? this->AMI() : neighbPatch().AMI()); + + if (AMI.distributed()) + { + const auto& map = (owner() ? AMI.tgtMap() : AMI.srcMap()); + + // Insert send/receive requests (non-blocking) + map.send(fld, sendRequests, sendBuffers, recvRequests, recvBuffers); + } +} + + +template +void Foam::cyclicAMIPolyPatch::initInterpolate +( + const Field& fld, + labelRange& sendRequests, + PtrList>& sendBuffers, + labelRange& recvRequests, + PtrList>& recvBuffers +) const +{ + const auto& AMI = (owner() ? this->AMI() : neighbPatch().AMI()); + + if (!AMI.distributed()) + { + return; + } + + autoPtr cs; + + if (is_vectorspace::value) + { + cs.reset(cylindricalCS()); + } + + if (!cs) + { + initInterpolateUntransformed + ( + fld, + sendRequests, + sendBuffers, + recvRequests, + recvBuffers + ); + } + else + { + const cyclicAMIPolyPatch& nbrPp = this->neighbPatch(); + + Field localFld(fld.size()); + + // Transform to cylindrical coords + { + const tensorField nbrT(cs().R(nbrPp.faceCentres())); + Foam::invTransform(localFld, nbrT, fld); + } + + initInterpolateUntransformed + ( + localFld, + sendRequests, + sendBuffers, + recvRequests, + recvBuffers + ); + } +} + + +template +Foam::tmp> Foam::cyclicAMIPolyPatch::interpolate +( + const Field& localFld, + const labelRange& requests, + const PtrList>& recvBuffers, + const UList& defaultValues +) const +{ + const auto& AMI = (owner() ? this->AMI() : neighbPatch().AMI()); + const auto& map = (owner() ? AMI.tgtMap() : AMI.srcMap()); + + Field work; + if (AMI.distributed()) + { + // Receive (= copy) data from buffers into work. TBD: receive directly + // into slices of work. + map.receive(requests, recvBuffers, work); + } + const Field& fld = (AMI.distributed() ? work : localFld); + + auto tresult = tmp>::New(this->size(), Zero); + + // Note: tresult is optionally in transformed coord system + autoPtr cs; + + if (is_vectorspace::value) + { + cs.reset(cylindricalCS()); + } + + if (!cs) + { + AMI.weightedSum + ( + owner(), + fld, + tresult.ref(), + defaultValues + ); + } + else + { + const tensorField ownT(cs().R(this->faceCentres())); + + Field localDeflt(defaultValues.size()); + if (defaultValues.size() == size()) + { + // Transform default values into cylindrical coords (using + // *this faceCentres) + // We get in UList (why? Copied from cyclicAMI). Convert to + // Field so we can use transformField routines. + const SubField defaultSubFld(defaultValues); + const Field& defaultFld(defaultSubFld); + Foam::invTransform(localDeflt, ownT, defaultFld); + } + + AMI.weightedSum + ( + owner(), + fld, + tresult.ref(), + localDeflt + ); + + // Transform back + Foam::transform(tresult.ref(), ownT, tresult()); + } + + return tresult; +} + + template void Foam::cyclicAMIPolyPatch::interpolate ( @@ -168,26 +322,37 @@ void Foam::cyclicAMIPolyPatch::interpolate ) const { //- Commented out for now since called with non-primitives (e.g. wallPoint - // from FaceCellWave) - these are missing the pTraits::rank and - // Foam::transform + // from FaceCellWave) - missing Foam::transform, Foam::invTransform /* - autoPtr cs(cylindricalCS()); + autoPtr cs; - if (cs && pTraits::rank > 0) + if (is_vectorspace::value) + { + cs.reset(cylindricalCS()); + } + + if (cs) { const cyclicAMIPolyPatch& nbrPp = this->neighbPatch(); - tmp nbrT(cs().R(nbrPp.faceCentres())); - - result = Foam::invTransform(nbrT, result); - List localDeflt(defaultValues.size()); - if (defaultValues.size() == nbrT().size()) + // Transform to cylindrical coords { + const tensorField nbrT(cs().R(nbrPp.faceCentres())); + Foam::invTransform(result, nbrT, result); + } + + const tensorField ownT(cs().R(this->faceCentres())); + + Field localDeflt(defaultValues.size()); + if (defaultValues.size() == size()) + { + // Transform default values into cylindrical coords (using + // *this faceCentres) // We get in UList (why? Copied from cyclicAMI). Convert to // Field so we can use transformField routines. const SubField defaultSubFld(defaultValues); const Field& defaultFld(defaultSubFld); - localDeflt = Foam::invTransform(nbrT, defaultFld); + Foam::invTransform(localDeflt, ownT, defaultFld); } // Do actual AMI interpolation @@ -213,8 +378,7 @@ void Foam::cyclicAMIPolyPatch::interpolate } // Transform back. Result is now at *this - const vectorField::subField fc(this->faceCentres()); - result = Foam::transform(cs().R(fc), result); + Foam::transform(result, ownT, result); } else */ diff --git a/tutorials/basic/laplacianFoam/implicitAMI-nonblocking/0/T b/tutorials/basic/laplacianFoam/implicitAMI-nonblocking/0/T new file mode 100644 index 0000000000..d10f8c3da4 --- /dev/null +++ b/tutorials/basic/laplacianFoam/implicitAMI-nonblocking/0/T @@ -0,0 +1,93 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v2312 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object T; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 1 0 0 0]; + +internalField uniform 0; + +boundaryField +{ + cyclicAMI + { + type cyclicAMI; + value $internalField; + } + + // solid1 + solid1_top + { + type uniformFixedValue; + uniformValue 1; + } + solid1_left + { + type zeroGradient; + } + solid1_right + { + type zeroGradient; + } + + // solid2 + solid2_left + { + type zeroGradient; + } + solid2_right + { + type zeroGradient; + } + solid2_bottom + { + type uniformFixedValue; + uniformValue 0; + } + + + // solid1 + solid1_b_top + { + type uniformFixedValue; + uniformValue 1; + } + solid1_b_left + { + type zeroGradient; + } + solid1_b_right + { + type zeroGradient; + } + + + // solid2 + solid2_b_left + { + type zeroGradient; + } + solid2_b_right + { + type zeroGradient; + } + solid2_b_bottom + { + type uniformFixedValue; + uniformValue 0; + } +} + + +// ************************************************************************* // diff --git a/tutorials/basic/laplacianFoam/implicitAMI-nonblocking/Allrun b/tutorials/basic/laplacianFoam/implicitAMI-nonblocking/Allrun new file mode 100755 index 0000000000..d451c050a3 --- /dev/null +++ b/tutorials/basic/laplacianFoam/implicitAMI-nonblocking/Allrun @@ -0,0 +1,14 @@ +#!/bin/sh +cd "${0%/*}" || exit # Run from this directory +. ${WM_PROJECT_DIR:?}/bin/tools/RunFunctions # Tutorial run functions +#------------------------------------------------------------------------------ + +# restore0Dir + +runApplication blockMesh + +runApplication decomposePar + +runParallel $(getApplication) + +#------------------------------------------------------------------------------ diff --git a/tutorials/basic/laplacianFoam/implicitAMI-nonblocking/constant/transportProperties b/tutorials/basic/laplacianFoam/implicitAMI-nonblocking/constant/transportProperties new file mode 100644 index 0000000000..a882117301 --- /dev/null +++ b/tutorials/basic/laplacianFoam/implicitAMI-nonblocking/constant/transportProperties @@ -0,0 +1,21 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v2306 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant"; + object transportProperties; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +DT 4e-05; + + +// ************************************************************************* // diff --git a/tutorials/basic/laplacianFoam/implicitAMI-nonblocking/system/blockMeshDict b/tutorials/basic/laplacianFoam/implicitAMI-nonblocking/system/blockMeshDict new file mode 100644 index 0000000000..64cbb04640 --- /dev/null +++ b/tutorials/basic/laplacianFoam/implicitAMI-nonblocking/system/blockMeshDict @@ -0,0 +1,269 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v2312 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object blockMeshDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +scale 1; + +vertices +( + // solid1 + (-0.1 0.00 -0.05) + ( 0.1 0.00 -0.05) + ( 0.1 0.04 -0.05) + (-0.1 0.04 -0.05) + (-0.1 0.00 0.05) + ( 0.1 0.00 0.05) + ( 0.1 0.04 0.05) + (-0.1 0.04 0.05) + + + // solid2 + (-0.1 -0.04 -0.05) + ( 0.1 -0.04 -0.05) + ( 0.1 0.00 -0.05) + (-0.1 0.00 -0.05) + (-0.1 -0.04 0.05) + ( 0.1 -0.04 0.05) + ( 0.1 0.00 0.05) + (-0.1 0.00 0.05) + + // solid1_b + ( 0.2 0.00 -0.05) + ( 0.4 0.00 -0.05) + ( 0.4 0.04 -0.05) + ( 0.2 0.04 -0.05) + ( 0.2 0.00 0.05) + ( 0.4 0.00 0.05) + ( 0.4 0.04 0.05) + ( 0.2 0.04 0.05) + + + // solid2_b + ( 0.2 -0.04 -0.05) + ( 0.4 -0.04 -0.05) + ( 0.4 0.00 -0.05) + ( 0.2 0.00 -0.05) + ( 0.2 -0.04 0.05) + ( 0.4 -0.04 0.05) + ( 0.4 0.00 0.05) + ( 0.2 0.00 0.05) +); + +blocks +( + hex (0 1 2 3 4 5 6 7) solid1 (5 10 1) simpleGrading (1 1 1) + hex (8 9 10 11 12 13 14 15) solid2 (4 10 1) simpleGrading (1 1 1) + + hex (16 17 18 19 20 21 22 23) solid1_b (3 7 1) simpleGrading (1 1 1) + hex (24 25 26 27 28 29 30 31) solid2_b (7 7 1) simpleGrading (1 1 1) +); + +edges +( +); + +boundary +( + solid1_bottom + { + type cyclicAMI; + inGroups (coupleGroup); + coupleGroup coupleGroup; + faces + ( + (1 5 4 0) + ); + } + solid1_top + { + type wall; + faces + ( + (3 7 6 2) + ); + } + solid1_left + { + type wall; + faces + ( + (0 4 7 3) + ); + } + solid1_right + { + type wall; + faces + ( + (2 6 5 1) + ); + } + solid1_frontAndBack + { + type empty; + faces + ( + (0 3 2 1) + (4 5 6 7) + ); + } + + solid2_bottom + { + type wall; + faces + ( + (9 13 12 8) + ); + } + solid2_top + { + type cyclicAMI; + inGroups (coupleGroup); + coupleGroup coupleGroup; + + faces + ( + (11 15 14 10) + ); + } + solid2_left + { + type wall; + faces + ( + (8 12 15 11) + ); + } + solid2_right + { + type wall; + faces + ( + (10 14 13 9) + ); + } + + solid2_frontAndBack + { + type empty; + faces + ( + (8 11 10 9) + (12 13 14 15) + ); + } + + + // block b + // ~~~~~~~ + + solid1_b_bottom + { + type cyclicAMI; + inGroups (coupleGroup_b); + coupleGroup coupleGroup_b; + faces + ( + (17 21 20 16) + ); + } + solid1_b_top + { + type wall; + faces + ( + (19 23 22 18) + ); + } + solid1_b_left + { + type wall; + faces + ( + (16 20 23 19) + ); + } + solid1_b_right + { + type wall; + faces + ( + (18 22 21 17) + ); + } + solid1_b_frontAndBack + { + type empty; + faces + ( + (16 19 18 17) + (20 21 22 23) + ); + } + + solid2_b_bottom + { + type wall; + faces + ( + //(9 13 12 8) + (25 29 28 24) + ); + } + solid2_b_top + { + type cyclicAMI; + inGroups (coupleGroup_b); + coupleGroup coupleGroup_b; + + faces + ( + //(11 15 14 10) + (27 31 30 26) + ); + } + solid2_b_left + { + type wall; + faces + ( + //(8 12 15 11) + (24 28 31 27) + ); + } + solid2_b_right + { + type wall; + faces + ( + //(10 14 13 9) + (26 30 29 25) + ); + } + solid2_b_frontAndBack + { + type empty; + faces + ( + //(8 11 10 9) + (24 27 26 25) + //(12 13 14 15) + (28 29 30 31) + ); + } +); + +// ************************************************************************* // diff --git a/tutorials/basic/laplacianFoam/implicitAMI-nonblocking/system/controlDict b/tutorials/basic/laplacianFoam/implicitAMI-nonblocking/system/controlDict new file mode 100644 index 0000000000..78a1986794 --- /dev/null +++ b/tutorials/basic/laplacianFoam/implicitAMI-nonblocking/system/controlDict @@ -0,0 +1,50 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v2312 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object controlDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +application laplacianFoam; + +startFrom latestTime; + +startTime 0; + +stopAt endTime; + +endTime 2; + +deltaT 1; + +//writeControl runTime; +//writeInterval 0.1; +writeControl timeStep; +writeInterval 1; + +purgeWrite 0; + +writeFormat ascii; + +writePrecision 6; + +writeCompression off; + +timeFormat general; + +timePrecision 6; + +runTimeModifiable true; + + +// ************************************************************************* // diff --git a/tutorials/basic/laplacianFoam/implicitAMI-nonblocking/system/decomposeParDict b/tutorials/basic/laplacianFoam/implicitAMI-nonblocking/system/decomposeParDict new file mode 100644 index 0000000000..fa584aa1e0 --- /dev/null +++ b/tutorials/basic/laplacianFoam/implicitAMI-nonblocking/system/decomposeParDict @@ -0,0 +1,26 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v2312 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object decomposeParDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +//- The total number of domains (mandatory) +numberOfSubdomains 4; + +//- The decomposition method (mandatory) +method hierarchical; +n (4 1 1); + +// NOTE: no patch constraints! + +// ************************************************************************* // diff --git a/tutorials/basic/laplacianFoam/implicitAMI-nonblocking/system/fvSchemes b/tutorials/basic/laplacianFoam/implicitAMI-nonblocking/system/fvSchemes new file mode 100644 index 0000000000..6ca6eae217 --- /dev/null +++ b/tutorials/basic/laplacianFoam/implicitAMI-nonblocking/system/fvSchemes @@ -0,0 +1,52 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v2312 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object fvSchemes; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +ddtSchemes +{ + default steadyState; //Euler; +} + +gradSchemes +{ + default Gauss linear; + grad(T) Gauss linear; +} + +divSchemes +{ + default none; +} + +laplacianSchemes +{ + default none; + laplacian(DT,T) Gauss linear corrected; + laplacian(DTV,T) Gauss linear corrected; +} + +interpolationSchemes +{ + default linear; +} + +snGradSchemes +{ + default corrected; +} + + +// ************************************************************************* // diff --git a/tutorials/basic/laplacianFoam/implicitAMI-nonblocking/system/fvSolution b/tutorials/basic/laplacianFoam/implicitAMI-nonblocking/system/fvSolution new file mode 100644 index 0000000000..5f41211552 --- /dev/null +++ b/tutorials/basic/laplacianFoam/implicitAMI-nonblocking/system/fvSolution @@ -0,0 +1,35 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v2312 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object fvSolution; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +solvers +{ + T + { + solver PCG; + preconditioner DIC; + tolerance 1e-06; + relTol 0; + } +} + +SIMPLE +{ + nNonOrthogonalCorrectors 2; +} + + +// ************************************************************************* //