diff --git a/src/finiteVolume/fields/fvPatchFields/constraint/cyclicAMI/cyclicAMIFvPatchField.C b/src/finiteVolume/fields/fvPatchFields/constraint/cyclicAMI/cyclicAMIFvPatchField.C index 5642e9a36a..bb48eac3b0 100644 --- a/src/finiteVolume/fields/fvPatchFields/constraint/cyclicAMI/cyclicAMIFvPatchField.C +++ b/src/finiteVolume/fields/fvPatchFields/constraint/cyclicAMI/cyclicAMIFvPatchField.C @@ -143,7 +143,7 @@ Foam::cyclicAMIFvPatchField::patchNeighbourField() const { const Field& iField = this->internalField(); const labelUList& nbrFaceCells = - cyclicAMIPatch_.cyclicAMIPatch().nbrPatch().faceCells(); + cyclicAMIPatch_.cyclicAMIPatch().neighbPatch().faceCells(); Field pnf(iField, nbrFaceCells); @@ -187,7 +187,7 @@ void Foam::cyclicAMIFvPatchField::updateInterfaceMatrix ) const { const labelUList& nbrFaceCells = - cyclicAMIPatch_.cyclicAMIPatch().nbrPatch().faceCells(); + cyclicAMIPatch_.cyclicAMIPatch().neighbPatch().faceCells(); scalarField pnf(psiInternal, nbrFaceCells); diff --git a/src/finiteVolume/fvMesh/fvPatches/constraint/cyclicAMI/cyclicAMIFvPatch.H b/src/finiteVolume/fvMesh/fvPatches/constraint/cyclicAMI/cyclicAMIFvPatch.H index c53518fb23..02317e09a7 100644 --- a/src/finiteVolume/fvMesh/fvPatches/constraint/cyclicAMI/cyclicAMIFvPatch.H +++ b/src/finiteVolume/fvMesh/fvPatches/constraint/cyclicAMI/cyclicAMIFvPatch.H @@ -97,7 +97,7 @@ public: //- Return neighbour virtual label neighbPatchID() const { - return cyclicAMIPolyPatch_.nbrPatchID(); + return cyclicAMIPolyPatch_.neighbPatchID(); } virtual bool owner() const @@ -110,10 +110,16 @@ public: { return refCast ( - this->boundaryMesh()[cyclicAMIPolyPatch_.nbrPatchID()] + this->boundaryMesh()[cyclicAMIPolyPatch_.neighbPatchID()] ); } + //- Return a reference to the AMI interpolator + virtual const AMIPatchToPatchInterpolation& AMI() const + { + return cyclicAMIPolyPatch_.AMI(); + } + //- Are the cyclic planes parallel virtual bool parallel() const { @@ -136,7 +142,7 @@ public: { return refCast ( - this->boundaryMesh()[cyclicAMIPolyPatch_.nbrPatchID()] + this->boundaryMesh()[cyclicAMIPolyPatch_.neighbPatchID()] ); } diff --git a/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.C b/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.C index cfa3fa852b..083d622c04 100644 --- a/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.C +++ b/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.C @@ -120,7 +120,7 @@ void Foam::AMIInterpolation::checkPatches template -bool Foam::AMIInterpolation::distributed +Foam::label Foam::AMIInterpolation::calcDistribution ( const primitivePatch& srcPatch, const primitivePatch& tgtPatch @@ -140,13 +140,21 @@ bool Foam::AMIInterpolation::distributed Pstream::gatherList(facesPresentOnProc); Pstream::scatterList(facesPresentOnProc); - if (sum(facesPresentOnProc) > 1) + + label nHaveFaces = sum(facesPresentOnProc); + + if (nHaveFaces > 1) { - return true; + return -1; + } + else if (nHaveFaces == 1) + { + return findIndex(facesPresentOnProc, 1); } } - - return false; + + // Either not parallel or no faces on any processor + return 0; } @@ -1005,7 +1013,7 @@ void Foam::AMIInterpolation::calcAddressing template void Foam::AMIInterpolation::normaliseWeights ( - const primitivePatch& patch, + const scalarField& patchAreas, const word& patchName, const labelListList& addr, scalarListList& wght, @@ -1023,7 +1031,7 @@ void Foam::AMIInterpolation::normaliseWeights scalar s = sum(wght[faceI]); wghtSum[faceI] = s; - scalar t = s/patch[faceI].mag(patch.points()); + scalar t = s/patchAreas[faceI]; if (t < minBound) { minBound = t; @@ -1049,6 +1057,266 @@ void Foam::AMIInterpolation::normaliseWeights } +template +void Foam::AMIInterpolation::agglomerate +( + const autoPtr& targetMapPtr, + const scalarField& fineSrcMagSf, + const labelListList& fineSrcAddress, + const scalarListList& fineSrcWeights, + + const labelList& sourceRestrictAddressing, + const labelList& targetRestrictAddressing, + + scalarField& srcMagSf, + labelListList& srcAddress, + scalarListList& srcWeights, + autoPtr& tgtMap +) +{ + label sourceCoarseSize = + ( + sourceRestrictAddressing.size() + ? max(sourceRestrictAddressing)+1 + : 0 + ); + + label targetCoarseSize = + ( + targetRestrictAddressing.size() + ? max(targetRestrictAddressing)+1 + : 0 + ); + + // Agglomerate face areas + { + srcMagSf.setSize(sourceRestrictAddressing.size(), 0.0); + forAll(sourceRestrictAddressing, faceI) + { + label coarseFaceI = sourceRestrictAddressing[faceI]; + srcMagSf[coarseFaceI] += fineSrcMagSf[faceI]; + } + } + + + // Agglomerate weights and indices + if (targetMapPtr.valid()) + { + const mapDistribute& map = targetMapPtr(); + + // Get all restriction addressing. + labelList allRestrict(targetRestrictAddressing); + map.distribute(allRestrict); + + // So now we have agglomeration of the target side in + // allRestrict: + // 0..size-1 : local agglomeration (= targetRestrictAddressing) + // size.. : agglomeration data from other processors + + labelListList tgtSubMap(Pstream::nProcs()); + + // Local subMap is just identity + { + tgtSubMap[Pstream::myProcNo()] = identity(targetCoarseSize); + } + + forAll(map.subMap(), procI) + { + if (procI != Pstream::myProcNo()) + { + // Combine entries that point to the same coarse element. All + // the elements refer to local data so index into + // targetRestrictAddressing or allRestrict (since the same + // for local data). + const labelList& elems = map.subMap()[procI]; + labelList& newSubMap = tgtSubMap[procI]; + newSubMap.setSize(elems.size()); + + labelList oldToNew(targetCoarseSize, -1); + label newI = 0; + + forAll(elems, i) + { + label fineElem = elems[i]; + label coarseElem = allRestrict[fineElem]; + if (oldToNew[coarseElem] == -1) + { + oldToNew[coarseElem] = newI; + newSubMap[newI] = coarseElem; + newI++; + } + } + newSubMap.setSize(newI); + } + } + + // Reconstruct constructMap by combining entries. Note that order + // of handing out indices should be the same as loop above to compact + // the sending map + + labelListList tgtConstructMap(Pstream::nProcs()); + labelList tgtCompactMap; + + // Local constructMap is just identity + { + tgtConstructMap[Pstream::myProcNo()] = + identity(targetCoarseSize); + + tgtCompactMap = targetRestrictAddressing; + } + tgtCompactMap.setSize(map.constructSize()); + label compactI = targetCoarseSize; + + // Compact data from other processors + forAll(map.constructMap(), procI) + { + if (procI != Pstream::myProcNo()) + { + // Combine entries that point to the same coarse element. All + // elements now are remote data so we cannot use any local + // data here - use allRestrict instead. + const labelList& elems = map.constructMap()[procI]; + + labelList& newConstructMap = tgtConstructMap[procI]; + newConstructMap.setSize(elems.size()); + + if (elems.size()) + { + // Get the maximum target coarse size for this set of + // received data. + label remoteTargetCoarseSize = labelMin; + forAll(elems, i) + { + remoteTargetCoarseSize = max + ( + remoteTargetCoarseSize, + allRestrict[elems[i]] + ); + } + remoteTargetCoarseSize += 1; + + // Combine locally data coming from procI + labelList oldToNew(remoteTargetCoarseSize, -1); + label newI = 0; + + forAll(elems, i) + { + label fineElem = elems[i]; + // fineElem now points to section from procI + label coarseElem = allRestrict[fineElem]; + if (oldToNew[coarseElem] == -1) + { + oldToNew[coarseElem] = newI; + tgtCompactMap[fineElem] = compactI; + newConstructMap[newI] = compactI++; + newI++; + } + else + { + // Get compact index + label compactI = oldToNew[coarseElem]; + tgtCompactMap[fineElem] = newConstructMap[compactI]; + } + } + newConstructMap.setSize(newI); + } + } + } + + + srcAddress.setSize(sourceCoarseSize); + srcWeights.setSize(sourceCoarseSize); + + forAll(fineSrcAddress, faceI) + { + // All the elements contributing to faceI. Are slots in + // mapDistribute'd data. + const labelList& elems = fineSrcAddress[faceI]; + const scalarList& weights = fineSrcWeights[faceI]; + const scalar fineArea = fineSrcMagSf[faceI]; + + label coarseFaceI = sourceRestrictAddressing[faceI]; + + labelList& newElems = srcAddress[coarseFaceI]; + scalarList& newWeights = srcWeights[coarseFaceI]; + + forAll(elems, i) + { + label elemI = elems[i]; + label coarseElemI = tgtCompactMap[elemI]; + + label index = findIndex(newElems, coarseElemI); + if (index == -1) + { + newElems.append(coarseElemI); + newWeights.append(fineArea*weights[i]); + } + else + { + newWeights[index] += fineArea*weights[i]; + } + } + } + + tgtMap.reset + ( + new mapDistribute + ( + compactI, + tgtSubMap.xfer(), + tgtConstructMap.xfer() + ) + ); + } + else + { + srcAddress.setSize(sourceCoarseSize); + srcWeights.setSize(sourceCoarseSize); + + forAll(fineSrcAddress, faceI) + { + // All the elements contributing to faceI. Are slots in + // mapDistribute'd data. + const labelList& elems = fineSrcAddress[faceI]; + const scalarList& weights = fineSrcWeights[faceI]; + const scalar fineArea = fineSrcMagSf[faceI]; + + label coarseFaceI = sourceRestrictAddressing[faceI]; + + labelList& newElems = srcAddress[coarseFaceI]; + scalarList& newWeights = srcWeights[coarseFaceI]; + + forAll(elems, i) + { + label elemI = elems[i]; + label coarseElemI = targetRestrictAddressing[elemI]; + + label index = findIndex(newElems, coarseElemI); + if (index == -1) + { + newElems.append(coarseElemI); + newWeights.append(fineArea*weights[i]); + } + else + { + newWeights[index] += fineArea*weights[i]; + } + } + } + } + + // weights normalisation + normaliseWeights + ( + srcMagSf, + "source", + srcAddress, + srcWeights, + true + ); +} + + // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // template @@ -1059,6 +1327,7 @@ Foam::AMIInterpolation::AMIInterpolation const faceAreaIntersect::triangulationMode& triMode ) : + singlePatchProc_(-999), srcAddress_(), srcWeights_(), tgtAddress_(), @@ -1088,6 +1357,7 @@ Foam::AMIInterpolation::AMIInterpolation const faceAreaIntersect::triangulationMode& triMode ) : + singlePatchProc_(-999), srcAddress_(), srcWeights_(), tgtAddress_(), @@ -1165,6 +1435,127 @@ Foam::AMIInterpolation::AMIInterpolation } +template +Foam::AMIInterpolation::AMIInterpolation +( + const AMIInterpolation& fineAMI, + const labelList& sourceRestrictAddressing, + const labelList& targetRestrictAddressing +) +: + singlePatchProc_(fineAMI.singlePatchProc_), + srcAddress_(), + srcWeights_(), + tgtAddress_(), + tgtWeights_(), + startSeedI_(0), + triMode_(fineAMI.triMode_), + srcMapPtr_(NULL), + tgtMapPtr_(NULL) +{ + label sourceCoarseSize = + ( + sourceRestrictAddressing.size() + ? max(sourceRestrictAddressing)+1 + : 0 + ); + + label neighbourCoarseSize = + ( + targetRestrictAddressing.size() + ? max(targetRestrictAddressing)+1 + : 0 + ); + + if (debug & 2) + { + Pout<< "AMI: Creating addressing and weights as agglomeration of AMI :" + << " source:" << fineAMI.srcAddress().size() + << " target:" << fineAMI.tgtAddress().size() + << " coarse source size:" << sourceCoarseSize + << " neighbour source size:" << neighbourCoarseSize + << endl; + } + + if + ( + fineAMI.srcAddress().size() != sourceRestrictAddressing.size() + || fineAMI.tgtAddress().size() != targetRestrictAddressing.size() + ) + { + FatalErrorIn + ( + "AMIInterpolation::AMIInterpolation\n" + "(\n" + " const AMIInterpolation&,\n" + " const label,\n" + " const labelList&\n" + ")" + ) << "Size mismatch." << nl + << "Source patch size:" << fineAMI.srcAddress().size() << nl + << "Source agglomeration size:" + << sourceRestrictAddressing.size() << nl + << "Target patch size:" << fineAMI.tgtAddress().size() << nl + << "Target agglomeration size:" + << targetRestrictAddressing.size() + << exit(FatalError); + } + + + // Agglomerate addresses and weights + + agglomerate + ( + fineAMI.tgtMapPtr_, + fineAMI.srcMagSf(), + fineAMI.srcAddress(), + fineAMI.srcWeights(), + + sourceRestrictAddressing, + targetRestrictAddressing, + + srcMagSf_, + srcAddress_, + srcWeights_, + tgtMapPtr_ + ); + + //if (tgtMapPtr_.valid()) + //{ + // Pout<< "tgtMap:" << endl; + // string oldPrefix = Pout.prefix(); + // Pout.prefix() = oldPrefix + " "; + // tgtMapPtr_().printLayout(Pout); + // Pout.prefix() = oldPrefix; + //} + + agglomerate + ( + fineAMI.srcMapPtr_, + fineAMI.tgtMagSf(), + fineAMI.tgtAddress(), + fineAMI.tgtWeights(), + + targetRestrictAddressing, + sourceRestrictAddressing, + + tgtMagSf_, + tgtAddress_, + tgtWeights_, + srcMapPtr_ + ); + + //if (srcMapPtr_.valid()) + //{ + // Pout<< "srcMap:" << endl; + // string oldPrefix = Pout.prefix(); + // Pout.prefix() = oldPrefix + " "; + // srcMapPtr_().printLayout(Pout); + // Pout.prefix() = oldPrefix; + //} +} + + // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // template @@ -1181,9 +1572,23 @@ void Foam::AMIInterpolation::update const primitivePatch& tgtPatch ) { - static label patchI = 0; + // Calculate face areas + srcMagSf_.setSize(srcPatch.size()); + forAll(srcMagSf_, faceI) + { + srcMagSf_[faceI] = srcPatch[faceI].mag(srcPatch.points()); + } + tgtMagSf_.setSize(tgtPatch.size()); + forAll(tgtMagSf_, faceI) + { + tgtMagSf_[faceI] = tgtPatch[faceI].mag(tgtPatch.points()); + } - if (Pstream::parRun() && distributed(srcPatch, tgtPatch)) + + // Calculate if patches present on multiple processors + singlePatchProc_ = calcDistribution(srcPatch, tgtPatch); + + if (singlePatchProc_ == -1) { // convert local addressing to global addressing globalIndex globalSrcFaces(srcPatch.size()); @@ -1288,8 +1693,8 @@ void Foam::AMIInterpolation::update ); // weights normalisation - normaliseWeights(srcPatch, "source", srcAddress_, srcWeights_, true); - normaliseWeights(tgtPatch, "target", tgtAddress_, tgtWeights_, true); + normaliseWeights(srcMagSf_, "source", srcAddress_, srcWeights_, true); + normaliseWeights(tgtMagSf_, "target", tgtAddress_, tgtWeights_, true); // cache maps and reset addresses List > cMap; @@ -1308,11 +1713,9 @@ void Foam::AMIInterpolation::update calcAddressing(srcPatch, tgtPatch); - normaliseWeights(srcPatch, "source", srcAddress_, srcWeights_, true); - normaliseWeights(tgtPatch, "target", tgtAddress_, tgtWeights_, true); + normaliseWeights(srcMagSf_, "source", srcAddress_, srcWeights_, true); + normaliseWeights(tgtMagSf_, "target", tgtAddress_, tgtWeights_, true); } - - patchI++; } @@ -1348,7 +1751,7 @@ Foam::AMIInterpolation::interpolateToSource Field& result = tresult(); - if (Pstream::parRun()) + if (singlePatchProc_ == -1) { const mapDistribute& map = tgtMapPtr_(); @@ -1430,7 +1833,7 @@ Foam::AMIInterpolation::interpolateToTarget Field& result = tresult(); - if (Pstream::parRun()) + if (singlePatchProc_ == -1) { const mapDistribute& map = srcMapPtr_(); diff --git a/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.H b/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.H index 8ac857a66f..e43180db6f 100644 --- a/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.H +++ b/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.H @@ -106,8 +106,16 @@ class AMIInterpolation // Private data + + //- Index of processor that holds all of both sides. -1 in all other + // cases + label singlePatchProc_; + // Source patch + //- Source face areas + scalarField srcMagSf_; + //- Addresses of target faces per source face labelListList srcAddress_; @@ -117,6 +125,9 @@ class AMIInterpolation // Target patch + //- Target face areas + scalarField tgtMagSf_; + //- Addresses of source faces per target face labelListList tgtAddress_; @@ -168,8 +179,8 @@ class AMIInterpolation // Parallel functionality - //- Return true if faces are spread over multiple domains - bool distributed + //- Calculate if patches are on multiple processors + label calcDistribution ( const primitivePatch& srcPatch, const primitivePatch& tgtPatch @@ -276,15 +287,32 @@ class AMIInterpolation // NOTE: if area weights are incorrect by 'a significant amount' // normalisation may stabilise the solution, but will introduce // numerical error! - void normaliseWeights + static void normaliseWeights ( - const primitivePatch& patch, + const scalarField& patchAreas, const word& patchName, const labelListList& addr, scalarListList& wght, const bool output ); + // Constructor helper + + static void agglomerate + ( + const autoPtr& targetMap, + const scalarField& fineSrcMagSf, + const labelListList& fineSrcAddress, + const scalarListList& fineSrcWeights, + + const labelList& sourceRestrictAddressing, + const labelList& targetRestrictAddressing, + + scalarField& srcMagSf, + labelListList& srcAddress, + scalarListList& srcWeights, + autoPtr& tgtMap + ); public: @@ -307,6 +335,15 @@ public: const faceAreaIntersect::triangulationMode& triMode ); + //- Construct from agglomeration of AMIInterpolation. Agglomeration + // passed in as new coarse size and addressing from fine from coarse. + AMIInterpolation + ( + const AMIInterpolation& fineAMI, + const labelList& sourceRestrictAddressing, + const labelList& neighbourRestrictAddressing + ); + //- Destructor ~AMIInterpolation(); @@ -316,22 +353,43 @@ public: // Access + //- -1 or the processor holding all faces (both sides) of the AMI + label singlePatchProc() const; + // Source patch + //- Return const access to source patch face areas + inline const scalarField& srcMagSf() const; + //- Return const access to source patch addressing - inline const labelListList& srcAddress(); + inline const labelListList& srcAddress() const; //- Return const access to source patch weights - inline const scalarListList& srcWeights(); + inline const scalarListList& srcWeights() const; + + //- Source map pointer - valid only if singlePatchProc=-1. + // This gets + // source data into a form to be consumed by + // tgtAddress, tgtWeights + inline const mapDistribute& srcMap() const; // Target patch + //- Return const access to target patch face areas + inline const scalarField& tgtMagSf() const; + //- Return const access to target patch addressing - inline const labelListList& tgtAddress(); + inline const labelListList& tgtAddress() const; //- Return const access to target patch weights - inline const scalarListList& tgtWeights(); + inline const scalarListList& tgtWeights() const; + + //- Target map pointer - valid only if singlePatchProc=-1. + // This gets + // target data into a form to be consumed by + // srcAddress, srcWeights + inline const mapDistribute& tgtMap() const; // Manipulation diff --git a/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolationI.H b/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolationI.H index 9163979727..0907ee494c 100644 --- a/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolationI.H +++ b/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolationI.H @@ -23,9 +23,25 @@ License \*---------------------------------------------------------------------------*/ +template +inline Foam::label +Foam::AMIInterpolation::singlePatchProc() const +{ + return singlePatchProc_; +} + + +template +inline const Foam::scalarField& +Foam::AMIInterpolation::srcMagSf() const +{ + return srcMagSf_; +} + + template inline const Foam::labelListList& -Foam::AMIInterpolation::srcAddress() +Foam::AMIInterpolation::srcAddress() const { return srcAddress_; } @@ -33,15 +49,31 @@ Foam::AMIInterpolation::srcAddress() template inline const Foam::scalarListList& -Foam::AMIInterpolation::srcWeights() +Foam::AMIInterpolation::srcWeights() const { return srcWeights_; } +template +inline const Foam::mapDistribute& +Foam::AMIInterpolation::srcMap() const +{ + return srcMapPtr_(); +} + + +template +inline const Foam::scalarField& +Foam::AMIInterpolation::tgtMagSf() const +{ + return tgtMagSf_; +} + + template inline const Foam::labelListList& -Foam::AMIInterpolation::tgtAddress() +Foam::AMIInterpolation::tgtAddress() const { return tgtAddress_; } @@ -49,10 +81,18 @@ Foam::AMIInterpolation::tgtAddress() template inline const Foam::scalarListList& -Foam::AMIInterpolation::tgtWeights() +Foam::AMIInterpolation::tgtWeights() const { return tgtWeights_; } +template +inline const Foam::mapDistribute& +Foam::AMIInterpolation::tgtMap() const +{ + return tgtMapPtr_(); +} + + // ************************************************************************* // diff --git a/src/meshTools/AMIInterpolation/GAMG/interfaceFields/cyclicAMIGAMGInterfaceField/cyclicAMIGAMGInterfaceField.C b/src/meshTools/AMIInterpolation/GAMG/interfaceFields/cyclicAMIGAMGInterfaceField/cyclicAMIGAMGInterfaceField.C new file mode 100644 index 0000000000..a7f97ed84d --- /dev/null +++ b/src/meshTools/AMIInterpolation/GAMG/interfaceFields/cyclicAMIGAMGInterfaceField/cyclicAMIGAMGInterfaceField.C @@ -0,0 +1,107 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see . + +\*---------------------------------------------------------------------------*/ + +#include "cyclicAMIGAMGInterfaceField.H" +#include "addToRunTimeSelectionTable.H" +#include "lduMatrix.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ + defineTypeNameAndDebug(cyclicAMIGAMGInterfaceField, 0); + addToRunTimeSelectionTable + ( + GAMGInterfaceField, + cyclicAMIGAMGInterfaceField, + lduInterface + ); +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::cyclicAMIGAMGInterfaceField::cyclicAMIGAMGInterfaceField +( + const GAMGInterface& GAMGCp, + const lduInterfaceField& fineInterface +) +: + GAMGInterfaceField(GAMGCp, fineInterface), + cyclicAMIInterface_(refCast(GAMGCp)), + doTransform_(false), + rank_(0) +{ + const cyclicAMILduInterfaceField& p = + refCast(fineInterface); + + doTransform_ = p.doTransform(); + rank_ = p.rank(); +} + + +// * * * * * * * * * * * * * * * * Desstructor * * * * * * * * * * * * * * * // + +Foam::cyclicAMIGAMGInterfaceField::~cyclicAMIGAMGInterfaceField() +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void Foam::cyclicAMIGAMGInterfaceField::updateInterfaceMatrix +( + const scalarField& psiInternal, + scalarField& result, + const lduMatrix&, + const scalarField& coeffs, + const direction cmpt, + const Pstream::commsTypes +) const +{ + // Get neighbouring field + scalarField pnf + ( + cyclicAMIInterface_.neighbPatch().interfaceInternalField(psiInternal) + ); + + if (cyclicAMIInterface_.owner()) + { + pnf = cyclicAMIInterface_.AMI().interpolateToSource(pnf); + } + else + { + pnf = cyclicAMIInterface_.neighbPatch().AMI().interpolateToTarget(pnf); + } + + const labelUList& faceCells = cyclicAMIInterface_.faceCells(); + + forAll(faceCells, elemI) + { + result[faceCells[elemI]] -= coeffs[elemI]*pnf[elemI]; + } +} + + +// ************************************************************************* // diff --git a/src/meshTools/AMIInterpolation/GAMG/interfaceFields/cyclicAMIGAMGInterfaceField/cyclicAMIGAMGInterfaceField.H b/src/meshTools/AMIInterpolation/GAMG/interfaceFields/cyclicAMIGAMGInterfaceField/cyclicAMIGAMGInterfaceField.H new file mode 100644 index 0000000000..ae4ede91e1 --- /dev/null +++ b/src/meshTools/AMIInterpolation/GAMG/interfaceFields/cyclicAMIGAMGInterfaceField/cyclicAMIGAMGInterfaceField.H @@ -0,0 +1,158 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see . + +Class + Foam::cyclicAMIGAMGInterfaceField + +Description + GAMG agglomerated cyclic interface field. + +SourceFiles + cyclicAMIGAMGInterfaceField.C + +\*---------------------------------------------------------------------------*/ + +#ifndef cyclicAMIGAMGInterfaceField_H +#define cyclicAMIGAMGInterfaceField_H + +#include "GAMGInterfaceField.H" +#include "cyclicAMIGAMGInterface.H" +#include "cyclicAMILduInterfaceField.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class cyclicAMIGAMGInterfaceField Declaration +\*---------------------------------------------------------------------------*/ + +class cyclicAMIGAMGInterfaceField +: + public GAMGInterfaceField, + virtual public cyclicAMILduInterfaceField +{ + // Private data + + //- Local reference cast into the cyclic interface + const cyclicAMIGAMGInterface& cyclicAMIInterface_; + + //- Is the transform required + bool doTransform_; + + //- Rank of component for transformation + int rank_; + + + // Private Member Functions + + //- Disallow default bitwise copy construct + cyclicAMIGAMGInterfaceField(const cyclicAMIGAMGInterfaceField&); + + //- Disallow default bitwise assignment + void operator=(const cyclicAMIGAMGInterfaceField&); + + +public: + + //- Runtime type information + TypeName("cyclicAMI"); + + + // Constructors + + //- Construct from GAMG interface and fine level interface field + cyclicAMIGAMGInterfaceField + ( + const GAMGInterface& GAMGCp, + const lduInterfaceField& fineInterfaceField + ); + + + //- Destructor + virtual ~cyclicAMIGAMGInterfaceField(); + + + // Member Functions + + // Access + + //- Return size + label size() const + { + return cyclicAMIInterface_.size(); + } + + + // Interface matrix update + + //- Update result field based on interface functionality + virtual void updateInterfaceMatrix + ( + const scalarField& psiInternal, + scalarField& result, + const lduMatrix&, + const scalarField& coeffs, + const direction cmpt, + const Pstream::commsTypes commsType + ) const; + + + //- Cyclic interface functions + + //- Does the interface field perform the transfromation + virtual bool doTransform() const + { + return doTransform_; + } + + //- Return face transformation tensor + virtual const tensorField& forwardT() const + { + return cyclicAMIInterface_.forwardT(); + } + + //- Return neighbour-cell transformation tensor + virtual const tensorField& reverseT() const + { + return cyclicAMIInterface_.reverseT(); + } + + //- Return rank of component for transform + virtual int rank() const + { + return rank_; + } +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/meshTools/AMIInterpolation/GAMG/interfaces/cyclicAMIGAMGInterface/cyclicAMIGAMGInterface.C b/src/meshTools/AMIInterpolation/GAMG/interfaces/cyclicAMIGAMGInterface/cyclicAMIGAMGInterface.C new file mode 100644 index 0000000000..6fa4f1a41a --- /dev/null +++ b/src/meshTools/AMIInterpolation/GAMG/interfaces/cyclicAMIGAMGInterface/cyclicAMIGAMGInterface.C @@ -0,0 +1,198 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see . + +\*---------------------------------------------------------------------------*/ + +#include "AMIInterpolation.H" +#include "cyclicAMIGAMGInterface.H" +#include "addToRunTimeSelectionTable.H" +#include "Map.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ + defineTypeNameAndDebug(cyclicAMIGAMGInterface, 0); + addToRunTimeSelectionTable + ( + GAMGInterface, + cyclicAMIGAMGInterface, + lduInterface + ); +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::cyclicAMIGAMGInterface::cyclicAMIGAMGInterface +( + const label index, + const lduInterfacePtrsList& coarseInterfaces, + const lduInterface& fineInterface, + const labelField& localRestrictAddressing, + const labelField& neighbourRestrictAddressing +) +: + GAMGInterface + ( + index, + coarseInterfaces, + fineInterface, + localRestrictAddressing, + neighbourRestrictAddressing + ), + fineCyclicAMIInterface_ + ( + refCast(fineInterface) + ) +{ + // Construct face agglomeration from cell agglomeration + { + // From coarse face to cell + DynamicList