Merge branch 'feature-overset-lsq' into 'develop'

ENH: overset: new solvers, new stencil

See merge request Development/OpenFOAM-plus!180
This commit is contained in:
Andrew Heather
2017-12-14 15:43:59 +00:00
38 changed files with 1508 additions and 310 deletions

View File

@ -7,8 +7,8 @@ surfaceScalarField faceMask(localMin<scalar>(mesh).interpolate(cellMask));
volScalarField rAU(1.0/UEqn.A()); volScalarField rAU(1.0/UEqn.A());
surfaceScalarField rhorAUf("rhorAUf", faceMask*fvc::interpolate(rho*rAU)); surfaceScalarField rhorAUf("rhorAUf", faceMask*fvc::interpolate(rho*rAU));
volVectorField HbyA("HbyA", constrainHbyA(rAU*UEqn.H(), U, p)); volVectorField HbyA("HbyA", U);
//mesh.interpolate(HbyA); HbyA = constrainHbyA(rAU*UEqn.H(), U, p);
if (pimple.nCorrPISO() <= 1) if (pimple.nCorrPISO() <= 1)
{ {

View File

@ -16,6 +16,9 @@
fvOptions.constrain(UEqn); fvOptions.constrain(UEqn);
if (simple.momentumPredictor())
{
solve(UEqn == -cellMask*fvc::grad(p)); solve(UEqn == -cellMask*fvc::grad(p));
}
fvOptions.correct(U); fvOptions.correct(U);

View File

@ -5,7 +5,7 @@
surfaceScalarField rAUf("rAUf", faceMask*fvc::interpolate(rAU)); surfaceScalarField rAUf("rAUf", faceMask*fvc::interpolate(rAU));
volVectorField HbyA("HbyA", U); volVectorField HbyA("HbyA", U);
HbyA = constrainHbyA(rAU*UEqn.H(), U, p); HbyA = constrainHbyA(cellMask*rAU*UEqn.H(), U, p);
//mesh.interpolate(HbyA); //mesh.interpolate(HbyA);
if (massFluxInterpolation) if (massFluxInterpolation)

View File

@ -138,3 +138,4 @@ volScalarField pDivU
mesh, mesh,
dimensionedScalar("pDivU", p.dimensions()/dimTime, 0) dimensionedScalar("pDivU", p.dimensions()/dimTime, 0)
); );

View File

@ -1,6 +1,6 @@
#include "readTimeControls.H" #include "readTimeControls.H"
correctPhi = pimple.dict().lookupOrDefault<Switch>("correctPhi", true); correctPhi = pimple.dict().lookupOrDefault<Switch>("correctPhi", false);
checkMeshCourantNo = checkMeshCourantNo =
pimple.dict().lookupOrDefault<Switch>("checkMeshCourantNo", false); pimple.dict().lookupOrDefault<Switch>("checkMeshCourantNo", false);

View File

@ -32,6 +32,7 @@ bodies
type sphere; type sphere;
mass 1; mass 1;
radius 0.05; radius 0.05;
centreOfMass (0 10 0);
transform (1 0 0 0 1 0 0 0 1) (0 -1 0); transform (1 0 0 0 1 0 0 0 1) (0 -1 0);
mergeWith hinge; mergeWith hinge;
} }

View File

@ -14,6 +14,7 @@ bodies
parent root; parent root;
mass 6e4; mass 6e4;
radius 0.01; radius 0.01;
centreOfMass (0 0 0);
transform (1 0 0 0 1 0 0 0 1) (0 0 0); transform (1 0 0 0 1 0 0 0 1) (0 0 0);
joint joint
{ {
@ -37,6 +38,7 @@ bodies
parent M; parent M;
mass 6e3; mass 6e3;
radius 0.01; radius 0.01;
centreOfMass (0 0 0);
transform (1 0 0 0 1 0 0 0 1) (0 -5 0); transform (1 0 0 0 1 0 0 0 1) (0 -5 0);
mergeWith M; mergeWith M;
} }

View File

@ -233,10 +233,10 @@ public:
void reorder(const labelUList&, const bool validBoundary); void reorder(const labelUList&, const bool validBoundary);
//- writeData member function required by regIOobject //- writeData member function required by regIOobject
bool writeData(Ostream&) const; virtual bool writeData(Ostream&) const;
//- Write using given format, version and form uncompression //- Write using given format, version and form uncompression
bool writeObject virtual bool writeObject
( (
IOstream::streamFormat fmt, IOstream::streamFormat fmt,
IOstream::versionNumber ver, IOstream::versionNumber ver,

View File

@ -101,7 +101,18 @@ bool Foam::patchDistMethods::Poisson::correct
volVectorField gradyPsi(fvc::grad(yPsi)); volVectorField gradyPsi(fvc::grad(yPsi));
volScalarField magGradyPsi(mag(gradyPsi)); volScalarField magGradyPsi(mag(gradyPsi));
y = sqrt(magSqr(gradyPsi) + 2*yPsi) - magGradyPsi; // Need to stabilise the y for overset meshes since the holed cells
// keep the initial value (0.0) so the gradient of that will be
// zero as well. Turbulence models do not like zero wall distance.
y = max
(
sqrt(magSqr(gradyPsi) + 2*yPsi) - magGradyPsi,
dimensionedScalar("smallY", dimLength, SMALL)
);
// For overset: enforce smooth y field (yPsi is smooth, magGradyPsi is
// not)
mesh_.interpolate(y);
// Need to stabilise the y for overset meshes since the holed cells // Need to stabilise the y for overset meshes since the holed cells
// keep the initial value (0.0) so the gradient of that will be // keep the initial value (0.0) so the gradient of that will be

View File

@ -6,6 +6,7 @@ cellCellStencil/inverseDistance/waveMethod.C
cellCellStencil/inverseDistance/meshToMeshData.C cellCellStencil/inverseDistance/meshToMeshData.C
cellCellStencil/trackingInverseDistance/voxelMeshSearch.C cellCellStencil/trackingInverseDistance/voxelMeshSearch.C
cellCellStencil/trackingInverseDistance/trackingInverseDistanceCellCellStencil.C cellCellStencil/trackingInverseDistance/trackingInverseDistanceCellCellStencil.C
cellCellStencil/leastSquares/leastSquaresCellCellStencil.C
dynamicOversetFvMesh/dynamicOversetFvMesh.C dynamicOversetFvMesh/dynamicOversetFvMesh.C
@ -21,6 +22,9 @@ oversetPolyPatch/oversetGAMGInterfaceField.C
oversetPolyPatch/oversetPointPatch.C oversetPolyPatch/oversetPointPatch.C
oversetPolyPatch/oversetPointPatchFields.C oversetPolyPatch/oversetPointPatchFields.C
oversetPolyPatch/semiImplicitOversetFvPatchFields.C
oversetPolyPatch/semiImplicitOversetGAMGInterfaceField.C
oversetAdjustPhi/oversetAdjustPhi.C oversetAdjustPhi/oversetAdjustPhi.C
regionsToCell/regionsToCell.C regionsToCell/regionsToCell.C

View File

@ -94,22 +94,22 @@ Foam::cellCellStencil::~cellCellStencil()
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
const Foam::labelIOList& Foam::cellCellStencil::zoneID() const const Foam::labelIOList& Foam::cellCellStencil::zoneID(const fvMesh& mesh)
{ {
if (!mesh_.foundObject<labelIOList>("zoneID")) if (!mesh.foundObject<labelIOList>("zoneID"))
{ {
labelIOList* zoneIDPtr = new labelIOList labelIOList* zoneIDPtr = new labelIOList
( (
IOobject IOobject
( (
"zoneID", "zoneID",
mesh_.facesInstance(), mesh.facesInstance(),
polyMesh::meshSubDir, polyMesh::meshSubDir,
mesh_, mesh,
IOobject::NO_READ, IOobject::NO_READ,
IOobject::NO_WRITE IOobject::NO_WRITE
), ),
mesh_.nCells() mesh.nCells()
); );
labelIOList& zoneID = *zoneIDPtr; labelIOList& zoneID = *zoneIDPtr;
@ -118,13 +118,13 @@ const Foam::labelIOList& Foam::cellCellStencil::zoneID() const
IOobject IOobject
( (
"zoneID", "zoneID",
mesh_.time().findInstance(mesh_.dbDir(), "zoneID"), mesh.time().findInstance(mesh.dbDir(), "zoneID"),
mesh_, mesh,
IOobject::MUST_READ, IOobject::MUST_READ,
IOobject::NO_WRITE, IOobject::NO_WRITE,
false false
), ),
mesh_ mesh
); );
forAll(volZoneID, cellI) forAll(volZoneID, cellI)
{ {
@ -133,7 +133,7 @@ const Foam::labelIOList& Foam::cellCellStencil::zoneID() const
zoneIDPtr->store(); zoneIDPtr->store();
} }
return mesh_.lookupObject<labelIOList>("zoneID"); return mesh.lookupObject<labelIOList>("zoneID");
} }

View File

@ -168,12 +168,27 @@ public:
// calculated, 1 = use interpolated) // calculated, 1 = use interpolated)
virtual const scalarList& cellInterpolationWeight() const = 0; virtual const scalarList& cellInterpolationWeight() const = 0;
//- Calculate weights for a single acceptor
virtual void stencilWeights
(
const point& sample,
const pointList& donorCcs,
scalarList& weights
) const = 0;
//- Helper: is stencil fully local //- Helper: is stencil fully local
bool localStencil(const labelUList&) const; bool localStencil(const labelUList&) const;
//- Helper: get reference to registered zoneID. Loads volScalarField //- Helper: get reference to registered zoneID. Loads volScalarField
// if not registered. // if not registered.
const labelIOList& zoneID() const; static const labelIOList& zoneID(const fvMesh&);
//- Helper: get reference to registered zoneID. Loads volScalarField
// if not registered.
const labelIOList& zoneID() const
{
return zoneID(mesh_);
}
//- Helper: create cell-cell addressing in global numbering //- Helper: create cell-cell addressing in global numbering
static void globalCellCells static void globalCellCells

View File

@ -154,6 +154,17 @@ public:
{ {
return stencilPtr_().cellInterpolationWeight(); return stencilPtr_().cellInterpolationWeight();
} }
//- Calculate weights for a single acceptor
virtual void stencilWeights
(
const point& sample,
const pointList& donorCcs,
scalarList& weights
) const
{
stencilPtr_().stencilWeights(sample, donorCcs, weights);
}
}; };

View File

@ -1100,4 +1100,39 @@ bool Foam::cellCellStencils::cellVolumeWeight::update()
} }
void Foam::cellCellStencils::cellVolumeWeight::stencilWeights
(
const point& sample,
const pointList& donorCcs,
scalarList& weights
) const
{
// Inverse-distance weighting
weights.setSize(donorCcs.size());
scalar sum = 0.0;
forAll(donorCcs, i)
{
scalar d = mag(sample-donorCcs[i]);
if (d > ROOTVSMALL)
{
weights[i] = 1.0/d;
sum += weights[i];
}
else
{
// Short circuit
weights = 0.0;
weights[i] = 1.0;
return;
}
}
forAll(weights, i)
{
weights[i] /= sum;
}
}
// ************************************************************************* // // ************************************************************************* //

View File

@ -227,6 +227,15 @@ public:
{ {
return cellInterpolationWeight_; return cellInterpolationWeight_;
} }
//- Calculate inverse distance weights for a single acceptor. Revert
// to inverse distance (so not consistent with volume overlap!)
virtual void stencilWeights
(
const point& sample,
const pointList& donorCcs,
scalarList& weights
) const;
}; };

View File

@ -155,6 +155,7 @@ void Foam::cellCellStencils::inverseDistance::fill
void Foam::cellCellStencils::inverseDistance::markBoundaries void Foam::cellCellStencils::inverseDistance::markBoundaries
( (
const fvMesh& mesh, const fvMesh& mesh,
const vector& smallVec,
const boundBox& bb, const boundBox& bb,
const labelVector& nDivs, const labelVector& nDivs,
@ -188,6 +189,9 @@ void Foam::cellCellStencils::inverseDistance::markBoundaries
// Mark in voxel mesh // Mark in voxel mesh
boundBox faceBb(pp.points(), pp[i], false); boundBox faceBb(pp.points(), pp[i], false);
faceBb.min() -= smallVec;
faceBb.max() += smallVec;
if (bb.overlaps(faceBb)) if (bb.overlaps(faceBb))
{ {
fill(patchTypes, bb, nDivs, faceBb, patchCellType::PATCH); fill(patchTypes, bb, nDivs, faceBb, patchCellType::PATCH);
@ -213,6 +217,9 @@ void Foam::cellCellStencils::inverseDistance::markBoundaries
// Mark in voxel mesh // Mark in voxel mesh
boundBox faceBb(pp.points(), pp[i], false); boundBox faceBb(pp.points(), pp[i], false);
faceBb.min() -= smallVec;
faceBb.max() += smallVec;
if (bb.overlaps(faceBb)) if (bb.overlaps(faceBb))
{ {
fill(patchTypes, bb, nDivs, faceBb, patchCellType::OVERSET); fill(patchTypes, bb, nDivs, faceBb, patchCellType::OVERSET);
@ -333,6 +340,10 @@ void Foam::cellCellStencils::inverseDistance::markPatchesAsHoles
forAll(tgtCellMap, tgtCelli) forAll(tgtCellMap, tgtCelli)
{ {
label celli = tgtCellMap[tgtCelli]; label celli = tgtCellMap[tgtCelli];
treeBoundBox cBb(cellBb(mesh_, celli));
cBb.min() -= smallVec_;
cBb.max() += smallVec_;
if if
( (
overlaps overlaps
@ -340,7 +351,7 @@ void Foam::cellCellStencils::inverseDistance::markPatchesAsHoles
srcPatchBb, srcPatchBb,
zoneDivs, zoneDivs,
srcPatchTypes, srcPatchTypes,
cellBb(mesh_, celli), cBb,
patchCellType::PATCH patchCellType::PATCH
) )
) )
@ -399,6 +410,9 @@ void Foam::cellCellStencils::inverseDistance::markPatchesAsHoles
forAll(tgtCellMap, tgtCelli) forAll(tgtCellMap, tgtCelli)
{ {
label celli = tgtCellMap[tgtCelli]; label celli = tgtCellMap[tgtCelli];
treeBoundBox cBb(cellBb(mesh_, celli));
cBb.min() -= smallVec_;
cBb.max() += smallVec_;
if if
( (
overlaps overlaps
@ -406,7 +420,7 @@ void Foam::cellCellStencils::inverseDistance::markPatchesAsHoles
srcPatchBb, srcPatchBb,
zoneDivs, zoneDivs,
srcPatchTypes, srcPatchTypes,
cellBb(mesh_, celli), cBb,
patchCellType::PATCH patchCellType::PATCH
) )
) )
@ -501,7 +515,9 @@ void Foam::cellCellStencils::inverseDistance::markDonors
label celli = tgtCellMap[tgtCelli]; label celli = tgtCellMap[tgtCelli];
if (allStencil[celli].empty()) if (allStencil[celli].empty())
{ {
const treeBoundBox subBb(cellBb(mesh_, celli)); treeBoundBox subBb(cellBb(mesh_, celli));
subBb.min() -= smallVec_;
subBb.max() += smallVec_;
forAll(srcOverlapProcs, i) forAll(srcOverlapProcs, i)
{ {
@ -1194,12 +1210,20 @@ void Foam::cellCellStencils::inverseDistance::walkFront
{ {
if (isA<oversetFvPatch>(fvm[patchI])) if (isA<oversetFvPatch>(fvm[patchI]))
{ {
forAll(fvm[patchI], i) const labelList& fc = fvm[patchI].faceCells();
forAll(fc, i)
{ {
label cellI = fc[i];
if (allCellTypes[cellI] == INTERPOLATED)
{
// Note that acceptors might have been marked hole if
// there are no donors in which case we do not want to
// walk this out. This is an extreme situation.
isFront[fvm[patchI].start()+i] = true; isFront[fvm[patchI].start()+i] = true;
} }
} }
} }
}
// Outside of 'hole' region // Outside of 'hole' region
@ -1353,12 +1377,12 @@ void Foam::cellCellStencils::inverseDistance::walkFront
} }
void Foam::cellCellStencils::inverseDistance::calcStencilWeights void Foam::cellCellStencils::inverseDistance::stencilWeights
( (
const point& sample, const point& sample,
const pointList& donorCcs, const pointList& donorCcs,
scalarList& weights scalarList& weights
) ) const
{ {
// Inverse-distance weighting // Inverse-distance weighting
@ -1500,7 +1524,7 @@ void Foam::cellCellStencils::inverseDistance::createStencil
{ {
label cellI = donorCells[i]; label cellI = donorCells[i];
const pointList& donorCentres = donorCellCentres[cellI]; const pointList& donorCentres = donorCellCentres[cellI];
calcStencilWeights stencilWeights
( (
samples[cellI], samples[cellI],
donorCentres, donorCentres,
@ -1565,6 +1589,7 @@ Foam::cellCellStencils::inverseDistance::inverseDistance
: :
cellCellStencil(mesh), cellCellStencil(mesh),
dict_(dict), dict_(dict),
smallVec_(vector::zero),
cellTypes_(labelList(mesh.nCells(), CALCULATED)), cellTypes_(labelList(mesh.nCells(), CALCULATED)),
interpolationCells_(0), interpolationCells_(0),
cellInterpolationMap_(), cellInterpolationMap_(),
@ -1605,6 +1630,9 @@ bool Foam::cellCellStencils::inverseDistance::update()
{ {
scalar layerRelax(dict_.lookupOrDefault("layerRelax", 1.0)); scalar layerRelax(dict_.lookupOrDefault("layerRelax", 1.0));
scalar tol = dict_.lookupOrDefault("tolerance", 1e-10);
smallVec_ = mesh_.bounds().span()*tol;
const labelIOList& zoneID = this->zoneID(); const labelIOList& zoneID = this->zoneID();
label nZones = gMax(zoneID)+1; label nZones = gMax(zoneID)+1;
@ -1745,6 +1773,7 @@ bool Foam::cellCellStencils::inverseDistance::update()
markBoundaries markBoundaries
( (
meshParts[zoneI].subMesh(), meshParts[zoneI].subMesh(),
smallVec_,
patchBb[zoneI][Pstream::myProcNo()], patchBb[zoneI][Pstream::myProcNo()],
patchDivisions[zoneI], patchDivisions[zoneI],
@ -1758,7 +1787,7 @@ bool Foam::cellCellStencils::inverseDistance::update()
// Print a bit // Print a bit
{ {
Info<< typeName << " : detected " << nZones Info<< type() << " : detected " << nZones
<< " mesh regions" << endl; << " mesh regions" << endl;
Info<< incrIndent; Info<< incrIndent;
forAll(nCellsPerZone, zoneI) forAll(nCellsPerZone, zoneI)
@ -1862,6 +1891,16 @@ bool Foam::cellCellStencils::inverseDistance::update()
} }
else else
{ {
// If there are no donors we can either set the
// acceptor cell to 'hole' i.e. nothing gets calculated
// if the acceptor cells go outside the donor meshes or
// we can set it to 'calculated' to have something
// like an acmi type behaviour where only covered
// acceptor cell use the interpolation and non-covered
// become calculated. Uncomment below line. Note: this
// should be switchable?
//allCellTypes[cellI] = CALCULATED;
allCellTypes[cellI] = HOLE; allCellTypes[cellI] = HOLE;
} }
} }
@ -1915,7 +1954,7 @@ bool Foam::cellCellStencils::inverseDistance::update()
// Dump stencil // Dump stencil
mkDir(mesh_.time().timePath()); mkDir(mesh_.time().timePath());
OBJstream str(mesh_.time().timePath()/"injectionStencil.obj"); OBJstream str(mesh_.time().timePath()/"injectionStencil.obj");
Pout<< typeName << " : dumping injectionStencil to " Pout<< type() << " : dumping injectionStencil to "
<< str.name() << endl; << str.name() << endl;
pointField cc(mesh_.cellCentres()); pointField cc(mesh_.cellCentres());
cellInterpolationMap_.distribute(cc); cellInterpolationMap_.distribute(cc);
@ -1973,7 +2012,7 @@ bool Foam::cellCellStencils::inverseDistance::update()
// Dump stencil // Dump stencil
mkDir(mesh_.time().timePath()); mkDir(mesh_.time().timePath());
OBJstream str(mesh_.time().timePath()/"stencil.obj"); OBJstream str(mesh_.time().timePath()/"stencil.obj");
Pout<< typeName << " : dumping to " << str.name() << endl; Pout<< type() << " : dumping to " << str.name() << endl;
pointField cc(mesh_.cellCentres()); pointField cc(mesh_.cellCentres());
cellInterpolationMap_.distribute(cc); cellInterpolationMap_.distribute(cc);

View File

@ -74,6 +74,9 @@ protected:
//- Dictionary of motion control parameters //- Dictionary of motion control parameters
const dictionary dict_; const dictionary dict_;
//- Small perturbation vector for geometric tests
vector smallVec_;
//- Per cell the cell type //- Per cell the cell type
labelList cellTypes_; labelList cellTypes_;
@ -143,6 +146,8 @@ protected:
static void markBoundaries static void markBoundaries
( (
const fvMesh& mesh, const fvMesh& mesh,
const vector& smallVec,
const boundBox& bb, const boundBox& bb,
const labelVector& nDivs, const labelVector& nDivs,
PackedList<2>& patchTypes, PackedList<2>& patchTypes,
@ -237,15 +242,6 @@ protected:
scalarField& allWeight scalarField& allWeight
) const; ) const;
//- Calculate inverse distance weights
static void calcStencilWeights
(
const point& sample,
const pointList& donorCcs,
scalarList& weights
);
//- Create stencil starting from the donor containing the acceptor //- Create stencil starting from the donor containing the acceptor
virtual void createStencil(const globalIndex&); virtual void createStencil(const globalIndex&);
@ -319,6 +315,14 @@ public:
{ {
return cellInterpolationWeight_; return cellInterpolationWeight_;
} }
//- Calculate inverse distance weights for a single acceptor
virtual void stencilWeights
(
const point& sample,
const pointList& donorCcs,
scalarList& weights
) const;
}; };

View File

@ -0,0 +1,177 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2017 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify i
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 <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "leastSquaresCellCellStencil.H"
#include "addToRunTimeSelectionTable.H"
#include "SVD.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
namespace cellCellStencils
{
defineTypeNameAndDebug(leastSquares, 0);
addToRunTimeSelectionTable(cellCellStencil, leastSquares, mesh);
}
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::cellCellStencils::leastSquares::stencilWeights
(
const point& sample,
const pointList& donorCcs,
scalarList& weights
) const
{
// Implicit least squares weighting
// Number of donors
label nD = donorCcs.size();
weights.setSize(nD);
// List for distance vectors and LSQ weights
List<vector> d(nD);
scalarList LSQw(nD);
// Sum of weights
scalar W = 0;
// Sum of weighted distance vectors
vector dw = vector::zero;
RectangularMatrix<scalar> A(nD, 3);
bool shortC = false;
// Compute distance vectors and fill rectangular matrix
forAll(donorCcs, j)
{
// Neighbour weights
d[j] = donorCcs[j] - sample;
// Check for short-circuiting if zero distance
// is detected with respect to any donor
if (mag(d[j]) < ROOTVSMALL)
{
shortC = true;
break;
}
LSQw[j] = 1.0/magSqr(d[j]);
// T matrix
vector wd = LSQw[j]*d[j];
A[j][0] = wd.x();
A[j][1] = wd.y();
A[j][2] = wd.z();
// Sum of weighted distance vectors
dw += wd;
// Sum of weights
W += LSQw[j];
}
if (!shortC)
{
// Use Singular Value Decomposition to avoid problems
// with 1D, 2D stencils
SVD svd(A.T()*A, SMALL);
// Least squares vectors
RectangularMatrix<scalar> ATAinvAT(svd.VSinvUt()*A.T());
scalar saveDiag(W);
// Diagonal coefficient
for (label i = 0; i < 3; i++)
{
// Get row
scalarList Row(UList<scalar>(ATAinvAT[i], nD));
forAll(donorCcs, j)
{
W -= Row[j]*LSQw[j]*dw[i];
}
}
if (mag(W) < SMALL*mag(saveDiag))
{
shortC = true;
}
else
{
// Compute final neighbour weights with additional scaling
forAll(donorCcs, j)
{
weights[j] =
(
LSQw[j]
- ATAinvAT[0][j]*LSQw[j]*dw[0]
- ATAinvAT[1][j]*LSQw[j]*dw[1]
- ATAinvAT[2][j]*LSQw[j]*dw[2]
)
/W;
}
}
}
if (shortC)
{
// Matrix ill conditioned. Use straight injection from central
// donor.
weights = 0.0;
weights[0] = 1.0;
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::cellCellStencils::leastSquares::leastSquares
(
const fvMesh& mesh,
const dictionary& dict,
const bool doUpdate
)
:
inverseDistance(mesh, dict, false)
{
if (doUpdate)
{
update();
}
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::cellCellStencils::leastSquares::~leastSquares()
{}
// ************************************************************************* //

View File

@ -0,0 +1,107 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2017 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 <http://www.gnu.org/licenses/>.
Class
Foam::cellCellStencils::leastSquares
Description
Least-squares-weighted interpolation stencil.
Base machinery is similar to inverse distance interpolation stencil
but weights minimize error in LSQ sense recovering exact solution
for linear solution problems. Gradient and values are found
simultaneously.
SourceFiles
leastSquaresCellCellStencil.C
\*---------------------------------------------------------------------------*/
#ifndef cellCellStencils_leastSquares_H
#define cellCellStencils_leastSquares_H
#include "inverseDistanceCellCellStencil.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace cellCellStencils
{
/*---------------------------------------------------------------------------*\
Class leastSquares Declaration
\*---------------------------------------------------------------------------*/
class leastSquares
:
public inverseDistance
{
// Private Member Functions
//- Disallow default bitwise copy construct
leastSquares(const leastSquares&);
//- Disallow default bitwise assignment
void operator=(const leastSquares&);
public:
//- Runtime type information
TypeName("leastSquares");
// Constructors
//- Construct from fvMesh
leastSquares(const fvMesh&, const dictionary&, const bool);
//- Destructor
virtual ~leastSquares();
// Member Functions
//- Calculate lsq weights for single acceptor
virtual void stencilWeights
(
const point& sample,
const pointList& donorCcs,
scalarList& weights
) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace cellCellStencils
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -51,6 +51,7 @@ namespace cellCellStencils
void Foam::cellCellStencils::trackingInverseDistance::markBoundaries void Foam::cellCellStencils::trackingInverseDistance::markBoundaries
( (
const fvMesh& mesh, const fvMesh& mesh,
const vector& smallVec,
const boundBox& bb, const boundBox& bb,
const labelVector& nDivs, const labelVector& nDivs,
@ -84,6 +85,9 @@ void Foam::cellCellStencils::trackingInverseDistance::markBoundaries
// Mark in voxel mesh // Mark in voxel mesh
boundBox faceBb(pp.points(), pp[i], false); boundBox faceBb(pp.points(), pp[i], false);
faceBb.min() -= smallVec;
faceBb.max() += smallVec;
if (bb.overlaps(faceBb)) if (bb.overlaps(faceBb))
{ {
voxelMeshSearch::fill voxelMeshSearch::fill
@ -116,6 +120,8 @@ void Foam::cellCellStencils::trackingInverseDistance::markBoundaries
// Mark in voxel mesh // Mark in voxel mesh
boundBox faceBb(pp.points(), pp[i], false); boundBox faceBb(pp.points(), pp[i], false);
faceBb.min() -= smallVec;
faceBb.max() += smallVec;
if (bb.overlaps(faceBb)) if (bb.overlaps(faceBb))
{ {
voxelMeshSearch::fill voxelMeshSearch::fill
@ -165,6 +171,9 @@ void Foam::cellCellStencils::trackingInverseDistance::markPatchesAsHoles
forAll(tgtCellMap, tgtCelli) forAll(tgtCellMap, tgtCelli)
{ {
label celli = tgtCellMap[tgtCelli]; label celli = tgtCellMap[tgtCelli];
boundBox cBb(allPoints, allCellPoints[celli], false);
cBb.min() -= smallVec_;
cBb.max() += smallVec_;
if if
( (
@ -172,7 +181,7 @@ void Foam::cellCellStencils::trackingInverseDistance::markPatchesAsHoles
( (
srcPatchBb, srcPatchBb,
srcDivs, srcDivs,
boundBox(allPoints, allCellPoints[celli], false), cBb,
srcPatchTypes, srcPatchTypes,
static_cast<unsigned int>(patchCellType::PATCH) static_cast<unsigned int>(patchCellType::PATCH)
) )
@ -231,13 +240,17 @@ void Foam::cellCellStencils::trackingInverseDistance::markPatchesAsHoles
forAll(tgtCellMap, tgtCelli) forAll(tgtCellMap, tgtCelli)
{ {
label celli = tgtCellMap[tgtCelli]; label celli = tgtCellMap[tgtCelli];
boundBox cBb(allPoints, allCellPoints[celli], false);
cBb.min() -= smallVec_;
cBb.max() += smallVec_;
if if
( (
voxelMeshSearch::overlaps voxelMeshSearch::overlaps
( (
srcPatchBb, srcPatchBb,
srcDivs, srcDivs,
boundBox(allPoints, allCellPoints[celli], false), cBb,
srcPatchTypes, srcPatchTypes,
static_cast<unsigned int>(patchCellType::PATCH) static_cast<unsigned int>(patchCellType::PATCH)
) )
@ -628,6 +641,7 @@ bool Foam::cellCellStencils::trackingInverseDistance::update()
markBoundaries markBoundaries
( (
meshParts_[zonei].subMesh(), meshParts_[zonei].subMesh(),
smallVec_,
patchBb[zonei][Pstream::myProcNo()], patchBb[zonei][Pstream::myProcNo()],
patchDivisions[zonei], patchDivisions[zonei],

View File

@ -77,6 +77,7 @@ protected:
static void markBoundaries static void markBoundaries
( (
const fvMesh& mesh, const fvMesh& mesh,
const vector& smallVec,
const boundBox& bb, const boundBox& bb,
const labelVector& nDivs, const labelVector& nDivs,

View File

@ -228,7 +228,10 @@ Foam::dynamicOversetFvMesh::dynamicOversetFvMesh(const IOobject& io)
: :
dynamicMotionSolverFvMesh(io), dynamicMotionSolverFvMesh(io),
active_(false) active_(false)
{} {
// Force loading zoneID field before time gets incremented
(void)cellCellStencil::zoneID(*this);
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //

View File

@ -38,6 +38,8 @@ SourceFiles
#include "dynamicMotionSolverFvMesh.H" #include "dynamicMotionSolverFvMesh.H"
#include "labelIOList.H" #include "labelIOList.H"
#include "fvMeshPrimitiveLduAddressing.H" #include "fvMeshPrimitiveLduAddressing.H"
#include "lduInterfaceFieldPtrsList.H"
#include "volFields.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -100,6 +102,14 @@ protected:
template<class GeoField> template<class GeoField>
void interpolate(GeoField& psi) const; void interpolate(GeoField& psi) const;
//- Freeze values at holes
template<class Type>
void freezeHoles(fvMatrix<Type>&) const;
//- Get scalar interfaces of certain type
template<class GeoField, class PatchType>
lduInterfaceFieldPtrsList scalarInterfaces(const GeoField& psi) const;
//- Add interpolation to matrix (coefficients) //- Add interpolation to matrix (coefficients)
template<class Type> template<class Type>
void addInterpolation(fvMatrix<Type>&) const; void addInterpolation(fvMatrix<Type>&) const;
@ -112,25 +122,6 @@ protected:
template<class GeoField> template<class GeoField>
static void correctCoupledBoundaryConditions(GeoField& fld); static void correctCoupledBoundaryConditions(GeoField& fld);
//- Use extended addressing
void active(const bool f) const
{
active_ = f;
if (active_)
{
DebugInfo<< "Switching to extended addressing with nFaces:"
<< primitiveLduAddr().lowerAddr().size()
<< endl;
}
else
{
DebugInfo<< "Switching to base addressing with nFaces:"
<< fvMesh::lduAddr().lowerAddr().size()
<< endl;
}
}
private: private:
@ -164,12 +155,6 @@ public:
// Extended addressing // Extended addressing
//- Use extended addressing
bool active() const
{
return active_;
}
//- Return extended ldu addressing //- Return extended ldu addressing
const fvMeshPrimitiveLduAddressing& primitiveLduAddr() const; const fvMeshPrimitiveLduAddressing& primitiveLduAddr() const;
@ -177,6 +162,37 @@ public:
// primitiveLduAddr // primitiveLduAddr
virtual const lduAddressing& lduAddr() const; virtual const lduAddressing& lduAddr() const;
//- Return old to new face addressing
const labelList& reverseFaceMap() const
{
return reverseFaceMap_;
}
//- Return true if using extended addressing
bool active() const
{
return active_;
}
//- Enable/disable extended addressing
void active(const bool f) const
{
active_ = f;
if (active_)
{
DebugInfo<< "Switching to extended addressing with nFaces:"
<< primitiveLduAddr().lowerAddr().size()
<< endl;
}
else
{
DebugInfo<< "Switching to base addressing with nFaces:"
<< fvMesh::lduAddr().lowerAddr().size()
<< endl;
}
}
// Overset // Overset

View File

@ -26,6 +26,7 @@ License
#include "volFields.H" #include "volFields.H"
#include "fvMatrix.H" #include "fvMatrix.H"
#include "cellCellStencilObject.H" #include "cellCellStencilObject.H"
#include "oversetFvPatchField.H"
// * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * * //
@ -77,41 +78,34 @@ void Foam::dynamicOversetFvMesh::interpolate(GeoField& psi) const
} }
//template<class T> template<class GeoField, class PatchType>
//void Foam::dynamicOversetFvMesh::setReference(fvMatrix<T>& m) const Foam::lduInterfaceFieldPtrsList
//{ Foam::dynamicOversetFvMesh::scalarInterfaces(const GeoField& psi) const
// const mapDistribute& map = cellInterpolationMap(); {
// const List<scalarList>& wghts = cellInterpolationWeights(); const typename GeoField::Boundary& bpsi = psi.boundaryField();
// const labelListList& stencil = cellStencil();
// const labelList& cellIDs = interpolationCells(); lduInterfaceFieldPtrsList interfaces(bpsi.size());
// const scalarList& factor = cellInterpolationWeight();
// forAll(interfaces, patchi)
// Field<T> work(m.psi()); {
// map.mapDistributeBase::distribute(work, UPstream::msgType()+1); if
// (
// forAll(cellIDs, i) isA<lduInterfaceField>(bpsi[patchi])
// { && isA<PatchType>(bpsi[patchi])
// label celli = cellIDs[i]; )
// {
// const scalarList& w = wghts[celli]; interfaces.set
// const labelList& nbrs = stencil[celli]; (
// const scalar f = factor[celli]; patchi,
// &refCast<const lduInterfaceField>
// //Pout<< "Interpolating " << celli << " from values:" << endl; (
// T s(pTraits<T>::zero); bpsi[patchi]
// forAll(nbrs, nbrI) )
// { );
// //Pout<< " " << work[nbrs[nbrI]] }
// // << " from slot " << nbrs[nbrI] << endl; }
// s += w[nbrI]*work[nbrs[nbrI]]; return interfaces;
// } }
// //Pout<< "Interpolated value:" << s << endl;
// const T oldPsi = m.psi()[celli];
// m.setReference(celli, (1.0-f)*oldPsi + f*s, true);
// Pout<< "psi was:" << oldPsi << " now forcing to:"
// << (1.0-f)*oldPsi + f*s << endl;
// }
//}
template<class Type> template<class Type>
@ -185,6 +179,7 @@ void Foam::dynamicOversetFvMesh::addInterpolation(fvMatrix<Type>& m) const
} }
} }
forAll(m.internalCoeffs(), patchI) forAll(m.internalCoeffs(), patchI)
{ {
const labelUList& fc = addr.patchAddr(patchI); const labelUList& fc = addr.patchAddr(patchI);
@ -209,6 +204,76 @@ void Foam::dynamicOversetFvMesh::addInterpolation(fvMatrix<Type>& m) const
} }
} }
// NOTE: For a non-scalar matrix, in the function fvMatrix::solveSegregated
// it uses updateInterfaceMatrix to correct for remote source contributions.
// This unfortunately also triggers the overset interpolation which then
// produces a non-zero source for interpolated cells.
// The procedure below calculates this contribution 'correctionSource'
// and substracts it from the source later in order to compensate.
Field<Type> correctionSource(diag.size(), pTraits<Type>::zero);
if (pTraits<Type>::nComponents > 1)
{
typedef GeometricField<Type, fvPatchField, volMesh> GeoField;
typename pTraits<Type>::labelType validComponents
(
this->template validComponents<Type>()
);
// Get all the overset lduInterfaces
lduInterfaceFieldPtrsList interfaces
(
scalarInterfaces<GeoField, oversetFvPatchField<Type>>
(
m.psi()
)
);
const Field<Type>& psiInt = m.psi().primitiveField();
for (direction cmpt=0; cmpt<pTraits<Type>::nComponents; cmpt++)
{
if (component(validComponents, cmpt) != -1)
{
const scalarField psiCmpt(psiInt.component(cmpt));
scalarField corrSourceCmpt(correctionSource.component(cmpt));
forAll(interfaces, patchi)
{
if (interfaces.set(patchi))
{
interfaces[patchi].initInterfaceMatrixUpdate
(
corrSourceCmpt,
true,
psiCmpt,
m.boundaryCoeffs()[patchi].component(cmpt),
cmpt,
Pstream::defaultCommsType
);
}
}
forAll(interfaces, patchi)
{
if (interfaces.set(patchi))
{
interfaces[patchi].updateInterfaceMatrix
(
corrSourceCmpt,
true,
psiCmpt,
m.boundaryCoeffs()[patchi].component(cmpt),
cmpt,
Pstream::defaultCommsType
);
}
}
correctionSource.replace(cmpt, corrSourceCmpt);
}
}
}
// Modify matrix // Modify matrix
@ -271,12 +336,14 @@ void Foam::dynamicOversetFvMesh::addInterpolation(fvMatrix<Type>& m) const
{ {
// Create interpolation stencil. Leave any non-local contributions // Create interpolation stencil. Leave any non-local contributions
// to be done by oversetFvPatchField updateMatrixInterface // to be done by oversetFvPatchField updateMatrixInterface
// 'correctionSource' is only applied for vector and higher
// fvMatrix; it is zero for scalar matrices (see above).
diag[celli] *= (1.0-f); diag[celli] *= (1.0-f);
diag[celli] += normalisation*f; diag[celli] += normalisation*f;
source[celli] *= (1.0-f); source[celli] *= (1.0-f);
source[celli] += normalisation*f*pTraits<Type>::zero; // dummy source[celli] -= correctionSource[celli];
//Pout<< "Interpolating " << celli << " with factor:" << f //Pout<< "Interpolating " << celli << " with factor:" << f
// << " new diag:" << diag[celli] // << " new diag:" << diag[celli]
@ -328,6 +395,39 @@ Foam::SolverPerformance<Type> Foam::dynamicOversetFvMesh::solve
const dictionary& dict const dictionary& dict
) const ) const
{ {
// Check we're running with bcs that can handle implicit matrix manipulation
const typename GeometricField<Type, fvPatchField, volMesh>::Boundary bpsi =
m.psi().boundaryField();
bool hasOverset = false;
forAll(bpsi, patchi)
{
if (isA<oversetFvPatchField<Type>>(bpsi[patchi]))
{
hasOverset = true;
break;
}
}
if (!hasOverset)
{
if (debug)
{
Pout<< "dynamicOversetFvMesh::solve() :"
<< " bypassing matrix adjustment for field " << m.psi().name()
<< endl;
}
return dynamicMotionSolverFvMesh::solve(m, dict);
}
if (debug)
{
Pout<< "dynamicOversetFvMesh::solve() :"
<< " adjusting matrix for interpolation for field "
<< m.psi().name() << endl;
}
// Switch to extended addressing (requires mesh::update() having been // Switch to extended addressing (requires mesh::update() having been
// called) // called)
active(true); active(true);
@ -346,8 +446,7 @@ Foam::SolverPerformance<Type> Foam::dynamicOversetFvMesh::solve
// Use lower level solver // Use lower level solver
SolverPerformance<Type> s(dynamicMotionSolverFvMesh::solve(m, dict)); SolverPerformance<Type> s(dynamicMotionSolverFvMesh::solve(m, dict));
// Reset matrix (shuffle faces into original order) // Restore matrix
//resetMatrix(m);
m.upper().transfer(oldUpper); m.upper().transfer(oldUpper);
m.lower().transfer(oldLower); m.lower().transfer(oldLower);
m.internalCoeffs().transfer(oldInt); m.internalCoeffs().transfer(oldInt);

View File

@ -24,6 +24,8 @@ License
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "volFields.H" #include "volFields.H"
#include "cellCellStencil.H"
#include "dynamicOversetFvMesh.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
@ -34,9 +36,7 @@ Foam::oversetFvPatchField<Type>::oversetFvPatchField
const DimensionedField<Type, volMesh>& iF const DimensionedField<Type, volMesh>& iF
) )
: :
LduInterfaceField<Type>(refCast<const oversetFvPatch>(p)), semiImplicitOversetFvPatchField<Type>(p, iF)
zeroGradientFvPatchField<Type>(p, iF),
oversetPatch_(refCast<const oversetFvPatch>(p))
{} {}
@ -49,21 +49,8 @@ Foam::oversetFvPatchField<Type>::oversetFvPatchField
const fvPatchFieldMapper& mapper const fvPatchFieldMapper& mapper
) )
: :
LduInterfaceField<Type>(refCast<const oversetFvPatch>(p)), semiImplicitOversetFvPatchField<Type>(ptf, p, iF, mapper)
zeroGradientFvPatchField<Type>(ptf, p, iF, mapper), {}
oversetPatch_(refCast<const oversetFvPatch>(p))
{
if (!isA<oversetFvPatch>(this->patch()))
{
FatalErrorInFunction
<< " patch type '" << p.type()
<< "' not constraint type '" << typeName << "'"
<< "\n for patch " << p.name()
<< " of field " << this->internalField().name()
<< " in file " << this->internalField().objectPath()
<< exit(FatalIOError);
}
}
template<class Type> template<class Type>
@ -74,26 +61,8 @@ Foam::oversetFvPatchField<Type>::oversetFvPatchField
const dictionary& dict const dictionary& dict
) )
: :
LduInterfaceField<Type>(refCast<const oversetFvPatch>(p)), semiImplicitOversetFvPatchField<Type>(p, iF, dict)
zeroGradientFvPatchField<Type>(p, iF, dict), {}
oversetPatch_(refCast<const oversetFvPatch>(p))
{
if (!isA<oversetFvPatch>(p))
{
FatalIOErrorInFunction(dict)
<< " patch type '" << p.type()
<< "' not constraint type '" << typeName << "'"
<< "\n for patch " << p.name()
<< " of field " << this->internalField().name()
<< " in file " << this->internalField().objectPath()
<< exit(FatalIOError);
}
if (!dict.found("value") && this->coupled())
{
this->evaluate(Pstream::commsTypes::blocking);
}
}
template<class Type> template<class Type>
@ -102,9 +71,7 @@ Foam::oversetFvPatchField<Type>::oversetFvPatchField
const oversetFvPatchField<Type>& ptf const oversetFvPatchField<Type>& ptf
) )
: :
LduInterfaceField<Type>(ptf.oversetPatch_), semiImplicitOversetFvPatchField<Type>(ptf)
zeroGradientFvPatchField<Type>(ptf),
oversetPatch_(ptf.oversetPatch_)
{} {}
@ -115,22 +82,19 @@ Foam::oversetFvPatchField<Type>::oversetFvPatchField
const DimensionedField<Type, volMesh>& iF const DimensionedField<Type, volMesh>& iF
) )
: :
LduInterfaceField<Type>(ptf.oversetPatch_), semiImplicitOversetFvPatchField<Type>(ptf, iF)
zeroGradientFvPatchField<Type>(ptf, iF),
oversetPatch_(ptf.oversetPatch_)
{} {}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Type> template<class Type>
void Foam::oversetFvPatchField<Type>::initEvaluate void Foam::oversetFvPatchField<Type>::initEvaluate
( (
const Pstream::commsTypes commsType const Pstream::commsTypes commsType
) )
{ {
if (oversetPatch_.master()) if (this->oversetPatch_.master())
{ {
// Trigger interpolation // Trigger interpolation
const fvMesh& mesh = this->internalField().mesh(); const fvMesh& mesh = this->internalField().mesh();
@ -139,24 +103,14 @@ void Foam::oversetFvPatchField<Type>::initEvaluate
if (&mesh.lduAddr() != &mesh.fvMesh::lduAddr()) if (&mesh.lduAddr() != &mesh.fvMesh::lduAddr())
{ {
// Running extended addressing. Interpolate always. // Running extended addressing. Flux correction already done
// in the linear solver (through the initUpdateInterfaceMatrix
// method below)
if (debug) if (debug)
{ {
Info<< "Interpolating solved-for field " << fldName << endl; Info<< "Skipping overset interpolation for solved-for field "
<< fldName << endl;
} }
// Interpolate without bc update (since would trigger infinite
// recursion back to oversetFvPatchField<Type>::evaluate)
// The only problem is bcs that use the new cell values
// (e.g. zeroGradient, processor). These need to appear -after-
// the 'overset' bc.
mesh.interpolate
(
const_cast<Field<Type>&>
(
this->primitiveField()
)
);
} }
else if else if
( (
@ -206,31 +160,6 @@ void Foam::oversetFvPatchField<Type>::initEvaluate
} }
template<class Type>
void Foam::oversetFvPatchField<Type>::evaluate(const Pstream::commsTypes)
{
if (!this->updated())
{
this->updateCoeffs();
}
zeroGradientFvPatchField<Type>::evaluate();
}
template<class Type>
void Foam::oversetFvPatchField<Type>::initInterfaceMatrixUpdate
(
scalarField& result,
const bool add,
const scalarField& psiInternal,
const scalarField& coeffs,
const direction cmpt,
const Pstream::commsTypes commsType
) const
{}
template<class Type> template<class Type>
void Foam::oversetFvPatchField<Type>::updateInterfaceMatrix void Foam::oversetFvPatchField<Type>::updateInterfaceMatrix
( (
@ -243,7 +172,10 @@ void Foam::oversetFvPatchField<Type>::updateInterfaceMatrix
) const ) const
{ {
// Add remote values // Add remote values
if (oversetPatch_.master())
const oversetFvPatch& ovp = this->oversetPatch_;
if (ovp.master())
{ {
const fvMesh& mesh = this->patch().boundaryMesh().mesh(); const fvMesh& mesh = this->patch().boundaryMesh().mesh();
@ -251,11 +183,10 @@ void Foam::oversetFvPatchField<Type>::updateInterfaceMatrix
// TBD. This should be cleaner. // TBD. This should be cleaner.
if (&mesh.lduAddr() == &mesh.fvMesh::lduAddr()) if (&mesh.lduAddr() == &mesh.fvMesh::lduAddr())
{ {
//Pout<< "** not running extended addressing..." << endl;
return; return;
} }
const labelListList& stencil = oversetPatch_.stencil(); const labelListList& stencil = ovp.stencil();
if (stencil.size() != psiInternal.size()) if (stencil.size() != psiInternal.size())
{ {
@ -263,12 +194,11 @@ void Foam::oversetFvPatchField<Type>::updateInterfaceMatrix
<< " stencil:" << stencil.size() << exit(FatalError); << " stencil:" << stencil.size() << exit(FatalError);
} }
const mapDistribute& map = oversetPatch_.cellInterpolationMap(); const mapDistribute& map = ovp.cellInterpolationMap();
const List<scalarList>& wghts = const List<scalarList>& wghts = ovp.cellInterpolationWeights();
oversetPatch_.cellInterpolationWeights(); const labelList& cellIDs = ovp.interpolationCells();
const labelList& cellIDs = oversetPatch_.interpolationCells(); const scalarList& factor = ovp.cellInterpolationWeight();
const scalarList& factor = oversetPatch_.cellInterpolationWeight(); const scalarField& normalisation = ovp.normalisation();
const scalarField& normalisation = oversetPatch_.normalisation();
// Since we're inside initEvaluate/evaluate there might be processor // Since we're inside initEvaluate/evaluate there might be processor
@ -306,41 +236,4 @@ void Foam::oversetFvPatchField<Type>::updateInterfaceMatrix
} }
template<class Type>
void Foam::oversetFvPatchField<Type>::initInterfaceMatrixUpdate
(
Field<Type>&,
const bool add,
const Field<Type>&,
const scalarField&,
const Pstream::commsTypes commsType
) const
{
NotImplemented;
}
template<class Type>
void Foam::oversetFvPatchField<Type>::updateInterfaceMatrix
(
Field<Type>& result,
const bool add,
const Field<Type>& psiInternal,
const scalarField&,
const Pstream::commsTypes
) const
{
NotImplemented;
}
template<class Type>
void Foam::oversetFvPatchField<Type>::write(Ostream& os) const
{
zeroGradientFvPatchField<Type>::write(os);
// Make sure to write the value for ease of postprocessing.
this->writeEntry("value", os);
}
// ************************************************************************* // // ************************************************************************* //

View File

@ -28,8 +28,9 @@ Group
grpCoupledBoundaryConditions grpCoupledBoundaryConditions
Description Description
Boundary condition for use on overset patches. To be run in combination
SeeAlso with special dynamicFvMesh type that inserts local contributions into
the matrix. This boundary condition adds the remote contributions.
SourceFiles SourceFiles
oversetFvPatchField.C oversetFvPatchField.C
@ -39,9 +40,7 @@ SourceFiles
#ifndef oversetFvPatchField_H #ifndef oversetFvPatchField_H
#define oversetFvPatchField_H #define oversetFvPatchField_H
#include "oversetFvPatch.H" #include "semiImplicitOversetFvPatchField.H"
#include "zeroGradientFvPatchField.H"
#include "LduInterfaceField.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -55,18 +54,8 @@ namespace Foam
template<class Type> template<class Type>
class oversetFvPatchField class oversetFvPatchField
: :
public LduInterfaceField<Type>, public semiImplicitOversetFvPatchField<Type>
public zeroGradientFvPatchField<Type>
{ {
// Private data
//- Local reference cast into the overset patch
const oversetFvPatch& oversetPatch_;
//- Master patch ID
mutable label masterPatchID_;
public: public:
//- Runtime type information //- Runtime type information
@ -133,34 +122,11 @@ public:
// Member functions // Member functions
// Access
//- Return local reference cast into the cyclic AMI patch
const oversetFvPatch& oversetPatch() const
{
return oversetPatch_;
}
// Evaluation functions // Evaluation functions
//- Initialise the evaluation of the patch field //- Initialise the evaluation of the patch field
virtual void initEvaluate(const Pstream::commsTypes commsType); virtual void initEvaluate(const Pstream::commsTypes commsType);
//- Evaluate the patch field
virtual void evaluate(const Pstream::commsTypes commsType);
//- Initialise neighbour matrix update
virtual void initInterfaceMatrixUpdate
(
scalarField&,
const bool add,
const scalarField&,
const scalarField&,
const direction,
const Pstream::commsTypes commsType
) const;
//- Update result field based on interface functionality //- Update result field based on interface functionality
virtual void updateInterfaceMatrix virtual void updateInterfaceMatrix
( (
@ -171,32 +137,6 @@ public:
const direction cmpt, const direction cmpt,
const Pstream::commsTypes commsType const Pstream::commsTypes commsType
) const; ) const;
//- Initialise neighbour matrix update
virtual void initInterfaceMatrixUpdate
(
Field<Type>&,
const bool add,
const Field<Type>&,
const scalarField&,
const Pstream::commsTypes commsType
) const;
//- Update result field based on interface functionality
virtual void updateInterfaceMatrix
(
Field<Type>&,
const bool add,
const Field<Type>&,
const scalarField&,
const Pstream::commsTypes commsType
) const;
// I-O
//- Write
virtual void write(Ostream& os) const;
}; };

View File

@ -52,12 +52,16 @@ class oversetGAMGInterfaceField
: :
public GAMGInterfaceField public GAMGInterfaceField
{ {
// Private data protected:
// Protected data
//- Local reference cast into the interface //- Local reference cast into the interface
const oversetGAMGInterface& oversetInterface_; const oversetGAMGInterface& oversetInterface_;
private:
// Private Member Functions // Private Member Functions
//- Disallow default bitwise copy construct //- Disallow default bitwise copy construct

View File

@ -0,0 +1,272 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2017 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 <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "volFields.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class Type>
Foam::semiImplicitOversetFvPatchField<Type>::semiImplicitOversetFvPatchField
(
const fvPatch& p,
const DimensionedField<Type, volMesh>& iF
)
:
LduInterfaceField<Type>(refCast<const oversetFvPatch>(p)),
zeroGradientFvPatchField<Type>(p, iF),
oversetPatch_(refCast<const oversetFvPatch>(p))
{}
template<class Type>
Foam::semiImplicitOversetFvPatchField<Type>::semiImplicitOversetFvPatchField
(
const semiImplicitOversetFvPatchField<Type>& ptf,
const fvPatch& p,
const DimensionedField<Type, volMesh>& iF,
const fvPatchFieldMapper& mapper
)
:
LduInterfaceField<Type>(refCast<const oversetFvPatch>(p)),
zeroGradientFvPatchField<Type>(ptf, p, iF, mapper),
oversetPatch_(refCast<const oversetFvPatch>(p))
{
if (!isA<oversetFvPatch>(this->patch()))
{
FatalErrorInFunction
<< " patch type '" << p.type()
<< "' not constraint type '" << typeName << "'"
<< "\n for patch " << p.name()
<< " of field " << this->internalField().name()
<< " in file " << this->internalField().objectPath()
<< exit(FatalIOError);
}
}
template<class Type>
Foam::semiImplicitOversetFvPatchField<Type>::semiImplicitOversetFvPatchField
(
const fvPatch& p,
const DimensionedField<Type, volMesh>& iF,
const dictionary& dict
)
:
LduInterfaceField<Type>(refCast<const oversetFvPatch>(p)),
zeroGradientFvPatchField<Type>(p, iF, dict),
oversetPatch_(refCast<const oversetFvPatch>(p))
{
if (!isA<oversetFvPatch>(p))
{
FatalIOErrorInFunction(dict)
<< " patch type '" << p.type()
<< "' not constraint type '" << typeName << "'"
<< "\n for patch " << p.name()
<< " of field " << this->internalField().name()
<< " in file " << this->internalField().objectPath()
<< exit(FatalIOError);
}
if (!dict.found("value") && this->coupled())
{
this->evaluate(Pstream::commsTypes::blocking);
}
}
template<class Type>
Foam::semiImplicitOversetFvPatchField<Type>::semiImplicitOversetFvPatchField
(
const semiImplicitOversetFvPatchField<Type>& ptf
)
:
LduInterfaceField<Type>(ptf.oversetPatch_),
zeroGradientFvPatchField<Type>(ptf),
oversetPatch_(ptf.oversetPatch_)
{}
template<class Type>
Foam::semiImplicitOversetFvPatchField<Type>::semiImplicitOversetFvPatchField
(
const semiImplicitOversetFvPatchField<Type>& ptf,
const DimensionedField<Type, volMesh>& iF
)
:
LduInterfaceField<Type>(ptf.oversetPatch_),
zeroGradientFvPatchField<Type>(ptf, iF),
oversetPatch_(ptf.oversetPatch_)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Type>
void Foam::semiImplicitOversetFvPatchField<Type>::evaluate
(
const Pstream::commsTypes
)
{
if (debug)
{
Pout<< FUNCTION_NAME << " field " << this->internalField().name()
<< " patch " << this->patch().name() << endl;
}
if (!this->updated())
{
this->updateCoeffs();
}
zeroGradientFvPatchField<Type>::evaluate();
}
template<class Type>
void Foam::semiImplicitOversetFvPatchField<Type>::initEvaluate
(
const Pstream::commsTypes commsType
)
{
if (debug)
{
Pout<< FUNCTION_NAME << " field " << this->internalField().name()
<< " patch " << this->patch().name() << endl;
}
if (this->oversetPatch().master())
{
// Trigger interpolation
const fvMesh& mesh = this->internalField().mesh();
//const dictionary& fvSchemes = mesh.schemesDict();
const word& fldName = this->internalField().name();
if (&mesh.lduAddr() != &mesh.fvMesh::lduAddr())
{
// Running extended addressing so called from within fvMatrix::solve
FatalErrorInFunction
<< "Running extended addressing is not allowed when solving "
<< fldName
<< " Please choose a dynamicFvMesh without matrix adaptation"
<< exit(FatalError);
}
else
{
if (debug)
{
Info<< "Interpolating field " << fldName << endl;
}
// Interpolate without bc update (since would trigger infinite
// recursion back to
// semiImplicitOversetFvPatchField<Type>::evaluate)
// The only problem is bcs that use the new cell values
// (e.g. zeroGradient, processor). These need to appear -after-
// the 'overset' bc.
mesh.interpolate
(
const_cast<Field<Type>&>
(
this->primitiveField()
)
);
}
}
}
template<class Type>
void Foam::semiImplicitOversetFvPatchField<Type>::updateInterfaceMatrix
(
scalarField& result,
const bool add,
const scalarField& psiInternal,
const scalarField& coeffs,
const direction cmpt,
const Pstream::commsTypes
) const
{
if (debug)
{
Pout<< FUNCTION_NAME << " field " << this->internalField().name()
<< " patch " << this->patch().name() << endl;
}
const oversetFvPatch& ovp = this->oversetPatch();
// Set all interpolated cells
if (ovp.master())
{
const labelListList& stencil = ovp.stencil();
if (stencil.size() != psiInternal.size())
{
FatalErrorInFunction << "psiInternal:" << psiInternal.size()
<< " stencil:" << stencil.size() << exit(FatalError);
}
const mapDistribute& map = ovp.cellInterpolationMap();
const List<scalarList>& wghts = ovp.cellInterpolationWeights();
const labelList& cellIDs = ovp.interpolationCells();
//const scalarList& factor = ovp.cellInterpolationWeight();
// Since we're inside initEvaluate/evaluate there might be processor
// comms underway. Change the tag we use.
scalarField work(psiInternal);
map.mapDistributeBase::distribute(work, UPstream::msgType()+1);
forAll(cellIDs, i)
{
label celli = cellIDs[i];
const scalarList& w = wghts[celli];
const labelList& nbrs = stencil[celli];
//scalar f = factor[celli];
scalar s(0.0);
forAll(nbrs, nbrI)
{
s += w[nbrI]*work[nbrs[nbrI]];
}
//Pout<< "cell:" << celli << " interpolated value:" << s << endl;
result[celli] = s; //(1.0-f)*result[celli] + f*s;
}
}
}
template<class Type>
void Foam::semiImplicitOversetFvPatchField<Type>::write(Ostream& os) const
{
zeroGradientFvPatchField<Type>::write(os);
// Make sure to write the value for ease of postprocessing.
this->writeEntry("value", os);
}
// ************************************************************************* //

View File

@ -0,0 +1,207 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2017 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 <http://www.gnu.org/licenses/>.
Class
Foam::semiImplicitOversetFvPatchField
Group
grpCoupledBoundaryConditions
Description
Boundary condition for use on overset patches. Implements update of
interpolated cells inside the linear solvers.
SeeAlso
SourceFiles
semiImplicitOversetFvPatchField.C
\*---------------------------------------------------------------------------*/
#ifndef semiImplicitOversetFvPatchField_H
#define semiImplicitOversetFvPatchField_H
#include "oversetFvPatch.H"
#include "zeroGradientFvPatchField.H"
#include "LduInterfaceField.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class semiImplicitOversetFvPatchField Declaration
\*---------------------------------------------------------------------------*/
template<class Type>
class semiImplicitOversetFvPatchField
:
public LduInterfaceField<Type>,
public zeroGradientFvPatchField<Type>
{
protected:
// Protected data
//- Local reference cast into the overset patch
const oversetFvPatch& oversetPatch_;
//- Master patch ID
mutable label masterPatchID_;
public:
//- Runtime type information
TypeName("semiImplicitOverset");
// Constructors
//- Construct from patch and internal field
semiImplicitOversetFvPatchField
(
const fvPatch&,
const DimensionedField<Type, volMesh>&
);
//- Construct from patch, internal field and dictionary
semiImplicitOversetFvPatchField
(
const fvPatch&,
const DimensionedField<Type, volMesh>&,
const dictionary&
);
//- Construct by mapping given semiImplicitOversetFvPatchField onto a
// new patch
semiImplicitOversetFvPatchField
(
const semiImplicitOversetFvPatchField<Type>&,
const fvPatch&,
const DimensionedField<Type, volMesh>&,
const fvPatchFieldMapper&
);
//- Construct as copy
semiImplicitOversetFvPatchField
(
const semiImplicitOversetFvPatchField<Type>&
);
//- Construct and return a clone
virtual tmp<fvPatchField<Type> > clone() const
{
return tmp<fvPatchField<Type> >
(
new semiImplicitOversetFvPatchField<Type>(*this)
);
}
//- Construct as copy setting internal field reference
semiImplicitOversetFvPatchField
(
const semiImplicitOversetFvPatchField<Type>&,
const DimensionedField<Type, volMesh>&
);
//- Construct and return a clone setting internal field reference
virtual tmp<fvPatchField<Type> > clone
(
const DimensionedField<Type, volMesh>& iF
) const
{
return tmp<fvPatchField<Type> >
(
new semiImplicitOversetFvPatchField<Type>(*this, iF)
);
}
// Member functions
// Access
//- Return local reference cast into the cyclic AMI patch
const oversetFvPatch& oversetPatch() const
{
return oversetPatch_;
}
// Evaluation functions
//- Evaluate the patch field
virtual void evaluate(const Pstream::commsTypes commsType);
//- Initialise the evaluation of the patch field
virtual void initEvaluate(const Pstream::commsTypes commsType);
//- Update result field based on interface functionality
virtual void updateInterfaceMatrix
(
scalarField& result,
const bool add,
const scalarField& psiInternal,
const scalarField& coeffs,
const direction cmpt,
const Pstream::commsTypes commsType
) const;
//- Update result field based on interface functionality
virtual void updateInterfaceMatrix
(
Field<Type>&,
const bool add,
const Field<Type>&,
const scalarField&,
const Pstream::commsTypes commsType
) const
{
NotImplemented;
}
// I-O
//- Write
virtual void write(Ostream& os) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
# include "semiImplicitOversetFvPatchField.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,43 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016-2017 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 <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "semiImplicitOversetFvPatchFields.H"
#include "addToRunTimeSelectionTable.H"
#include "volFields.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
makePatchFields(semiImplicitOverset);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* //

View File

@ -0,0 +1,49 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2017 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 <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#ifndef semiImplicitOversetFvPatchFields_H
#define semiImplicitOversetFvPatchFields_H
#include "semiImplicitOversetFvPatchField.H"
#include "fieldTypes.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
makePatchTypeFieldTypedefs(semiImplicitOverset);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,122 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2017 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 <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "semiImplicitOversetGAMGInterfaceField.H"
#include "addToRunTimeSelectionTable.H"
#include "lduMatrix.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(semiImplicitOversetGAMGInterfaceField, 0);
addToRunTimeSelectionTable
(
GAMGInterfaceField,
semiImplicitOversetGAMGInterfaceField,
lduInterfaceField
);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::semiImplicitOversetGAMGInterfaceField::
semiImplicitOversetGAMGInterfaceField
(
const GAMGInterface& GAMGCp,
const lduInterfaceField& fineInterface
)
:
oversetGAMGInterfaceField(GAMGCp, fineInterface)
{}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::semiImplicitOversetGAMGInterfaceField::
~semiImplicitOversetGAMGInterfaceField()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::semiImplicitOversetGAMGInterfaceField::updateInterfaceMatrix
(
scalarField& result,
const bool add,
const scalarField& psiInternal,
const scalarField& coeffs,
const direction cmpt,
const Pstream::commsTypes commsType
) const
{
// Add remote values
if (oversetInterface_.master())
{
const labelListList& stencil = oversetInterface_.stencil();
if (stencil.size() != psiInternal.size())
{
FatalErrorInFunction << "psiInternal:" << psiInternal.size()
<< " stencil:" << stencil.size() << exit(FatalError);
}
const mapDistribute& map = oversetInterface_.cellInterpolationMap();
const List<scalarList>& wghts =
oversetInterface_.cellInterpolationWeights();
const labelList& cellIDs = oversetInterface_.interpolationCells();
const scalarList& factor = oversetInterface_.cellInterpolationWeight();
const scalarField& normalisation = oversetInterface_.normalisation();
scalarField work(psiInternal);
map.mapDistributeBase::distribute(work, UPstream::msgType()+1);
forAll(cellIDs, i)
{
label celli = cellIDs[i];
const scalarList& w = wghts[celli];
const labelList& nbrs = stencil[celli];
const scalar f = factor[celli];
scalar s(0.0);
forAll(nbrs, nbrI)
{
label slotI = nbrs[nbrI];
s += w[nbrI]*work[slotI];
}
if (add)
{
s = -1.0*s;
}
result[celli] += normalisation[celli]*f*s;
}
}
}
// ************************************************************************* //

View File

@ -0,0 +1,108 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2017 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 <http://www.gnu.org/licenses/>.
Class
Foam::semiImplicitOversetGAMGInterfaceField
Description
GAMG agglomerated processor interface field.
SourceFiles
processorGAMGInterfaceField.C
\*---------------------------------------------------------------------------*/
#ifndef semiImplicitOversetGAMGInterfaceField_H
#define semiImplicitOversetGAMGInterfaceField_H
#include "oversetGAMGInterfaceField.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class semiImplicitOversetGAMGInterfaceField Declaration
\*---------------------------------------------------------------------------*/
class semiImplicitOversetGAMGInterfaceField
:
public oversetGAMGInterfaceField
{
// Private Member Functions
//- Disallow default bitwise copy construct
semiImplicitOversetGAMGInterfaceField
(
const semiImplicitOversetGAMGInterfaceField&
);
//- Disallow default bitwise assignment
void operator=(const semiImplicitOversetGAMGInterfaceField&);
public:
//- Runtime type information
TypeName("semiImplicitOverset");
// Constructors
//- Construct from GAMG interface and fine level interface field
semiImplicitOversetGAMGInterfaceField
(
const GAMGInterface& GAMGCp,
const lduInterfaceField& fineInterface
);
//- Destructor
virtual ~semiImplicitOversetGAMGInterfaceField();
// Member Functions
//- Update result field based on interface functionality
virtual void updateInterfaceMatrix
(
scalarField& result,
const bool add,
const scalarField& psiInternal,
const scalarField& coeffs,
const direction cmpt,
const Pstream::commsTypes commsType
) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -57,6 +57,9 @@ snGradSchemes
oversetInterpolation oversetInterpolation
{ {
method inverseDistance; method inverseDistance;
searchBox (0 0 0)(0.01 0.01 0.01);
searchBoxDivisions (100 100 1);
} }
fluxRequired fluxRequired

View File

@ -16,11 +16,11 @@ FoamFile
numberOfSubdomains 8; numberOfSubdomains 8;
method hierarchical; method scotch; //hierarchical;
coeffs coeffs
{ {
n (8 1 1); n (4 2 1);
//delta 0.001; // default=0.001 //delta 0.001; // default=0.001
//order xyz; // default=xzy //order xyz; // default=xzy
} }

View File

@ -60,6 +60,7 @@ solvers
SIMPLE SIMPLE
{ {
momentumPredictor true;
nOuterCorrectors 1; nOuterCorrectors 1;
nCorrectors 2; nCorrectors 2;
nNonOrthogonalCorrectors 0; nNonOrthogonalCorrectors 0;

View File

@ -29,8 +29,8 @@ solvers
"alpha.water.*" "alpha.water.*"
{ {
nAlphaCorr 2; nAlphaCorr 3;
nAlphaSubCycles 1; nAlphaSubCycles 2;
cAlpha 1; cAlpha 1;
icAlpha 0; icAlpha 0;
@ -84,6 +84,10 @@ PIMPLE
ddtCorr yes; ddtCorr yes;
correctPhi no; correctPhi no;
massFluxInterpolation no;
moveMeshOuterCorrectors no;
turbOnFinalIterOnly no;
oversetAdjustPhi no; oversetAdjustPhi no;