ENH: overset: insert remote interpolation into lduMatrix

All remote contributions to interpolation stencils now
get added as 'processor' type lduInterfaces. This guarantees
a consistent matrix, e.g. initial residual is normalised to 1.

Second change is the normalisation of the interpolation discretisation
which uses the diagonal from the unmodified equation. This helps
GAMG.
This commit is contained in:
mattijs 2019-05-02 16:49:48 +01:00 committed by Andrew Heather
parent c924a3639c
commit 912009c458
26 changed files with 2617 additions and 652 deletions

View File

@ -69,7 +69,7 @@ void printInfo(const sliceCoeffs& coeffs)
const auto endIter = range.cend();
for (const label i : {-1, (range.size()/2), range.size()})
for (const label i : {label(-1), (range.size()/2), range.size()})
{
const auto iter = range.at(i);

View File

@ -13,23 +13,27 @@ dynamicOversetFvMesh/dynamicOversetFvMesh.C
fvMeshPrimitiveLduAddressing/fvMeshPrimitiveLduAddressing.C
oversetPolyPatch/oversetPolyPatch.C
oversetPolyPatch/oversetLduInterface.C
oversetPolyPatch/oversetFvPatch.C
oversetPolyPatch/oversetFvPatchFields.C
oversetPolyPatch/oversetFvsPatchFields.C
oversetPolyPatch/oversetGAMGInterface.C
oversetPolyPatch/oversetGAMGInterfaceField.C
oversetPolyPatch/oversetPointPatch.C
oversetPolyPatch/oversetPointPatchFields.C
/*
oversetPolyPatch/semiImplicitOversetFvPatchFields.C
oversetPolyPatch/oversetLduInterface.C
oversetPolyPatch/oversetGAMGInterface.C
oversetPolyPatch/oversetGAMGInterfaceField.C
oversetPolyPatch/semiImplicitOversetGAMGInterfaceField.C
*/
oversetAdjustPhi/oversetAdjustPhi.C
regionsToCell/regionsToCell.C
lduPrimitiveProcessorInterface/lduPrimitiveProcessorInterface.C
lduPrimitiveProcessorInterface/calculatedProcessorFvPatchFields.C
lduPrimitiveProcessorInterface/GAMG/calculatedProcessorGAMGInterface.C
lduPrimitiveProcessorInterface/GAMG/calculatedProcessorGAMGInterfaceField.C
LIB = $(FOAM_LIBBIN)/liboverset

View File

@ -91,41 +91,168 @@ bool Foam::dynamicOversetFvMesh::updateAddressing() const
<< " nExtraFaces:" << nExtraFaces << endl;
}
// Extract relevant remote processors
labelList nbrProcs(localFaceCells.size());
// Now for the tricky bits. We want to hand out processor faces according
// to the localFaceCells/remoteFaceCells. Ultimately we need
// per entry in stencil:
// - the patch (or -1 for internal faces)
// - the face (is either an internal face index or a patch face index)
stencilPatches_.setSize(stencilFaces_.size());
// Per processor to owner (local)/neighbour (remote)
List<DynamicList<label>> procOwner(Pstream::nProcs());
List<DynamicList<label>> dynProcNeighbour(Pstream::nProcs());
forAll(stencil, celli)
{
label nbrI = 0;
forAll(localFaceCells, procI)
const labelList& nbrs = stencil[celli];
stencilPatches_[celli].setSize(nbrs.size(), -1);
forAll(nbrs, nbri)
{
if (localFaceCells[procI].size())
const label nbrCelli = nbrs[nbri];
if (stencilFaces_[celli][nbri] == -1)
{
//Pout<< " from proc:" << procI
// << " want its local cells " << remoteFaceCells[procI]
// << " to add to my local cells:" << localFaceCells[procI]
// << endl;
nbrProcs[nbrI++] = procI;
label globalNbr = globalCellIDs[nbrCelli];
label proci = globalNumbering.whichProcID(globalNbr);
label remoteCelli = globalNumbering.toLocal(proci, globalNbr);
// Overwrite the face to be a patch face
stencilFaces_[celli][nbri] = procOwner[proci].size();
stencilPatches_[celli][nbri] = proci;
procOwner[proci].append(celli);
dynProcNeighbour[proci].append(remoteCelli);
//Pout<< "From neighbour proc:" << proci
// << " allocating patchFace:" << stencilFaces_[celli][nbri]
// << " to get remote cell " << remoteCelli
// << " onto local cell " << celli << endl;
}
}
nbrProcs.setSize(nbrI);
}
labelListList procNeighbour(dynProcNeighbour.size());
forAll(procNeighbour, i)
{
procNeighbour[i] = std::move(dynProcNeighbour[i]);
}
labelListList mySendCells;
Pstream::exchange<labelList, label>(procNeighbour, mySendCells);
label nbri = 0;
forAll(procOwner, proci)
{
if (procOwner[proci].size())
{
nbri++;
}
if (mySendCells[proci].size())
{
nbri++;
}
}
remoteStencilInterfaces_.setSize(nbri);
nbri = 0;
// E.g. if proc1 needs some data from proc2 and proc2 needs some data from
// proc1. We first want the pair : proc1 receive and proc2 send
// and then the pair : proc1 send, proc2 receive
labelList procToInterface(Pstream::nProcs(), -1);
forAll(procOwner, proci)
{
if (proci < Pstream::myProcNo() && procOwner[proci].size())
{
//Pout<< "Adding interface " << nbri
// << " to receive my " << procOwner[proci]
// << " from " << proci << endl;
procToInterface[proci] = nbri;
remoteStencilInterfaces_.set
(
nbri++,
new lduPrimitiveProcessorInterface
(
procOwner[proci],
Pstream::myProcNo(),
proci,
tensorField(0),
Pstream::msgType()+2
)
);
}
else if (proci > Pstream::myProcNo() && mySendCells[proci].size())
{
//Pout<< "Adding interface " << nbri
// << " to send my " << mySendCells[proci]
// << " to " << proci << endl;
remoteStencilInterfaces_.set
(
nbri++,
new lduPrimitiveProcessorInterface
(
mySendCells[proci],
Pstream::myProcNo(),
proci,
tensorField(0),
Pstream::msgType()+2
)
);
}
}
forAll(procOwner, proci)
{
if (proci > Pstream::myProcNo() && procOwner[proci].size())
{
//Pout<< "Adding interface " << nbri
// << " to receive my " << procOwner[proci]
// << " from " << proci << endl;
procToInterface[proci] = nbri;
remoteStencilInterfaces_.set
(
nbri++,
new lduPrimitiveProcessorInterface
(
procOwner[proci],
Pstream::myProcNo(),
proci,
tensorField(0),
Pstream::msgType()+2
)
);
}
else if (proci < Pstream::myProcNo() && mySendCells[proci].size())
{
//Pout<< "Adding interface " << nbri
// << " to send my " << mySendCells[proci]
// << " to " << proci << endl;
remoteStencilInterfaces_.set
(
nbri++,
new lduPrimitiveProcessorInterface
(
mySendCells[proci],
Pstream::myProcNo(),
proci,
tensorField(0),
Pstream::msgType()+2
)
);
}
}
// Construct interfaces
remoteStencilInterfaces_.setSize(nbrProcs.size());
forAll(nbrProcs, i)
// Rewrite stencilPatches now we know the actual interface (procToInterface)
for (auto& patches : stencilPatches_)
{
label procI = nbrProcs[i];
remoteStencilInterfaces_.set
(
i,
new lduPrimitiveProcessorInterface
(
localFaceCells[procI],
Pstream::myProcNo(),
procI,
tensorField(0),
Pstream::msgType()
)
);
for (auto& interface : patches)
{
if (interface != -1)
{
interface = procToInterface[interface]+boundary().size();
}
}
}
@ -218,6 +345,104 @@ bool Foam::dynamicOversetFvMesh::updateAddressing() const
}
void Foam::dynamicOversetFvMesh::writeAgglomeration
(
const GAMGAgglomeration& agglom
) const
{
labelList cellToCoarse(identity(nCells()));
labelListList coarseToCell(invertOneToMany(nCells(), cellToCoarse));
// Write initial agglomeration
{
volScalarField scalarAgglomeration
(
IOobject
(
"agglomeration",
this->time().timeName(),
*this,
IOobject::NO_READ,
IOobject::AUTO_WRITE
),
*this,
dimensionedScalar(dimless, Zero)
);
scalarField& fld = scalarAgglomeration.primitiveFieldRef();
forAll(fld, celli)
{
fld[celli] = cellToCoarse[celli];
}
fld /= max(fld);
correctBoundaryConditions
<
volScalarField,
oversetFvPatchField<scalar>
>(scalarAgglomeration.boundaryFieldRef(), false);
scalarAgglomeration.write();
Info<< "Writing initial cell distribution to "
<< this->time().timeName() << endl;
}
for (label level = 0; level < agglom.size(); level++)
{
const labelList& addr = agglom.restrictAddressing(level);
label coarseSize = max(addr)+1;
Info<< "Level : " << level << endl
<< returnReduce(addr.size(), sumOp<label>()) << endl
<< " current size : "
<< returnReduce(addr.size(), sumOp<label>()) << endl
<< " agglomerated size : "
<< returnReduce(coarseSize, sumOp<label>()) << endl;
forAll(addr, fineI)
{
const labelList& cellLabels = coarseToCell[fineI];
forAll(cellLabels, i)
{
cellToCoarse[cellLabels[i]] = addr[fineI];
}
}
coarseToCell = invertOneToMany(coarseSize, cellToCoarse);
// Write agglomeration
{
volScalarField scalarAgglomeration
(
IOobject
(
"agglomeration_" + Foam::name(level),
this->time().timeName(),
*this,
IOobject::NO_READ,
IOobject::AUTO_WRITE
),
*this,
dimensionedScalar(dimless, Zero)
);
scalarField& fld = scalarAgglomeration.primitiveFieldRef();
forAll(fld, celli)
{
fld[celli] = cellToCoarse[celli];
}
//if (normalise)
//{
// fld /= max(fld);
//}
correctBoundaryConditions
<
volScalarField,
oversetFvPatchField<scalar>
>(scalarAgglomeration.boundaryFieldRef(), false);
scalarAgglomeration.write();
}
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::dynamicOversetFvMesh::dynamicOversetFvMesh(const IOobject& io)
@ -253,6 +478,21 @@ const Foam::lduAddressing& Foam::dynamicOversetFvMesh::lduAddr() const
}
Foam::lduInterfacePtrsList Foam::dynamicOversetFvMesh::interfaces() const
{
if (!active_)
{
return dynamicMotionSolverFvMesh::interfaces();
}
if (lduPtr_.empty())
{
// Build extended addressing
updateAddressing();
}
return allInterfaces_;
}
const Foam::fvMeshPrimitiveLduAddressing&
Foam::dynamicOversetFvMesh::primitiveLduAddr() const
{

View File

@ -48,6 +48,7 @@ namespace Foam
class mapDistribute;
class lduPrimitiveProcessorInterface;
class GAMGAgglomeration;
/*---------------------------------------------------------------------------*\
Class dynamicOversetFvMesh Declaration
@ -80,6 +81,9 @@ protected:
//- Corresponding faces (in above lduPtr) to the stencil
mutable labelListList stencilFaces_;
//- Corresponding patches (in above lduPtr) to the stencil
mutable labelListList stencilPatches_;
//- From old to new face labels
mutable labelList reverseFaceMap_;
@ -91,7 +95,13 @@ protected:
//- Debug: print matrix
template<class Type>
void write(Ostream&, const fvMatrix<Type>&, const lduAddressing&) const;
void write
(
Ostream&,
const fvMatrix<Type>&,
const lduAddressing&,
const lduInterfacePtrsList&
) const;
//- Explicit interpolation of acceptor cells from donor cells
template<class T>
@ -111,16 +121,31 @@ protected:
void interpolate(const wordHashSet& suppressed);
//- Freeze values at holes
template<class Type>
void freezeHoles(fvMatrix<Type>&) const;
//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;
//- Correct boundary conditions of certain type (typeOnly = true)
// or explicitly not of the type (typeOnly = false)
template<class GeoField, class PatchType>
lduInterfaceFieldPtrsList scalarInterfaces(const GeoField& psi) const;
static void correctBoundaryConditions
(
typename GeoField::Boundary& bfld,
const bool typeOnly
);
//- Determine normalisation for interpolation. This equals the
// original diagonal except stabilised for zero diagonals (possible
// in hole cells)
template<class Type>
tmp<scalarField> normalisation(const fvMatrix<Type>& m) const;
//- Add interpolation to matrix (coefficients)
template<class Type>
void addInterpolation(fvMatrix<Type>&) const;
void addInterpolation(fvMatrix<Type>&, const scalarField& norm) const;
//- Solve given dictionary with settings
template<class Type>
@ -130,6 +155,12 @@ protected:
template<class GeoField>
static void correctCoupledBoundaryConditions(GeoField& fld);
//- Debug: dump agglomeration
void writeAgglomeration
(
const GAMGAgglomeration& agglom
) const;
private:
@ -170,6 +201,11 @@ public:
// primitiveLduAddr
virtual const lduAddressing& lduAddr() const;
//- Return a list of pointers for each patch
// with only those pointing to interfaces being set. If active:
// return additional remoteStencilInterfaces_
virtual lduInterfacePtrsList interfaces() const;
//- Return old to new face addressing
const labelList& reverseFaceMap() const
{

View File

@ -27,6 +27,9 @@ License
#include "fvMatrix.H"
#include "cellCellStencilObject.H"
#include "oversetFvPatchField.H"
#include "calculatedProcessorFvPatchField.H"
#include "lduInterfaceFieldPtrsList.H"
#include "processorFvPatch.H"
// * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * * //
@ -107,37 +110,91 @@ void Foam::dynamicOversetFvMesh::interpolate(const wordHashSet& suppressed)
template<class GeoField, class PatchType>
Foam::lduInterfaceFieldPtrsList
Foam::dynamicOversetFvMesh::scalarInterfaces(const GeoField& psi) const
void Foam::dynamicOversetFvMesh::correctBoundaryConditions
(
typename GeoField::Boundary& bfld,
const bool typeOnly
)
{
const typename GeoField::Boundary& bpsi = psi.boundaryField();
const label nReq = Pstream::nRequests();
lduInterfaceFieldPtrsList interfaces(bpsi.size());
forAll(interfaces, patchi)
forAll(bfld, patchi)
{
if
(
isA<lduInterfaceField>(bpsi[patchi])
&& isA<PatchType>(bpsi[patchi])
)
if (typeOnly == (isA<PatchType>(bfld[patchi]) != nullptr))
{
interfaces.set
(
patchi,
&refCast<const lduInterfaceField>
(
bpsi[patchi]
)
);
bfld[patchi].initEvaluate(Pstream::defaultCommsType);
}
}
// Block for any outstanding requests
if (Pstream::parRun())
{
Pstream::waitRequests(nReq);
}
forAll(bfld, patchi)
{
if (typeOnly == (isA<PatchType>(bfld[patchi]) != nullptr))
{
bfld[patchi].evaluate(Pstream::defaultCommsType);
}
}
return interfaces;
}
template<class Type>
void Foam::dynamicOversetFvMesh::addInterpolation(fvMatrix<Type>& m) const
Foam::tmp<Foam::scalarField> Foam::dynamicOversetFvMesh::normalisation
(
const fvMatrix<Type>& m
) const
{
// Determine normalisation. This is normally the original diagonal.
// This needs to be stabilised for hole cells
// which can have a zero diagonal. Assume that if any component has
// a non-zero diagonal the cell does not need stabilisation.
tmp<scalarField> tnorm(tmp<scalarField>::New(m.diag()));
scalarField& norm = tnorm.ref();
// Add boundary coeffs to duplicate behaviour of fvMatrix
const FieldField<Field, Type>& internalCoeffs = m.internalCoeffs();
for (direction cmpt=0; cmpt<pTraits<Type>::nComponents; cmpt++)
{
//m.addBoundaryDiag(norm, cmpt);
forAll(internalCoeffs, patchi)
{
const labelUList& fc = lduAddr().patchAddr(patchi);
const Field<Type>& intCoeffs = internalCoeffs[patchi];
const scalarField cmptCoeffs(intCoeffs.component(cmpt));
forAll(fc, i)
{
norm[fc[i]] += cmptCoeffs[i];
}
}
}
forAll(norm, celli)
{
scalar& n = norm[celli];
if (mag(n) < SMALL)
{
n = 1.0; //?
}
else
{
// Restore original diagonal
n = m.diag()[celli];
}
}
return tnorm;
}
template<class Type>
void Foam::dynamicOversetFvMesh::addInterpolation
(
fvMatrix<Type>& m,
const scalarField& normalisation
) const
{
const cellCellStencilObject& overlap = Stencil::New(*this);
const List<scalarList>& wghts = overlap.cellInterpolationWeights();
@ -161,7 +218,7 @@ void Foam::dynamicOversetFvMesh::addInterpolation(fvMatrix<Type>& m) const
const labelUList& lowerAddr = addr.lowerAddr();
const labelUList& ownerStartAddr = addr.ownerStartAddr();
const labelUList& losortAddr = addr.losortAddr();
const lduInterfacePtrsList& interfaces = allInterfaces_;
if (!isA<fvMeshPrimitiveLduAddressing>(addr))
{
@ -179,6 +236,71 @@ void Foam::dynamicOversetFvMesh::addInterpolation(fvMatrix<Type>& m) const
inplaceReorder(reverseFaceMap_, lower);
const label nOldInterfaces = dynamicMotionSolverFvMesh::interfaces().size();
if (interfaces.size() > nOldInterfaces)
{
// Extend matrix coefficients
m.internalCoeffs().setSize(interfaces.size());
m.boundaryCoeffs().setSize(interfaces.size());
// 1b. Adapt for additional interfaces
for
(
label patchi = nOldInterfaces;
patchi < interfaces.size();
patchi++
)
{
const labelUList& fc = interfaces[patchi].faceCells();
m.internalCoeffs().set(patchi, new Field<Type>(fc.size(), Zero));
m.boundaryCoeffs().set(patchi, new Field<Type>(fc.size(), Zero));
}
// 1c. Adapt field for additional interfaceFields (note: solver uses
// GeometricField::scalarInterfaces() to get hold of interfaces)
typedef GeometricField<Type, fvPatchField, volMesh> GeoField;
typename GeoField::Boundary& bfld =
const_cast<GeoField&>(m.psi()).boundaryFieldRef();
bfld.setSize(interfaces.size());
// This gets quite interesting: we do not want to add additional
// fvPatches (since direct correspondence to polyMesh) so instead
// add a reference to an existing processor patch
label addPatchi = 0;
for (label patchi = 0; patchi < nOldInterfaces; patchi++)
{
if (isA<processorFvPatch>(bfld[patchi].patch()))
{
addPatchi = patchi;
break;
}
}
for
(
label patchi = nOldInterfaces;
patchi < interfaces.size();
patchi++
)
{
bfld.set
(
patchi,
new calculatedProcessorFvPatchField<Type>
(
interfaces[patchi],
bfld[addPatchi].patch(), // dummy processorFvPatch
m.psi()
)
);
}
}
// 2. Adapt fvMatrix level: faceFluxCorrectionPtr
// Question: do we need to do this?
// This seems to be set/used only by the gaussLaplacianScheme and
@ -207,12 +329,11 @@ void Foam::dynamicOversetFvMesh::addInterpolation(fvMatrix<Type>& m) const
}
}
forAll(m.internalCoeffs(), patchI)
for (label patchi = 0; patchi < nOldInterfaces; ++patchi)
{
const labelUList& fc = addr.patchAddr(patchI);
Field<Type>& intCoeffs = m.internalCoeffs()[patchI];
Field<Type>& bouCoeffs = m.boundaryCoeffs()[patchI];
const labelUList& fc = addr.patchAddr(patchi);
Field<Type>& intCoeffs = m.internalCoeffs()[patchi];
Field<Type>& bouCoeffs = m.boundaryCoeffs()[patchi];
forAll(fc, i)
{
label celli = fc[i];
@ -232,92 +353,16 @@ 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 subtracts it from the source later in order to compensate.
Field<Type> correctionSource(diag.size(), 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
// ~~~~~~~~~~~~~
// Do hole cells. Note: maybe put into interpolationCells() loop above?
forAll(types, celli)
{
if (types[celli] == cellCellStencil::HOLE)
{
//Pout<< "Found hole cell:" << celli
// << " at:" << C()[celli]
// << " ; setting value" << endl;
label startLabel = ownerStartAddr[celli];
label endLabel = ownerStartAddr[celli + 1];
@ -335,13 +380,21 @@ void Foam::dynamicOversetFvMesh::addInterpolation(fvMatrix<Type>& m) const
lower[facei] = 0.0;
}
const scalar normalisation = V()[celli];
diag[celli] = normalisation;
source[celli] = normalisation*m.psi()[celli];
diag[celli] = normalisation[celli];
source[celli] = normalisation[celli]*m.psi()[celli];
}
}
//const globalIndex globalNumbering(V().size());
//labelList globalCellIDs(overlap.cellInterpolationMap().constructSize());
//forAll(V(), cellI)
//{
// globalCellIDs[cellI] = globalNumbering.toGlobal(cellI);
//}
//overlap.cellInterpolationMap().distribute(globalCellIDs);
forAll(cellIDs, i)
{
label celli = cellIDs[i];
@ -350,8 +403,7 @@ void Foam::dynamicOversetFvMesh::addInterpolation(fvMatrix<Type>& m) const
const scalarList& w = wghts[celli];
const labelList& nbrs = stencil[celli];
const labelList& nbrFaces = stencilFaces_[celli];
const scalar normalisation = V()[celli];
const labelList& nbrPatches = stencilPatches_[celli];
if (types[celli] == cellCellStencil::HOLE)
{
@ -362,55 +414,90 @@ void Foam::dynamicOversetFvMesh::addInterpolation(fvMatrix<Type>& m) const
}
else
{
// Create interpolation stencil. Leave any non-local contributions
// to be done by oversetFvPatchField updateMatrixInterface
// 'correctionSource' is only applied for vector and higher
// fvMatrix; it is zero for scalar matrices (see above).
// Create interpolation stencil
diag[celli] *= (1.0-f);
diag[celli] += normalisation*f;
source[celli] *= (1.0-f);
source[celli] -= correctionSource[celli];
//Pout<< "Interpolating " << celli << " with factor:" << f
// << " new diag:" << diag[celli]
// << " new source:" << source[celli]
// << " volume:" << V()[celli] << endl;
forAll(nbrs, nbri)
{
label patchi = nbrPatches[nbri];
label facei = nbrFaces[nbri];
if (facei != -1)
if (patchi == -1)
{
label nbrCelli = nbrs[nbri];
// Add the coefficients
const scalar s = normalisation[celli]*f*w[nbri];
scalar& u = upper[facei];
scalar& l = lower[facei];
if (celli < nbrCelli)
{
u += -normalisation*f*w[nbri];
diag[celli] += s;
u += -s;
}
else
{
l += -normalisation*f*w[nbri];
diag[celli] += s;
l += -s;
}
}
//else
//{
// Pout<< "addItnerpolation of " << celli
// << " at:" << this->cellCentres()[celli]
// << " zone:" << this->zoneID()[celli]
// << " diag:" << diag[celli]
// << " source:" << source[celli]
// <<" : skipping remote cell:" << nbrs[nbri]
// << " with weight:" << w[nbri]
// << endl;
//}
else
{
// Patch face. Store in boundaryCoeffs. Note sign change.
//const label globalCelli = globalCellIDs[nbrs[nbri]];
//const label proci =
// globalNumbering.whichProcID(globalCelli);
//const label remoteCelli =
// globalNumbering.toLocal(proci, globalCelli);
//
//Pout<< "for cell:" << celli
// << " need weight from remote slot:" << nbrs[nbri]
// << " proc:" << proci << " remote cell:" << remoteCelli
// << " patch:" << patchi
// << " patchFace:" << facei
// << " weight:" << w[nbri]
// << endl;
const scalar s = normalisation[celli]*f*w[nbri];
m.boundaryCoeffs()[patchi][facei] += pTraits<Type>::one*s;
m.internalCoeffs()[patchi][facei] += pTraits<Type>::one*s;
// Note: do NOT add to diagonal - this is in the
// internalCoeffs and gets added to the diagonal
// inside fvMatrix::solve
}
}
//if (mag(diag[celli]) < SMALL)
//{
// Pout<< "for cell:" << celli
// << " at:" << this->C()[celli]
// << " diag:" << diag[celli] << endl;
//
// forAll(nbrs, nbri)
// {
// label patchi = nbrPatches[nbri];
// label facei = nbrFaces[nbri];
//
// const label globalCelli = globalCellIDs[nbrs[nbri]];
// const label proci =
// globalNumbering.whichProcID(globalCelli);
// const label remoteCelli =
// globalNumbering.toLocal(proci, globalCelli);
//
// Pout<< " need weight from slot:" << nbrs[nbri]
// << " proc:" << proci << " remote cell:"
// << remoteCelli
// << " patch:" << patchi
// << " patchFace:" << facei
// << " weight:" << w[nbri]
// << endl;
// }
// Pout<< endl;
//}
}
}
}
@ -423,9 +510,10 @@ Foam::SolverPerformance<Type> Foam::dynamicOversetFvMesh::solve
const dictionary& dict
) const
{
typedef GeometricField<Type, fvPatchField, volMesh> GeoField;
// Check we're running with bcs that can handle implicit matrix manipulation
const typename GeometricField<Type, fvPatchField, volMesh>::Boundary bpsi =
m.psi().boundaryField();
typename GeoField::Boundary& bpsi =
const_cast<GeoField&>(m.psi()).boundaryFieldRef();
bool hasOverset = false;
forAll(bpsi, patchi)
@ -455,6 +543,9 @@ Foam::SolverPerformance<Type> Foam::dynamicOversetFvMesh::solve
<< m.psi().name() << endl;
}
// Calculate stabilised diagonal as normalisation for interpolation
const scalarField norm(normalisation(m));
// Switch to extended addressing (requires mesh::update() having been
// called)
@ -465,15 +556,32 @@ Foam::SolverPerformance<Type> Foam::dynamicOversetFvMesh::solve
scalarField oldLower(m.lower());
FieldField<Field, Type> oldInt(m.internalCoeffs());
FieldField<Field, Type> oldBou(m.boundaryCoeffs());
const label oldSize = bpsi.size();
addInterpolation(m, norm);
// Swap psi values so added patches have patchNeighbourField
correctBoundaryConditions<GeoField, calculatedProcessorFvPatchField<Type>>
(
bpsi,
true
);
addInterpolation(m);
// Print a bit
//write(Pout, m, lduAddr());
//write(Pout, m, lduAddr(), interfaces());
//{
// const fvSolution& sol = static_cast<const fvSolution&>(*this);
// const dictionary& pDict = sol.subDict("solvers").subDict("p");
// writeAgglomeration(GAMGAgglomeration::New(m, pDict));
//}
// Use lower level solver
SolverPerformance<Type> s(dynamicMotionSolverFvMesh::solve(m, dict));
// Restore boundary field
bpsi.setSize(oldSize);
// Restore matrix
m.upper().transfer(oldUpper);
m.lower().transfer(oldLower);
@ -492,7 +600,8 @@ void Foam::dynamicOversetFvMesh::write
(
Ostream& os,
const fvMatrix<Type>& m,
const lduAddressing& addr
const lduAddressing& addr,
const lduInterfacePtrsList& interfaces
) const
{
os << "** Matrix **" << endl;
@ -506,6 +615,26 @@ void Foam::dynamicOversetFvMesh::write
const Field<Type>& source = m.source();
const scalarField& diag = m.diag();
// Invert patch addressing
labelListList cellToPatch(addr.size());
labelListList cellToPatchFace(addr.size());
{
forAll(interfaces, patchi)
{
if (interfaces.set(patchi))
{
const labelUList& fc = interfaces[patchi].faceCells();
forAll(fc, i)
{
cellToPatch[fc[i]].append(patchi);
cellToPatchFace[fc[i]].append(i);
}
}
}
}
forAll(source, celli)
{
os << "cell:" << celli << " diag:" << diag[celli]
@ -531,6 +660,18 @@ void Foam::dynamicOversetFvMesh::write
<< " nbr:" << lowerAddr[facei] << " coeff:" << lower[facei]
<< endl;
}
forAll(cellToPatch[celli], i)
{
label patchi = cellToPatch[celli][i];
label patchFacei = cellToPatchFace[celli][i];
os << " patch:" << patchi
<< " patchface:" << patchFacei
<< " intcoeff:" << m.internalCoeffs()[patchi][patchFacei]
<< " boucoeff:" << m.boundaryCoeffs()[patchi][patchFacei]
<< endl;
}
}
forAll(m.internalCoeffs(), patchi)
{
@ -538,7 +679,22 @@ void Foam::dynamicOversetFvMesh::write
{
const labelUList& fc = addr.patchAddr(patchi);
os << "patch:" << patchi << " size:" << fc.size() << endl;
os << "patch:" << patchi
//<< " type:" << interfaces[patchi].type()
<< " size:" << fc.size() << endl;
if
(
interfaces.set(patchi)
&& isA<processorLduInterface>(interfaces[patchi])
)
{
const processorLduInterface& ppp =
refCast<const processorLduInterface>(interfaces[patchi]);
os << "(processor with my:" << ppp.myProcNo()
<< " nbr:" << ppp.neighbProcNo()
<< ")" << endl;
}
forAll(fc, i)
{
os << " cell:" << fc[i]
@ -550,15 +706,15 @@ void Foam::dynamicOversetFvMesh::write
}
lduInterfaceFieldPtrsList interfaces =
lduInterfaceFieldPtrsList interfaceFields =
m.psi().boundaryField().scalarInterfaces();
forAll(interfaces, inti)
forAll(interfaceFields, inti)
{
if (interfaces.set(inti))
if (interfaceFields.set(inti))
{
os << "interface:" << inti
<< " if type:" << interfaces[inti].interface().type()
<< " fld type:" << interfaces[inti].type() << endl;
<< " if type:" << interfaceFields[inti].interface().type()
<< " fld type:" << interfaceFields[inti].type() << endl;
}
}
@ -577,7 +733,7 @@ void Foam::dynamicOversetFvMesh::correctCoupledBoundaryConditions(GeoField& fld)
{
if (bfld[patchi].coupled())
{
Pout<< "initEval of " << bfld[patchi].patch().name() << endl;
//Pout<< "initEval of " << bfld[patchi].patch().name() << endl;
bfld[patchi].initEvaluate(Pstream::defaultCommsType);
}
}
@ -592,7 +748,7 @@ void Foam::dynamicOversetFvMesh::correctCoupledBoundaryConditions(GeoField& fld)
{
if (bfld[patchi].coupled())
{
Pout<< "eval of " << bfld[patchi].patch().name() << endl;
//Pout<< "eval of " << bfld[patchi].patch().name() << endl;
bfld[patchi].evaluate(Pstream::defaultCommsType);
}
}

View File

@ -192,7 +192,7 @@ Foam::labelList Foam::fvMeshPrimitiveLduAddressing::addAddressing
// Remote cell
faces[nbrI] = -1;
label globalNbr = globalCellIDs[nbrs[nbrI]];
label globalNbr = globalCellIDs[nbrCellI];
label procI = globalNumbering.whichProcID(globalNbr);
label remoteCellI = globalNumbering.toLocal(procI, globalNbr);

View File

@ -0,0 +1,221 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2019 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 "calculatedProcessorGAMGInterface.H"
#include "addToRunTimeSelectionTable.H"
#include "labelPairHashes.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(calculatedProcessorGAMGInterface, 0);
addToRunTimeSelectionTable
(
GAMGInterface,
calculatedProcessorGAMGInterface,
lduInterface
);
addToRunTimeSelectionTable
(
GAMGInterface,
calculatedProcessorGAMGInterface,
Istream
);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::calculatedProcessorGAMGInterface::calculatedProcessorGAMGInterface
(
const label index,
const lduInterfacePtrsList& coarseInterfaces,
const lduInterface& fineInterface,
const labelField& localRestrictAddressing,
const labelField& neighbourRestrictAddressing,
const label fineLevelIndex,
const label coarseComm
)
:
GAMGInterface
(
index,
coarseInterfaces
),
comm_(coarseComm),
myProcNo_(refCast<const processorLduInterface>(fineInterface).myProcNo()),
neighbProcNo_
(
refCast<const processorLduInterface>(fineInterface).neighbProcNo()
),
forwardT_(refCast<const processorLduInterface>(fineInterface).forwardT()),
tag_(refCast<const processorLduInterface>(fineInterface).tag())
{
// From coarse face to coarse cell
DynamicList<label> dynFaceCells(localRestrictAddressing.size());
// From fine face to coarse face
DynamicList<label> dynFaceRestrictAddressing
(
localRestrictAddressing.size()
);
// From coarse cell pair to coarse face
labelPairLookup cellsToCoarseFace(2*localRestrictAddressing.size());
forAll(localRestrictAddressing, ffi)
{
labelPair cellPair;
// Do switching on master/slave indexes based on the owner/neighbour of
// the processor index such that both sides get the same answer.
if (myProcNo() < neighbProcNo())
{
// Master side
cellPair = labelPair
(
localRestrictAddressing[ffi],
neighbourRestrictAddressing[ffi]
);
}
else
{
// Slave side
cellPair = labelPair
(
neighbourRestrictAddressing[ffi],
localRestrictAddressing[ffi]
);
}
const auto fnd = cellsToCoarseFace.cfind(cellPair);
if (fnd.found())
{
// Already have coarse face
dynFaceRestrictAddressing.append(fnd.val());
}
else
{
// New coarse face
label coarseI = dynFaceCells.size();
dynFaceRestrictAddressing.append(coarseI);
dynFaceCells.append(localRestrictAddressing[ffi]);
cellsToCoarseFace.insert(cellPair, coarseI);
}
}
faceCells_.transfer(dynFaceCells);
faceRestrictAddressing_.transfer(dynFaceRestrictAddressing);
}
Foam::calculatedProcessorGAMGInterface::calculatedProcessorGAMGInterface
(
const label index,
const lduInterfacePtrsList& coarseInterfaces,
const labelUList& faceCells,
const labelUList& faceRestrictAddresssing,
const label coarseComm,
const label myProcNo,
const label neighbProcNo,
const tensorField& forwardT,
const int tag
)
:
GAMGInterface
(
index,
coarseInterfaces,
faceCells,
faceRestrictAddresssing
),
comm_(coarseComm),
myProcNo_(myProcNo),
neighbProcNo_(neighbProcNo),
forwardT_(forwardT),
tag_(tag)
{}
Foam::calculatedProcessorGAMGInterface::calculatedProcessorGAMGInterface
(
const label index,
const lduInterfacePtrsList& coarseInterfaces,
Istream& is
)
:
GAMGInterface(index, coarseInterfaces, is),
comm_(readLabel(is)),
myProcNo_(readLabel(is)),
neighbProcNo_(readLabel(is)),
forwardT_(is),
tag_(readLabel(is))
{}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::calculatedProcessorGAMGInterface::~calculatedProcessorGAMGInterface()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::calculatedProcessorGAMGInterface::initInternalFieldTransfer
(
const Pstream::commsTypes commsType,
const labelUList& iF
) const
{
send(commsType, interfaceInternalField(iF)());
}
Foam::tmp<Foam::labelField>
Foam::calculatedProcessorGAMGInterface::internalFieldTransfer
(
const Pstream::commsTypes commsType,
const labelUList& iF
) const
{
tmp<Field<label>> tfld(receive<label>(commsType, this->size()));
return tfld;
}
void Foam::calculatedProcessorGAMGInterface::write(Ostream& os) const
{
GAMGInterface::write(os);
os << token::SPACE << comm_
<< token::SPACE << myProcNo_
<< token::SPACE << neighbProcNo_
<< token::SPACE << forwardT_
<< token::SPACE << tag_;
}
// ************************************************************************* //

View File

@ -0,0 +1,199 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2019 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::calculatedProcessorGAMGInterface
Description
GAMG agglomerated processor interface.
SourceFiles
calculatedProcessorGAMGInterface.C
\*---------------------------------------------------------------------------*/
#ifndef calculatedProcessorGAMGInterface_H
#define calculatedProcessorGAMGInterface_H
#include "GAMGInterface.H"
#include "processorLduInterface.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class calculatedProcessorGAMGInterface Declaration
\*---------------------------------------------------------------------------*/
class calculatedProcessorGAMGInterface
:
public GAMGInterface,
public processorLduInterface
{
// Private data
//- Communicator to use for parallel communication
const label comm_;
//- My processor rank in communicator
label myProcNo_;
//- Neighbouring processor rank in communicator
label neighbProcNo_;
//- Transformation tensor
tensorField forwardT_;
//- Message tag used for sending
int tag_;
// Private Member Functions
//- No copy construct
calculatedProcessorGAMGInterface
(
const calculatedProcessorGAMGInterface&
) = delete;
//- No copy assignment
void operator=(const calculatedProcessorGAMGInterface&) = delete;
public:
//- Runtime type information
TypeName("calculatedProcessor");
// Constructors
//- Construct from fine-level interface,
// local and neighbour restrict addressing
calculatedProcessorGAMGInterface
(
const label index,
const lduInterfacePtrsList& coarseInterfaces,
const lduInterface& fineInterface,
const labelField& restrictAddressing,
const labelField& neighbourRestrictAddressing,
const label fineLevelIndex,
const label coarseComm
);
//- Construct from components
calculatedProcessorGAMGInterface
(
const label index,
const lduInterfacePtrsList& coarseInterfaces,
const labelUList& faceCells,
const labelUList& faceRestrictAddresssing,
const label coarseComm,
const label myProcNo,
const label neighbProcNo,
const tensorField& forwardT,
const int tag
);
//- Construct from Istream
calculatedProcessorGAMGInterface
(
const label index,
const lduInterfacePtrsList& coarseInterfaces,
Istream& is
);
//- Destructor
virtual ~calculatedProcessorGAMGInterface();
// Member Functions
// Interface transfer functions
//- Initialise neighbour field transfer
virtual void initInternalFieldTransfer
(
const Pstream::commsTypes commsType,
const labelUList& iF
) const;
//- Transfer and return internal field adjacent to the interface
virtual tmp<labelField> internalFieldTransfer
(
const Pstream::commsTypes commsType,
const labelUList& iF
) const;
//- Processor interface functions
//- Return communicator used for sending
virtual label comm() const
{
return comm_;
}
//- Return processor number (rank in communicator)
virtual int myProcNo() const
{
return myProcNo_;
}
//- Return neighbour processor number (rank in communicator)
virtual int neighbProcNo() const
{
return neighbProcNo_;
}
//- Return face transformation tensor
virtual const tensorField& forwardT() const
{
return forwardT_;
}
//- Return message tag used for sending
virtual int tag() const
{
return tag_;
}
// I/O
//- Write to stream
virtual void write(Ostream&) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,206 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2019 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 "calculatedProcessorGAMGInterfaceField.H"
#include "addToRunTimeSelectionTable.H"
#include "lduMatrix.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(calculatedProcessorGAMGInterfaceField, 0);
addToRunTimeSelectionTable
(
GAMGInterfaceField,
calculatedProcessorGAMGInterfaceField,
lduInterface
);
addToRunTimeSelectionTable
(
GAMGInterfaceField,
calculatedProcessorGAMGInterfaceField,
lduInterfaceField
);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::calculatedProcessorGAMGInterfaceField::
calculatedProcessorGAMGInterfaceField
(
const GAMGInterface& GAMGCp,
const lduInterfaceField& fineInterface
)
:
GAMGInterfaceField(GAMGCp, fineInterface),
procInterface_(refCast<const calculatedProcessorGAMGInterface>(GAMGCp)),
doTransform_(false),
rank_(0)
{
const processorLduInterfaceField& p =
refCast<const processorLduInterfaceField>(fineInterface);
doTransform_ = p.doTransform();
rank_ = p.rank();
}
Foam::calculatedProcessorGAMGInterfaceField::
calculatedProcessorGAMGInterfaceField
(
const GAMGInterface& GAMGCp,
const bool doTransform,
const int rank
)
:
GAMGInterfaceField(GAMGCp, doTransform, rank),
procInterface_(refCast<const calculatedProcessorGAMGInterface>(GAMGCp)),
doTransform_(doTransform),
rank_(rank)
{}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::calculatedProcessorGAMGInterfaceField::
~calculatedProcessorGAMGInterfaceField()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::calculatedProcessorGAMGInterfaceField::initInterfaceMatrixUpdate
(
scalarField&,
const bool,
const scalarField& psiInternal,
const scalarField&,
const direction,
const Pstream::commsTypes commsType
) const
{
procInterface_.interfaceInternalField(psiInternal, scalarSendBuf_);
if
(
commsType == Pstream::commsTypes::nonBlocking
&& !Pstream::floatTransfer
)
{
// Fast path.
scalarReceiveBuf_.setSize(scalarSendBuf_.size());
outstandingRecvRequest_ = UPstream::nRequests();
IPstream::read
(
Pstream::commsTypes::nonBlocking,
procInterface_.neighbProcNo(),
reinterpret_cast<char*>(scalarReceiveBuf_.begin()),
scalarReceiveBuf_.byteSize(),
procInterface_.tag(),
comm()
);
outstandingSendRequest_ = UPstream::nRequests();
OPstream::write
(
Pstream::commsTypes::nonBlocking,
procInterface_.neighbProcNo(),
reinterpret_cast<const char*>(scalarSendBuf_.begin()),
scalarSendBuf_.byteSize(),
procInterface_.tag(),
comm()
);
}
else
{
procInterface_.compressedSend(commsType, scalarSendBuf_);
}
const_cast<calculatedProcessorGAMGInterfaceField&>(*this).updatedMatrix()
= false;
}
void Foam::calculatedProcessorGAMGInterfaceField::updateInterfaceMatrix
(
scalarField& result,
const bool add,
const scalarField&,
const scalarField& coeffs,
const direction cmpt,
const Pstream::commsTypes commsType
) const
{
if (updatedMatrix())
{
return;
}
if
(
commsType == Pstream::commsTypes::nonBlocking
&& !Pstream::floatTransfer
)
{
// Fast path.
if
(
outstandingRecvRequest_ >= 0
&& outstandingRecvRequest_ < Pstream::nRequests()
)
{
UPstream::waitRequest(outstandingRecvRequest_);
}
// Recv finished so assume sending finished as well.
outstandingSendRequest_ = -1;
outstandingRecvRequest_ = -1;
// Consume straight from scalarReceiveBuf_
// Transform according to the transformation tensor
transformCoupleField(scalarReceiveBuf_, cmpt);
// Multiply the field by coefficients and add into the result
addToInternalField(result, !add, coeffs, scalarReceiveBuf_);
}
else
{
scalarField pnf
(
procInterface_.compressedReceive<scalar>(commsType, coeffs.size())
);
transformCoupleField(pnf, cmpt);
addToInternalField(result, !add, coeffs, pnf);
}
const_cast<calculatedProcessorGAMGInterfaceField&>(*this).updatedMatrix()
= true;
}
// ************************************************************************* //

View File

@ -0,0 +1,208 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2019 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::calculatedProcessorGAMGInterfaceField
Description
GAMG agglomerated processor interface field.
SourceFiles
calculatedProcessorGAMGInterfaceField.C
\*---------------------------------------------------------------------------*/
#ifndef calculatedProcessorGAMGInterfaceField_H
#define calculatedProcessorGAMGInterfaceField_H
#include "GAMGInterfaceField.H"
#include "calculatedProcessorGAMGInterface.H"
#include "processorLduInterfaceField.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class calculatedProcessorGAMGInterfaceField Declaration
\*---------------------------------------------------------------------------*/
class calculatedProcessorGAMGInterfaceField
:
public GAMGInterfaceField,
public processorLduInterfaceField
{
// Private data
//- Local reference cast into the processor interface
const calculatedProcessorGAMGInterface& procInterface_;
//- Is the transform required
bool doTransform_;
//- Rank of component for transformation
int rank_;
// Sending and receiving
//- Outstanding request
mutable label outstandingSendRequest_;
//- Outstanding request
mutable label outstandingRecvRequest_;
//- Scalar send buffer
mutable Field<scalar> scalarSendBuf_;
//- Scalar receive buffer
mutable Field<scalar> scalarReceiveBuf_;
// Private Member Functions
//- No copy construct
calculatedProcessorGAMGInterfaceField
(
const calculatedProcessorGAMGInterfaceField&
) = delete;
//- No copy assignment
void operator=(const calculatedProcessorGAMGInterfaceField&) = delete;
public:
//- Runtime type information
TypeName("calculatedProcessor");
// Constructors
//- Construct from GAMG interface and fine level interface field
calculatedProcessorGAMGInterfaceField
(
const GAMGInterface& GAMGCp,
const lduInterfaceField& fineInterface
);
//- Construct from GAMG interface and fine level interface field
calculatedProcessorGAMGInterfaceField
(
const GAMGInterface& GAMGCp,
const bool doTransform,
const int rank
);
//- Destructor
virtual ~calculatedProcessorGAMGInterfaceField();
// Member Functions
// Access
//- Return size
label size() const
{
return procInterface_.size();
}
// Interface matrix update
//- Initialise neighbour matrix update
virtual void initInterfaceMatrixUpdate
(
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
(
scalarField& result,
const bool add,
const scalarField& psiInternal,
const scalarField& coeffs,
const direction cmpt,
const Pstream::commsTypes commsType
) const;
//- Processor interface functions
//- Return communicator used for comms
virtual label comm() const
{
return procInterface_.comm();
}
//- Return processor number
virtual int myProcNo() const
{
return procInterface_.myProcNo();
}
//- Return neighbour processor number
virtual int neighbProcNo() const
{
return procInterface_.neighbProcNo();
}
//- Does the interface field perform the transformation
virtual bool doTransform() const
{
return doTransform_;
}
//- Return face transformation tensor
virtual const tensorField& forwardT() const
{
return procInterface_.forwardT();
}
//- Return rank of component for transform
virtual int rank() const
{
return rank_;
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,348 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2019 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 "calculatedProcessorFvPatchField.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class Type>
Foam::calculatedProcessorFvPatchField<Type>::calculatedProcessorFvPatchField
(
const lduInterface& interface,
const fvPatch& p,
const DimensionedField<Type, volMesh>& iF
)
:
//lduInterfaceField(interface),
coupledFvPatchField<Type>(p, iF),
procInterface_(refCast<const lduPrimitiveProcessorInterface>(interface)),
sendBuf_(interface.faceCells().size()),
receiveBuf_(interface.faceCells().size()),
scalarSendBuf_(interface.faceCells().size()),
scalarReceiveBuf_(interface.faceCells().size()),
outstandingSendRequest_(-1),
outstandingRecvRequest_(-1)
{}
template<class Type>
Foam::calculatedProcessorFvPatchField<Type>::calculatedProcessorFvPatchField
(
const calculatedProcessorFvPatchField<Type>& ptf
)
:
//lduInterfaceField(ptf.procInterface_),
coupledFvPatchField<Type>(ptf),
procInterface_(ptf.procInterface_),
sendBuf_(procInterface_.faceCells().size()),
receiveBuf_(procInterface_.faceCells().size()),
scalarSendBuf_(procInterface_.faceCells().size()),
scalarReceiveBuf_(procInterface_.faceCells().size()),
outstandingSendRequest_(-1),
outstandingRecvRequest_(-1)
{}
template<class Type>
Foam::calculatedProcessorFvPatchField<Type>::calculatedProcessorFvPatchField
(
const calculatedProcessorFvPatchField<Type>& ptf,
const DimensionedField<Type, volMesh>& iF
)
:
//lduInterfaceField(ptf.procInterface_),
coupledFvPatchField<Type>(ptf, iF),
procInterface_(ptf.procInterface_),
sendBuf_(procInterface_.faceCells().size()),
receiveBuf_(procInterface_.faceCells().size()),
scalarSendBuf_(procInterface_.faceCells().size()),
scalarReceiveBuf_(procInterface_.faceCells().size()),
outstandingSendRequest_(-1),
outstandingRecvRequest_(-1)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Type>
bool Foam::calculatedProcessorFvPatchField<Type>::ready() const
{
if
(
this->outstandingSendRequest_ >= 0
&& this->outstandingSendRequest_ < Pstream::nRequests()
)
{
bool finished =
UPstream::finishedRequest(this->outstandingSendRequest_);
if (!finished)
{
return false;
}
}
this->outstandingSendRequest_ = -1;
if
(
this->outstandingRecvRequest_ >= 0
&& this->outstandingRecvRequest_ < Pstream::nRequests()
)
{
bool finished =
UPstream::finishedRequest(this->outstandingRecvRequest_);
if (!finished)
{
return false;
}
}
this->outstandingRecvRequest_ = -1;
return true;
}
template<class Type>
Foam::tmp<Foam::Field<Type>>
Foam::calculatedProcessorFvPatchField<Type>::patchNeighbourField() const
{
if (debug && !this->ready())
{
FatalErrorInFunction
<< "On patch of size " << procInterface_.faceCells().size()
<< " between proc " << procInterface_.myProcNo()
<< " and " << procInterface_.neighbProcNo()
<< " outstanding request."
<< abort(FatalError);
}
return *this;
}
template<class Type>
void Foam::calculatedProcessorFvPatchField<Type>::initEvaluate
(
const Pstream::commsTypes commsType
)
{
if (Pstream::parRun())
{
//this->patchInternalField(sendBuf_);
// Bypass patchInternalField since uses fvPatch addressing
{
const Field<Type>& iF = this->internalField();
const labelList& fc = procInterface_.faceCells();
sendBuf_.setSize(fc.size());
forAll(fc, i)
{
sendBuf_[i] = iF[fc[i]];
}
}
// Receive straight into *this
this->setSize(sendBuf_.size());
outstandingRecvRequest_ = UPstream::nRequests();
UIPstream::read
(
Pstream::commsTypes::nonBlocking,
procInterface_.neighbProcNo(),
reinterpret_cast<char*>(this->begin()),
this->byteSize(),
procInterface_.tag(),
procInterface_.comm()
);
outstandingSendRequest_ = UPstream::nRequests();
UOPstream::write
(
Pstream::commsTypes::nonBlocking,
procInterface_.neighbProcNo(),
reinterpret_cast<const char*>(sendBuf_.begin()),
this->byteSize(),
procInterface_.tag(),
procInterface_.comm()
);
}
}
template<class Type>
void Foam::calculatedProcessorFvPatchField<Type>::evaluate
(
const Pstream::commsTypes commsType
)
{
if (Pstream::parRun())
{
if
(
outstandingRecvRequest_ >= 0
&& outstandingRecvRequest_ < Pstream::nRequests()
)
{
UPstream::waitRequest(outstandingRecvRequest_);
}
outstandingSendRequest_ = -1;
outstandingRecvRequest_ = -1;
}
}
template<class Type>
void Foam::calculatedProcessorFvPatchField<Type>::initInterfaceMatrixUpdate
(
scalarField& result,
const bool add,
const scalarField& psiInternal,
const scalarField& coeffs,
const direction cmpt,
const Pstream::commsTypes commsType
) const
{
// Bypass patchInternalField since uses fvPatch addressing
const labelList& fc = procInterface_.faceCells();
scalarSendBuf_.setSize(fc.size());
forAll(fc, i)
{
scalarSendBuf_[i] = psiInternal[fc[i]];
}
if (debug && !this->ready())
{
FatalErrorInFunction
<< "On patch " //<< interface_.name()
<< " outstanding request."
<< abort(FatalError);
}
scalarReceiveBuf_.setSize(scalarSendBuf_.size());
outstandingRecvRequest_ = UPstream::nRequests();
UIPstream::read
(
Pstream::commsTypes::nonBlocking,
procInterface_.neighbProcNo(),
reinterpret_cast<char*>(scalarReceiveBuf_.begin()),
scalarReceiveBuf_.byteSize(),
procInterface_.tag(),
procInterface_.comm()
);
outstandingSendRequest_ = UPstream::nRequests();
UOPstream::write
(
Pstream::commsTypes::nonBlocking,
procInterface_.neighbProcNo(),
reinterpret_cast<const char*>(scalarSendBuf_.begin()),
scalarSendBuf_.byteSize(),
procInterface_.tag(),
procInterface_.comm()
);
const_cast<lduInterfaceField&>
(
static_cast<const lduInterfaceField&>(*this)
).updatedMatrix() = false;
}
template<class Type>
void Foam::calculatedProcessorFvPatchField<Type>::addToInternalField
(
scalarField& result,
const bool add,
const scalarField& coeffs,
const scalarField& vals
) const
{
const labelUList& faceCells = this->procInterface_.faceCells();
if (add)
{
forAll(faceCells, elemI)
{
result[faceCells[elemI]] += coeffs[elemI]*vals[elemI];
}
}
else
{
forAll(faceCells, elemI)
{
result[faceCells[elemI]] -= coeffs[elemI]*vals[elemI];
}
}
}
template<class Type>
void Foam::calculatedProcessorFvPatchField<Type>::updateInterfaceMatrix
(
scalarField& result,
const bool add,
const scalarField& psiInternal,
const scalarField& coeffs,
const direction cmpt,
const Pstream::commsTypes commsType
) const
{
if (this->updatedMatrix())
{
return;
}
if
(
outstandingRecvRequest_ >= 0
&& outstandingRecvRequest_ < Pstream::nRequests()
)
{
UPstream::waitRequest(outstandingRecvRequest_);
}
// Recv finished so assume sending finished as well.
outstandingSendRequest_ = -1;
outstandingRecvRequest_ = -1;
// Consume straight from scalarReceiveBuf_. Note use of our own
// helper to avoid using fvPatch addressing
addToInternalField(result, !add, coeffs, scalarReceiveBuf_);
const_cast<lduInterfaceField&>
(
static_cast<const lduInterfaceField&>(*this)
).updatedMatrix() = true;
}
//template<class Type>
//void Foam::calculatedProcessorFvPatchField<Type>::write(Ostream& os) const
//{
// //zeroGradientFvPatchField<Type>::write(os);
// fvPatchField<Type>::write(os);
// this->writeEntry("value", os);
//}
// ************************************************************************* //

View File

@ -0,0 +1,306 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2019 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::calculatedProcessorFvPatchField
Group
grpGenericBoundaryConditions
Description
processorFvPatchField type bypassing fvPatch
Used to temporarily add updateInterfaceMatrix capabilities to a matrix
during overset solving. Supplies:
- patchNeighbourField functionality (cached in *this as per
processorFvPatchField)
- initEvaluate/evaluate: caching of patchNeighbourField (see above)
- initInterfaceMatrixUpdate etc: adding of neighbouring data
SourceFiles
calculatedProcessorFvPatchField.C
\*---------------------------------------------------------------------------*/
#ifndef calculatedProcessorFvPatchField_H
#define calculatedProcessorFvPatchField_H
#include "lduPrimitiveProcessorInterface.H"
//#include "lduInterfaceField.H"
//#include "fvPatchField.H"
#include "coupledFvPatchField.H"
#include "processorLduInterfaceField.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class calculatedProcessorFvPatchField Declaration
\*---------------------------------------------------------------------------*/
template<class Type>
class calculatedProcessorFvPatchField
:
public processorLduInterfaceField,
public coupledFvPatchField<Type>
{
protected:
// Private data
//- Local reference cast into the interface
const lduPrimitiveProcessorInterface& procInterface_;
// Sending and receiving
//- Send buffer
mutable Field<Type> sendBuf_;
//- Receive buffer
mutable Field<Type> receiveBuf_;
//- Scalar send buffer
mutable Field<scalar> scalarSendBuf_;
//- Scalar receive buffer
mutable Field<scalar> scalarReceiveBuf_;
//- Outstanding request
mutable label outstandingSendRequest_;
//- Outstanding request
mutable label outstandingRecvRequest_;
// Private Member Functions
void addToInternalField
(
scalarField& result,
const bool add,
const scalarField& coeffs,
const scalarField& vals
) const;
public:
//- Runtime type information
TypeName("calculatedProcessor");
// Constructors
//- Construct from patch and internal field
calculatedProcessorFvPatchField
(
const lduInterface& interface,
const fvPatch&,
const DimensionedField<Type, volMesh>&
);
//- Construct as copy
calculatedProcessorFvPatchField
(
const calculatedProcessorFvPatchField<Type>&
);
//- Construct and return a clone
virtual tmp<fvPatchField<Type>> clone() const
{
return tmp<fvPatchField<Type>>
(
new calculatedProcessorFvPatchField<Type>(*this)
);
}
//- Construct as copy setting internal field reference
calculatedProcessorFvPatchField
(
const calculatedProcessorFvPatchField<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 calculatedProcessorFvPatchField<Type>(*this, iF)
);
}
//- Destructor
virtual ~calculatedProcessorFvPatchField() = default;
// Member functions
// processorLduInterfaceField implementation
//- Return communicator used for comms
virtual label comm() const
{
return procInterface_.comm();
}
//- Return processor number
virtual int myProcNo() const
{
return procInterface_.myProcNo();
}
//- Return neighbour processor number
virtual int neighbProcNo() const
{
return procInterface_.myProcNo();
}
//- Is the transform required
virtual bool doTransform() const
{
return false;
}
//- Return face transformation tensor
virtual const tensorField& forwardT() const
{
return procInterface_.forwardT();
}
//- Return rank of component for transform
virtual int rank() const
{
return pTraits<Type>::rank;
}
// Access
//- Return true if this patch field is coupled. Our field supplies
// coefficients to the fvMatrix so should behave as a
// processorFvPatchField (in addBoundarySource it should not add
// to the source)
virtual bool coupled() const
{
if (Pstream::parRun())
{
return true;
}
else
{
return false;
}
}
//- Return neighbour field of internal field
virtual tmp<Field<Type>> patchNeighbourField() const;
// Evaluation functions
//- Is all data available
virtual bool ready() const;
//- Initialise the evaluation of the patch field
virtual void initEvaluate(const Pstream::commsTypes commsType);
//- Evaluate the patch field
virtual void evaluate(const Pstream::commsTypes commsType);
//- Initialise neighbour matrix update
virtual void initInterfaceMatrixUpdate
(
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
(
scalarField& result,
const bool add,
const scalarField& psiInternal,
const scalarField& coeffs,
const direction cmpt,
const Pstream::commsTypes commsType
) const;
//- Initialise neighbour matrix update
virtual void initInterfaceMatrixUpdate
(
Field<Type>& result,
const bool add,
const Field<Type>& psiInternal,
const scalarField& coeffs,
const Pstream::commsTypes commsType
) const
{
NotImplemented;
}
//- Update result field based on interface functionality
virtual void updateInterfaceMatrix
(
Field<Type>& result,
const bool add,
const Field<Type>& psiInternal,
const scalarField& coeffs,
const Pstream::commsTypes commsType
) const
{
NotImplemented;
}
//- Write
//virtual void write(Ostream&) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "calculatedProcessorFvPatchField.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,52 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2019 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 "calculatedProcessorFvPatchFields.H"
#include "fvPatchFields.H"
#include "volMesh.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
defineNamedTemplateTypeNameAndDebug(calculatedProcessorFvPatchScalarField, 0);
defineNamedTemplateTypeNameAndDebug(calculatedProcessorFvPatchVectorField, 0);
defineNamedTemplateTypeNameAndDebug
(
calculatedProcessorFvPatchSphericalTensorField,
0
);
defineNamedTemplateTypeNameAndDebug(calculatedProcessorFvPatchSymmTensorField, 0);
defineNamedTemplateTypeNameAndDebug(calculatedProcessorFvPatchTensorField, 0);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* //

View File

@ -0,0 +1,49 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2019 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 calculatedProcessorFvPatchFields_H
#define calculatedProcessorFvPatchFields_H
#include "calculatedProcessorFvPatchField.H"
#include "fieldTypes.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
makePatchTypeFieldTypedefs(calculatedProcessor);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,50 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2019 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 calculatedProcessorFvPatchFieldsFwd_H
#define calculatedProcessorFvPatchFieldsFwd_H
#include "fieldTypes.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class Type> class calculatedProcessorFvPatchField;
makePatchTypeFieldTypedefs(calculatedProcessor);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -30,7 +30,7 @@ License
namespace Foam
{
defineTypeNameAndDebug(lduPrimitiveProcessorInterface, 0);
defineTypeName(lduPrimitiveProcessorInterface);
}

View File

@ -90,7 +90,7 @@ class lduPrimitiveProcessorInterface
public:
//- Runtime type information
TypeName("primitiveProcessor");
TypeName("calculatedProcessor");
// Constructors
@ -180,10 +180,13 @@ public:
}
// // I/O
//
// //- Write to stream
// virtual void write(Ostream&) const;
// Edit
//- Return message tag used for sending
int& tag()
{
return tag_;
}
};

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2016-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -41,75 +41,4 @@ namespace Foam
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::tmp<Foam::labelField> Foam::oversetFvPatch::interfaceInternalField
(
const labelUList& internalData
) const
{
return patchInternalField(internalData);
}
Foam::tmp<Foam::labelField> Foam::oversetFvPatch::internalFieldTransfer
(
const Pstream::commsTypes commsType,
const labelUList& restrictMap
) const
{
// Store the restrictMap. This routine gets used for
// - GAMGAgglomeration : this is the use we want to intercept.
// - GAMGProcAgglomeration : to find out the cell number on the other side
// - MGridGenGAMGAgglomeration: same
if (master())
{
restrictMap_ = restrictMap;
}
return patchInternalField(restrictMap);
}
const Foam::labelListList& Foam::oversetFvPatch::stencil() const
{
const cellCellStencilObject& overlap = Stencil::New(boundaryMesh().mesh());
return overlap.cellStencil();
}
const Foam::mapDistribute& Foam::oversetFvPatch::cellInterpolationMap() const
{
const cellCellStencilObject& overlap = Stencil::New(boundaryMesh().mesh());
return overlap.cellInterpolationMap();
}
const Foam::List<Foam::scalarList>&
Foam::oversetFvPatch::cellInterpolationWeights() const
{
const cellCellStencilObject& overlap = Stencil::New(boundaryMesh().mesh());
return overlap.cellInterpolationWeights();
}
const Foam::scalarField& Foam::oversetFvPatch::normalisation() const
{
return boundaryMesh().mesh().V().field();
}
const Foam::labelList& Foam::oversetFvPatch::interpolationCells() const
{
const cellCellStencilObject& overlap = Stencil::New(boundaryMesh().mesh());
return overlap.interpolationCells();
}
const Foam::scalarList& Foam::oversetFvPatch::cellInterpolationWeight() const
{
const cellCellStencilObject& overlap = Stencil::New(boundaryMesh().mesh());
return overlap.cellInterpolationWeight();
}
// ************************************************************************* //

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2016-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -38,8 +38,6 @@ SourceFiles
#include "fvPatch.H"
#include "oversetPolyPatch.H"
#include "fvBoundaryMesh.H"
#include "lduInterface.H"
#include "oversetLduInterface.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -52,18 +50,12 @@ namespace Foam
class oversetFvPatch
:
public lduInterface,
public oversetLduInterface,
public fvPatch
{
// Private data
const oversetPolyPatch& oversetPolyPatch_;
//- Temporary copy of the fine level restrict map. Cleared upon
// calculating stencils below
mutable labelList restrictMap_;
public:
@ -100,61 +92,11 @@ public:
return oversetPolyPatch_.faceCells();
}
// Interface transfer functions
//- Return the values of the given internal data adjacent to
// the interface as a field
virtual tmp<labelField> interfaceInternalField
(
const labelUList& internalData
) const;
//- Return neighbour field
virtual tmp<labelField> internalFieldTransfer
(
const Pstream::commsTypes commsType,
const labelUList& internalData
) const;
//- Overset interface functions
//- Name of interface (for debugging)
virtual const word& name() const
{
return oversetPolyPatch_.name();
}
//- Am I the master interface
virtual bool master() const
{
return oversetPolyPatch_.master();
}
//- GAMG restriction (fine-to-coarse)
virtual const labelList& restrictMap() const
{
return restrictMap_;
}
//- Donor stencil
virtual const labelListList& stencil() const;
//- Map for obtaining data in stencil order
virtual const mapDistribute& cellInterpolationMap() const;
//- Weights in stencil order
virtual const List<scalarList>& cellInterpolationWeights() const;
//- Normalisation of matrix; for explicit contributions
virtual const scalarField& normalisation() const;
//- Acceptor cells
virtual const labelList& interpolationCells() const;
//- Underrelaxation for acceptor cells
virtual const scalarList& cellInterpolationWeight() const;
};

View File

@ -37,7 +37,8 @@ Foam::oversetFvPatchField<Type>::oversetFvPatchField
const DimensionedField<Type, volMesh>& iF
)
:
semiImplicitOversetFvPatchField<Type>(p, iF)
zeroGradientFvPatchField<Type>(p, iF),
oversetPatch_(refCast<const oversetFvPatch>(p))
{}
@ -50,7 +51,8 @@ Foam::oversetFvPatchField<Type>::oversetFvPatchField
const fvPatchFieldMapper& mapper
)
:
semiImplicitOversetFvPatchField<Type>(ptf, p, iF, mapper)
zeroGradientFvPatchField<Type>(ptf, p, iF, mapper),
oversetPatch_(refCast<const oversetFvPatch>(p))
{}
@ -62,7 +64,8 @@ Foam::oversetFvPatchField<Type>::oversetFvPatchField
const dictionary& dict
)
:
semiImplicitOversetFvPatchField<Type>(p, iF, dict)
zeroGradientFvPatchField<Type>(p, iF, dict),
oversetPatch_(refCast<const oversetFvPatch>(p, dict))
{}
@ -72,7 +75,8 @@ Foam::oversetFvPatchField<Type>::oversetFvPatchField
const oversetFvPatchField<Type>& ptf
)
:
semiImplicitOversetFvPatchField<Type>(ptf)
zeroGradientFvPatchField<Type>(ptf),
oversetPatch_(ptf.oversetPatch_)
{}
@ -83,7 +87,8 @@ Foam::oversetFvPatchField<Type>::oversetFvPatchField
const DimensionedField<Type, volMesh>& iF
)
:
semiImplicitOversetFvPatchField<Type>(ptf, iF)
zeroGradientFvPatchField<Type>(ptf, iF),
oversetPatch_(ptf.oversetPatch_)
{}
@ -211,137 +216,138 @@ void Foam::oversetFvPatchField<Type>::initEvaluate
}
template<class Type>
void Foam::oversetFvPatchField<Type>::initInterfaceMatrixUpdate
(
scalarField&,
const bool add,
const scalarField& psiInternal,
const scalarField&,
const direction,
const Pstream::commsTypes commsType
) const
{
// Add remote values
const oversetFvPatch& ovp = this->oversetPatch_;
if (ovp.master())
{
const fvMesh& mesh = this->patch().boundaryMesh().mesh();
// Try to find out if the solve routine comes from the mesh
// TBD. This should be cleaner.
if (&mesh.lduAddr() == &mesh.fvMesh::lduAddr())
{
return;
}
const mapDistribute& map = ovp.cellInterpolationMap();
// Transfer the current state (similar to processorFvPatchField). Note
// use of separate tag to avoid clashes with any outstanding processor
// exchanges
if (this->pBufs_.valid())
{
this->pBufs_().clear();
}
else
{
this->pBufs_.set
(
new PstreamBuffers
(
Pstream::commsTypes::nonBlocking,
UPstream::msgType()+1
)
);
}
// Start sending
map.mapDistributeBase::send(this->pBufs_(), psiInternal);
}
}
template<class Type>
void Foam::oversetFvPatchField<Type>::updateInterfaceMatrix
(
scalarField& result,
const bool add,
const scalarField& psiInternal,
const scalarField& coeffs,
const direction cmpt,
const Pstream::commsTypes
) const
{
// Add remote values
const oversetFvPatch& ovp = this->oversetPatch_;
if (ovp.master())
{
const fvMesh& mesh = this->patch().boundaryMesh().mesh();
// Try to find out if the solve routine comes from the mesh
// TBD. This should be cleaner.
if (&mesh.lduAddr() == &mesh.fvMesh::lduAddr())
{
return;
}
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();
const scalarField& normalisation = ovp.normalisation();
// 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);
// Receive the outstanding data
scalarField work;
map.receive(this->pBufs_(), work);
forAll(cellIDs, i)
{
label celli = cellIDs[i];
const scalarList& w = wghts[celli];
const labelList& nbrs = stencil[celli];
scalar f = factor[celli];
const scalar norm = normalisation[celli];
// Add the non-local matrix contribution to psi. Note that the
// matrix coefficients are -weights
if (add)
{
f = -1.0*f;
}
forAll(nbrs, nbrI)
{
label slotI = nbrs[nbrI];
if (slotI >= psiInternal.size())
{
result[celli] += f*norm*w[nbrI]*work[slotI];
}
}
}
}
}
//template<class Type>
//void Foam::oversetFvPatchField<Type>::initInterfaceMatrixUpdate
//(
// scalarField&,
// const bool add,
// const scalarField& psiInternal,
// const scalarField&,
// const direction,
// const Pstream::commsTypes commsType
//) const
//{
//// // Add remote values
////
//// const oversetFvPatch& ovp = this->oversetPatch_;
////
//// if (ovp.master())
//// {
//// const fvMesh& mesh = this->patch().boundaryMesh().mesh();
////
//// // Try to find out if the solve routine comes from the mesh
//// // TBD. This should be cleaner.
//// if (&mesh.lduAddr() == &mesh.fvMesh::lduAddr())
//// {
//// return;
//// }
////
//// const mapDistribute& map = ovp.cellInterpolationMap();
////
//// // Transfer the current state (similar to processorFvPatchField).
//// // Note
//// // use of separate tag to avoid clashes with any outstanding
//// // processor exchanges
//// if (this->pBufs_.valid())
//// {
//// this->pBufs_().clear();
//// }
//// else
//// {
//// this->pBufs_.set
//// (
//// new PstreamBuffers
//// (
//// Pstream::commsTypes::nonBlocking,
//// UPstream::msgType()+1
//// )
//// );
//// }
////
//// // Start sending
//// map.mapDistributeBase::send(this->pBufs_(), psiInternal);
//// }
//}
//
//
//template<class Type>
//void Foam::oversetFvPatchField<Type>::updateInterfaceMatrix
//(
// scalarField& result,
// const bool add,
// const scalarField& psiInternal,
// const scalarField& coeffs,
// const direction cmpt,
// const Pstream::commsTypes
//) const
//{
//// // Add remote values
////
//// const oversetFvPatch& ovp = this->oversetPatch_;
////
//// if (ovp.master())
//// {
//// const fvMesh& mesh = this->patch().boundaryMesh().mesh();
////
//// // Try to find out if the solve routine comes from the mesh
//// // TBD. This should be cleaner.
//// if (&mesh.lduAddr() == &mesh.fvMesh::lduAddr())
//// {
//// return;
//// }
////
//// 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();
//// const scalarField& normalisation = ovp.normalisation();
////
//// // 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);
////
//// // Receive the outstanding data
//// scalarField work;
//// map.receive(this->pBufs_(), work);
////
//// forAll(cellIDs, i)
//// {
//// label celli = cellIDs[i];
////
//// const scalarList& w = wghts[celli];
//// const labelList& nbrs = stencil[celli];
////
//// scalar f = factor[celli];
//// const scalar norm = normalisation[celli];
////
//// // Add the non-local matrix contribution to psi. Note that the
//// // matrix coefficients are -weights
////
//// if (add)
//// {
//// f = -1.0*f;
//// }
////
//// forAll(nbrs, nbrI)
//// {
//// label slotI = nbrs[nbrI];
//// if (slotI >= psiInternal.size())
//// {
//// result[celli] += f*norm*w[nbrI]*work[slotI];
//// }
//// }
//// }
//// }
//}
// ************************************************************************* //

View File

@ -29,8 +29,7 @@ Group
Description
Boundary condition for use on overset patches. To be run in combination
with special dynamicFvMesh type that inserts local contributions into
the matrix. This boundary condition adds the remote contributions.
with special dynamicFvMesh type that inserts interpolation into the matrix.
SourceFiles
oversetFvPatchField.C
@ -40,7 +39,8 @@ SourceFiles
#ifndef oversetFvPatchField_H
#define oversetFvPatchField_H
#include "semiImplicitOversetFvPatchField.H"
#include "oversetFvPatch.H"
#include "zeroGradientFvPatchField.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -54,14 +54,20 @@ namespace Foam
template<class Type>
class oversetFvPatchField
:
public semiImplicitOversetFvPatchField<Type>
public zeroGradientFvPatchField<Type>
{
protected:
// Protected data
//- Local reference cast into the overset patch
const oversetFvPatch& oversetPatch_;
//- Master patch ID
mutable label masterPatchID_;
//- Send/receive buffer
mutable autoPtr<PstreamBuffers> pBufs_;
//mutable autoPtr<PstreamBuffers> pBufs_;
public:
@ -135,30 +141,30 @@ public:
//- Initialise the evaluation of the patch field
virtual void initEvaluate(const Pstream::commsTypes commsType);
using LduInterfaceField<Type>::initInterfaceMatrixUpdate;
//- Initialise neighbour matrix update. Add
//- or subtract coupled contributions to matrix
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
virtual void updateInterfaceMatrix
(
scalarField& result,
const bool add,
const scalarField& psiInternal,
const scalarField& coeffs,
const direction cmpt,
const Pstream::commsTypes commsType
) const;
// using LduInterfaceField<Type>::initInterfaceMatrixUpdate;
//
// //- Initialise neighbour matrix update. Add
// //- or subtract coupled contributions to matrix
// 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
// virtual void updateInterfaceMatrix
// (
// scalarField& result,
// const bool add,
// const scalarField& psiInternal,
// const scalarField& coeffs,
// const direction cmpt,
// const Pstream::commsTypes commsType
// ) const;
};

View File

@ -60,10 +60,10 @@ Foam::oversetGAMGInterface::oversetGAMGInterface
refCast<const oversetLduInterface>(fineInterface)
)
{
//Pout<< "Constructing oversetGAMGInterface index:" << index
// << " from:" << fineOversetInterface_.name()
// << " size:" << localRestrictAddressing.size()
// << endl;
Pout<< "Constructing oversetGAMGInterface index:" << index
<< " from:" << fineOversetInterface_.name()
<< " size:" << localRestrictAddressing.size()
<< endl;
// From coarse face to coarse cell
DynamicList<label> dynFaceCells(localRestrictAddressing.size());

View File

@ -72,80 +72,80 @@ void Foam::oversetGAMGInterfaceField::updateInterfaceMatrix
const Pstream::commsTypes commsType
) const
{
//Pout<< "oversetGAMGInterfaceField::updateInterfaceMatrix: at:"
Pout<< "oversetGAMGInterfaceField::updateInterfaceMatrix: at:"
// << oversetInterface_.name()
// << " nCells:" << result.size() << endl;
<< " nCells:" << result.size() << endl;
//
// 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];
bool hasRemote = false;
forAll(nbrs, nbrI)
{
label slotI = nbrs[nbrI];
if (slotI >= psiInternal.size())
{
hasRemote = true;
break;
}
}
if (hasRemote)
{
//Pout<< "oversetGAMGInterfaceField : Interpolating " << celli
// << " from remote values (if any):" << endl;
scalar s(0.0);
forAll(nbrs, nbrI)
{
label slotI = nbrs[nbrI];
if (slotI >= psiInternal.size())
{
//Pout<< " remote value " << work[slotI]
// << " from slot " << slotI << " with w:" << w[nbrI]
// << endl;
s += w[nbrI]*work[slotI];
}
}
//Pout<< "oversetGAMGInterfaceField : Interpolated value:"
// << s << endl;
//scalar oldPsi = result[celli];
if (add)
{
s = -1.0*s;
}
result[celli] += normalisation[celli]*f*s;
//Pout<< "oversetGAMGInterfaceField : result was:" << oldPsi
// << " now:" << result[celli] << endl;
}
}
}
// // 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];
//
// bool hasRemote = false;
// forAll(nbrs, nbrI)
// {
// label slotI = nbrs[nbrI];
// if (slotI >= psiInternal.size())
// {
// hasRemote = true;
// break;
// }
// }
//
// if (hasRemote)
// {
// //Pout<< "oversetGAMGInterfaceField : Interpolating " << celli
// // << " from remote values (if any):" << endl;
// scalar s(0.0);
// forAll(nbrs, nbrI)
// {
// label slotI = nbrs[nbrI];
// if (slotI >= psiInternal.size())
// {
// //Pout<< " remote value " << work[slotI]
// // << " from slot " << slotI << " with w:" << w[nbrI]
// // << endl;
// s += w[nbrI]*work[slotI];
// }
// }
// //Pout<< "oversetGAMGInterfaceField : Interpolated value:"
// // << s << endl;
// //scalar oldPsi = result[celli];
// if (add)
// {
// s = -1.0*s;
// }
//
// result[celli] += normalisation[celli]*f*s;
// //Pout<< "oversetGAMGInterfaceField : result was:" << oldPsi
// // << " now:" << result[celli] << endl;
// }
// }
// }
}

View File

@ -24,6 +24,7 @@ License
\*---------------------------------------------------------------------------*/
#include "volFields.H"
#include "cellCellStencilObject.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
@ -34,7 +35,7 @@ Foam::semiImplicitOversetFvPatchField<Type>::semiImplicitOversetFvPatchField
const DimensionedField<Type, volMesh>& iF
)
:
LduInterfaceField<Type>(refCast<const oversetFvPatch>(p)),
//LduInterfaceField<Type>(refCast<const oversetFvPatch>(p)),
zeroGradientFvPatchField<Type>(p, iF),
oversetPatch_(refCast<const oversetFvPatch>(p))
{}
@ -49,7 +50,7 @@ Foam::semiImplicitOversetFvPatchField<Type>::semiImplicitOversetFvPatchField
const fvPatchFieldMapper& mapper
)
:
LduInterfaceField<Type>(refCast<const oversetFvPatch>(p)),
//LduInterfaceField<Type>(refCast<const oversetFvPatch>(p)),
zeroGradientFvPatchField<Type>(ptf, p, iF, mapper),
oversetPatch_(refCast<const oversetFvPatch>(p))
{
@ -74,7 +75,7 @@ Foam::semiImplicitOversetFvPatchField<Type>::semiImplicitOversetFvPatchField
const dictionary& dict
)
:
LduInterfaceField<Type>(refCast<const oversetFvPatch>(p)),
//LduInterfaceField<Type>(refCast<const oversetFvPatch>(p)),
zeroGradientFvPatchField<Type>(p, iF, dict),
oversetPatch_(refCast<const oversetFvPatch>(p))
{
@ -102,7 +103,7 @@ Foam::semiImplicitOversetFvPatchField<Type>::semiImplicitOversetFvPatchField
const semiImplicitOversetFvPatchField<Type>& ptf
)
:
LduInterfaceField<Type>(ptf.oversetPatch_),
//LduInterfaceField<Type>(ptf.oversetPatch_),
zeroGradientFvPatchField<Type>(ptf),
oversetPatch_(ptf.oversetPatch_)
{}
@ -115,7 +116,7 @@ Foam::semiImplicitOversetFvPatchField<Type>::semiImplicitOversetFvPatchField
const DimensionedField<Type, volMesh>& iF
)
:
LduInterfaceField<Type>(ptf.oversetPatch_),
//LduInterfaceField<Type>(ptf.oversetPatch_),
zeroGradientFvPatchField<Type>(ptf, iF),
oversetPatch_(ptf.oversetPatch_)
{}
@ -198,66 +199,67 @@ void Foam::semiImplicitOversetFvPatchField<Type>::initEvaluate
}
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>::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 cellCellStencilObject& overlap = Stencil::New(*this);
// const labelListList& cellStencil = overlap.cellStencil();
//
// if (cellStencil.size() != psiInternal.size())
// {
// FatalErrorInFunction << "psiInternal:" << psiInternal.size()
// << " stencil:" << cellStencil.size() << exit(FatalError);
// }
//
// const mapDistribute& map = overlap.cellInterpolationMap();
// const List<scalarList>& wghts = overlap.cellInterpolationWeights();
// const labelList& cellIDs = overlap.interpolationCells();
// //const scalarList& factor = overlap.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 = cellStencil[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>

View File

@ -57,7 +57,7 @@ namespace Foam
template<class Type>
class semiImplicitOversetFvPatchField
:
public LduInterfaceField<Type>,
//public LduInterfaceField<Type>,
public zeroGradientFvPatchField<Type>
{
protected:
@ -158,29 +158,29 @@ public:
//- 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;
}
// //- 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

View File

@ -73,6 +73,8 @@ void Foam::semiImplicitOversetGAMGInterfaceField::updateInterfaceMatrix
const Pstream::commsTypes commsType
) const
{
DebugVar("Here");
// Add remote values
if (oversetInterface_.master())
{