diff --git a/src/finiteVolume/fvMesh/fvPatches/constraint/cyclicAMI/cyclicAMIFvPatch.C b/src/finiteVolume/fvMesh/fvPatches/constraint/cyclicAMI/cyclicAMIFvPatch.C index 5d8935139d..0f6064471f 100644 --- a/src/finiteVolume/fvMesh/fvPatches/constraint/cyclicAMI/cyclicAMIFvPatch.C +++ b/src/finiteVolume/fvMesh/fvPatches/constraint/cyclicAMI/cyclicAMIFvPatch.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011-2014 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -34,6 +34,13 @@ namespace Foam { defineTypeNameAndDebug(cyclicAMIFvPatch, 0); addToRunTimeSelectionTable(fvPatch, cyclicAMIFvPatch, polyPatch); + addNamedToRunTimeSelectionTable + ( + fvPatch, + cyclicAMIFvPatch, + polyPatch, + cyclicPeriodicAMI + ); } diff --git a/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.C b/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.C index 70372fc724..192236ab29 100644 --- a/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.C +++ b/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011-2014 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -604,7 +604,6 @@ void Foam::AMIInterpolation::constructFromSurface } } - // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // template @@ -965,7 +964,7 @@ void Foam::AMIInterpolation::update tgtMagSf_, triMode_, reverseTarget_, - requireMatch_ + requireMatch_ && (lowWeightCorrection_ < 0) ) ); @@ -1035,28 +1034,7 @@ void Foam::AMIInterpolation::update ); // weights normalisation - normaliseWeights - ( - srcMagSf_, - "source", - srcAddress_, - srcWeights_, - srcWeightsSum_, - AMIPtr->conformal(), - true, - lowWeightCorrection_ - ); - normaliseWeights - ( - tgtMagSf_, - "target", - tgtAddress_, - tgtWeights_, - tgtWeightsSum_, - AMIPtr->conformal(), - true, - lowWeightCorrection_ - ); + normaliseWeights(AMIPtr->conformal(), true); // cache maps and reset addresses List > cMap; @@ -1082,7 +1060,7 @@ void Foam::AMIInterpolation::update tgtMagSf_, triMode_, reverseTarget_, - requireMatch_ + requireMatch_ && (lowWeightCorrection_ < 0) ) ); @@ -1094,28 +1072,7 @@ void Foam::AMIInterpolation::update tgtWeights_ ); - normaliseWeights - ( - srcMagSf_, - "source", - srcAddress_, - srcWeights_, - srcWeightsSum_, - AMIPtr->conformal(), - true, - lowWeightCorrection_ - ); - normaliseWeights - ( - tgtMagSf_, - "target", - tgtAddress_, - tgtWeights_, - tgtWeightsSum_, - AMIPtr->conformal(), - true, - lowWeightCorrection_ - ); + normaliseWeights(AMIPtr->conformal(), true); } if (debug) @@ -1131,6 +1088,78 @@ void Foam::AMIInterpolation::update } +template +void Foam::AMIInterpolation::append +( + const SourcePatch& srcPatch, + const TargetPatch& tgtPatch +) +{ + // create a new interpolation + autoPtr > newPtr + ( + new AMIInterpolation + ( + srcPatch, + tgtPatch, + triMode_, + requireMatch_, + methodName_, + lowWeightCorrection_, + reverseTarget_ + ) + ); + + // combine new and current data + forAll(srcMagSf_, srcFaceI) + { + srcAddress_[srcFaceI].append(newPtr->srcAddress()[srcFaceI]); + srcWeights_[srcFaceI].append(newPtr->srcWeights()[srcFaceI]); + srcWeightsSum_[srcFaceI] += newPtr->srcWeightsSum()[srcFaceI]; + } + + forAll(tgtMagSf_, tgtFaceI) + { + tgtAddress_[tgtFaceI].append(newPtr->tgtAddress()[tgtFaceI]); + tgtWeights_[tgtFaceI].append(newPtr->tgtWeights()[tgtFaceI]); + tgtWeightsSum_[tgtFaceI] += newPtr->tgtWeightsSum()[tgtFaceI]; + } +} + + +template +void Foam::AMIInterpolation::normaliseWeights +( + const bool conformal, + const bool output +) +{ + normaliseWeights + ( + srcMagSf_, + "source", + srcAddress_, + srcWeights_, + srcWeightsSum_, + conformal, + output, + lowWeightCorrection_ + ); + + normaliseWeights + ( + tgtMagSf_, + "target", + tgtAddress_, + tgtWeights_, + tgtWeightsSum_, + conformal, + output, + lowWeightCorrection_ + ); +} + + template template void Foam::AMIInterpolation::interpolateToTarget diff --git a/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.H b/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.H index 27d077f126..67205b69a7 100644 --- a/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.H +++ b/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011-2014 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -418,6 +418,16 @@ public: const TargetPatch& tgtPatch ); + //- Append additional addressing and weights + void append + ( + const SourcePatch& srcPatch, + const TargetPatch& tgtPatch + ); + + //- Normalise the weights + void normaliseWeights(const bool conformal, const bool output); + // Evaluation diff --git a/src/meshTools/AMIInterpolation/patches/cyclicAMI/cyclicAMIPointPatch/cyclicAMIPointPatch.C b/src/meshTools/AMIInterpolation/patches/cyclicAMI/cyclicAMIPointPatch/cyclicAMIPointPatch.C index 2b4e6b8ad3..98fe75a0b7 100644 --- a/src/meshTools/AMIInterpolation/patches/cyclicAMI/cyclicAMIPointPatch/cyclicAMIPointPatch.C +++ b/src/meshTools/AMIInterpolation/patches/cyclicAMI/cyclicAMIPointPatch/cyclicAMIPointPatch.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -38,6 +38,13 @@ namespace Foam cyclicAMIPointPatch, polyPatch ); + addNamedToRunTimeSelectionTable + ( + facePointPatch, + cyclicAMIPointPatch, + polyPatch, + cyclicPeriodicAMI + ); } diff --git a/src/meshTools/AMIInterpolation/patches/cyclicPeriodicAMI/cyclicPeriodicAMIPolyPatch/cyclicPeriodicAMIPolyPatch.C b/src/meshTools/AMIInterpolation/patches/cyclicPeriodicAMI/cyclicPeriodicAMIPolyPatch/cyclicPeriodicAMIPolyPatch.C new file mode 100644 index 0000000000..751cca2f7d --- /dev/null +++ b/src/meshTools/AMIInterpolation/patches/cyclicPeriodicAMI/cyclicPeriodicAMIPolyPatch/cyclicPeriodicAMIPolyPatch.C @@ -0,0 +1,391 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2015 OpenCFD Ltd. + \\/ 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 "cyclicPeriodicAMIPolyPatch.H" +#include "addToRunTimeSelectionTable.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + defineTypeNameAndDebug(cyclicPeriodicAMIPolyPatch, 0); + + addToRunTimeSelectionTable(polyPatch, cyclicPeriodicAMIPolyPatch, word); + addToRunTimeSelectionTable + ( + polyPatch, + cyclicPeriodicAMIPolyPatch, + dictionary + ); +} + + +// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * // + +void Foam::cyclicPeriodicAMIPolyPatch::resetAMI +( + const AMIPatchToPatchInterpolation::interpolationMethod& AMIMethod +) const +{ + if (owner()) + { + // Get the periodic patch + const coupledPolyPatch& periodicPatch + ( + refCast + ( + boundaryMesh()[periodicPatchID()] + ) + ); + + // Create copies of both patches' points, transformed to the owner + pointField thisPoints0(localPoints()); + pointField nbrPoints0(neighbPatch().localPoints()); + transformPosition(nbrPoints0); + + // Reset the stored number of periodic transformations to a lower + // absolute value if possible + if (nSectors_ > 0) + { + if (nTransforms_ > nSectors_/2) + { + nTransforms_ -= nSectors_; + } + else if (nTransforms_ < - nSectors_/2) + { + nTransforms_ += nSectors_; + } + } + + // Apply the stored number of periodic transforms + for (label i = 0; i < nTransforms_; ++ i) + { + periodicPatch.transformPosition(thisPoints0); + } + for (label i = 0; i > nTransforms_; -- i) + { + periodicPatch.transformPosition(nbrPoints0); + } + + // Create another copy + pointField thisPoints(thisPoints0); + pointField nbrPoints(nbrPoints0); + + // Create patches for all the points + primitivePatch thisPatch0 + ( + SubList(localFaces(), size()), + thisPoints0 + ); + primitivePatch thisPatch + ( + SubList(localFaces(), size()), + thisPoints + ); + primitivePatch nbrPatch0 + ( + SubList(neighbPatch().localFaces(), neighbPatch().size()), + nbrPoints0 + ); + primitivePatch nbrPatch + ( + SubList(neighbPatch().localFaces(), neighbPatch().size()), + nbrPoints + ); + + // Construct a new AMI interpolation between the initial patch locations + AMIPtr_.reset + ( + new AMIPatchToPatchInterpolation + ( + thisPatch0, + nbrPatch0, + surfPtr(), + faceAreaIntersect::tmMesh, + false, + AMIPatchToPatchInterpolation::imPartialFaceAreaWeight, + AMILowWeightCorrection_, + AMIReverse_ + ) + ); + + // Number of geometry replications + label iter(0); + label nTransformsOld(nTransforms_); + + // Weight sum averages + scalar srcSum(gAverage(AMIPtr_->srcWeightsSum())); + scalar tgtSum(gAverage(AMIPtr_->tgtWeightsSum())); + + // Direction of geometry replication + bool direction = nTransforms_ >= 0; + + // Increase in the source weight sum for the last iteration in the + // opposite direction. If the current increase is less than this, the + // direction is reversed. + scalar srcSumDiff = 0; + + // Loop, replicating the geometry + while + ( + (iter < maxIter_) + && ( + (1 - srcSum > matchTolerance()) + || (1 - tgtSum > matchTolerance()) + ) + ) + { + if (direction) + { + periodicPatch.transformPosition(thisPoints); + + thisPatch.movePoints(thisPoints); + + AMIPtr_->append(thisPatch, nbrPatch0); + } + else + { + periodicPatch.transformPosition(nbrPoints); + + nbrPatch.movePoints(nbrPoints); + + AMIPtr_->append(thisPatch0, nbrPatch); + } + + const scalar srcSumNew = gAverage(AMIPtr_->srcWeightsSum()); + const scalar srcSumDiffNew = srcSumNew - srcSum; + + if (srcSumDiffNew < srcSumDiff || srcSumDiffNew < SMALL) + { + direction = !direction; + + srcSumDiff = srcSumDiffNew; + } + + srcSum = srcSumNew; + tgtSum = gAverage(AMIPtr_->tgtWeightsSum()); + + nTransforms_ += direction ? +1 : -1; + + ++ iter; + } + + // Average the number of transformstions + nTransforms_ = (nTransforms_ + nTransformsOld)/2; + + // Check that the match is complete + if (iter == maxIter_) + { + FatalErrorIn + ( + "void Foam::cyclicPeriodicAMIPolyPatch::resetPeriodicAMI" + "(" + "const AMIPatchToPatchInterpolation::interpolationMethod&" + ") const" + ) + << "Patches " << name() << " and " << neighbPatch().name() + << " do not couple to within a tolerance of " + << matchTolerance() + << " when transformed according to the periodic patch " + << periodicPatch.name() << "." << exit(FatalError); + } + + // Check that at least one patch has a weight sum of one + if + ( + mag(1 - srcSum) > matchTolerance() + && mag(1 - tgtSum) > matchTolerance() + ) + { + FatalErrorIn + ( + "void Foam::cyclicPeriodicAMIPolyPatch::resetPeriodicAMI" + "(" + "const AMIPatchToPatchInterpolation::interpolationMethod&" + ") const" + ) + << "Patches " << name() << " and " << neighbPatch().name() + << " do not overlap an integer number of times when transformed" + << " according to the periodic patch " + << periodicPatch.name() << "." << exit(FatalError); + } + + // Normalise the weights + AMIPtr_->normaliseWeights(true, false); + } +} + + +// * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * * // + +Foam::cyclicPeriodicAMIPolyPatch::cyclicPeriodicAMIPolyPatch +( + const word& name, + const label size, + const label start, + const label index, + const polyBoundaryMesh& bm, + const word& patchType, + const transformType transform +) +: + cyclicAMIPolyPatch(name, size, start, index, bm, patchType, transform), + periodicPatchName_(word::null), + periodicPatchID_(-1), + nTransforms_(0), + nSectors_(-1), + maxIter_(36) +{} + + +Foam::cyclicPeriodicAMIPolyPatch::cyclicPeriodicAMIPolyPatch +( + const word& name, + const dictionary& dict, + const label index, + const polyBoundaryMesh& bm, + const word& patchType +) +: + cyclicAMIPolyPatch(name, dict, index, bm, patchType), + periodicPatchName_(dict.lookup("periodicPatch")), + periodicPatchID_(-1), + nTransforms_(dict.lookupOrDefault