diff --git a/applications/solvers/compressible/rhoPimpleFoam/overRhoPimpleDyMFoam/pEqn.H b/applications/solvers/compressible/rhoPimpleFoam/overRhoPimpleDyMFoam/pEqn.H index 5f1fc7451c2e41d21061dba1cdeb96f2cee151d0..ba9cbf752c7374aa9f25608c89df044f6fd1e90a 100644 --- a/applications/solvers/compressible/rhoPimpleFoam/overRhoPimpleDyMFoam/pEqn.H +++ b/applications/solvers/compressible/rhoPimpleFoam/overRhoPimpleDyMFoam/pEqn.H @@ -7,8 +7,8 @@ surfaceScalarField faceMask(localMin<scalar>(mesh).interpolate(cellMask)); volScalarField rAU(1.0/UEqn.A()); surfaceScalarField rhorAUf("rhorAUf", faceMask*fvc::interpolate(rho*rAU)); -volVectorField HbyA("HbyA", constrainHbyA(rAU*UEqn.H(), U, p)); -//mesh.interpolate(HbyA); +volVectorField HbyA("HbyA", U); +HbyA = constrainHbyA(rAU*UEqn.H(), U, p); if (pimple.nCorrPISO() <= 1) { diff --git a/applications/solvers/incompressible/simpleFoam/overSimpleFoam/UEqn.H b/applications/solvers/incompressible/simpleFoam/overSimpleFoam/UEqn.H index 5e9861ccc383ec482ff1e04ff06dbc461e87ebc4..68b208f41b1d30938ac5bbcf2e571c0082dc474c 100644 --- a/applications/solvers/incompressible/simpleFoam/overSimpleFoam/UEqn.H +++ b/applications/solvers/incompressible/simpleFoam/overSimpleFoam/UEqn.H @@ -16,6 +16,9 @@ fvOptions.constrain(UEqn); - solve(UEqn == -cellMask*fvc::grad(p)); + if (simple.momentumPredictor()) + { + solve(UEqn == -cellMask*fvc::grad(p)); + } fvOptions.correct(U); diff --git a/applications/solvers/incompressible/simpleFoam/overSimpleFoam/pEqn.H b/applications/solvers/incompressible/simpleFoam/overSimpleFoam/pEqn.H index c64f92e33f798c6bd762797bfd6a9118e468d838..78555ec5ce8436c7a7e64e9765518295c63421a5 100644 --- a/applications/solvers/incompressible/simpleFoam/overSimpleFoam/pEqn.H +++ b/applications/solvers/incompressible/simpleFoam/overSimpleFoam/pEqn.H @@ -5,7 +5,7 @@ surfaceScalarField rAUf("rAUf", faceMask*fvc::interpolate(rAU)); volVectorField HbyA("HbyA", U); - HbyA = constrainHbyA(rAU*UEqn.H(), U, p); + HbyA = constrainHbyA(cellMask*rAU*UEqn.H(), U, p); //mesh.interpolate(HbyA); if (massFluxInterpolation) diff --git a/applications/solvers/multiphase/interCondensatingEvaporatingFoam/createFields.H b/applications/solvers/multiphase/interCondensatingEvaporatingFoam/createFields.H index 266b339b67570e4b2db6134d9daec29dfa0a6059..c6bde4234f6f3452665a8b943deafe791d30d7b0 100644 --- a/applications/solvers/multiphase/interCondensatingEvaporatingFoam/createFields.H +++ b/applications/solvers/multiphase/interCondensatingEvaporatingFoam/createFields.H @@ -138,3 +138,4 @@ volScalarField pDivU mesh, dimensionedScalar("pDivU", p.dimensions()/dimTime, 0) ); + diff --git a/applications/solvers/multiphase/interFoam/overInterDyMFoam/readControls.H b/applications/solvers/multiphase/interFoam/overInterDyMFoam/readControls.H index d8481c88704f42298d1b7f2c2fad8f843ce8c135..a2acf920692b33ac049e3a166a3c7c6981e5bacf 100644 --- a/applications/solvers/multiphase/interFoam/overInterDyMFoam/readControls.H +++ b/applications/solvers/multiphase/interFoam/overInterDyMFoam/readControls.H @@ -1,6 +1,6 @@ #include "readTimeControls.H" -correctPhi = pimple.dict().lookupOrDefault<Switch>("correctPhi", true); +correctPhi = pimple.dict().lookupOrDefault<Switch>("correctPhi", false); checkMeshCourantNo = pimple.dict().lookupOrDefault<Switch>("checkMeshCourantNo", false); diff --git a/applications/test/rigidBodyDynamics/pendulum/pendulum b/applications/test/rigidBodyDynamics/pendulum/pendulum index d179af4438547ee888802d8074f94b04aeedbad3..3a6b4b18433f54fa2e9de49221406620864a5290 100644 --- a/applications/test/rigidBodyDynamics/pendulum/pendulum +++ b/applications/test/rigidBodyDynamics/pendulum/pendulum @@ -32,6 +32,7 @@ bodies type sphere; mass 1; radius 0.05; + centreOfMass (0 10 0); transform (1 0 0 0 1 0 0 0 1) (0 -1 0); mergeWith hinge; } diff --git a/applications/test/rigidBodyDynamics/pendulumAndSpring/pendulumAndSpring b/applications/test/rigidBodyDynamics/pendulumAndSpring/pendulumAndSpring index ec9c3517b7dd78e5e2f715591fb9e531003e74a9..4f4fdc44c1c8fdd47ee424df748f4f36b3bc1ac3 100644 --- a/applications/test/rigidBodyDynamics/pendulumAndSpring/pendulumAndSpring +++ b/applications/test/rigidBodyDynamics/pendulumAndSpring/pendulumAndSpring @@ -14,6 +14,7 @@ bodies parent root; mass 6e4; radius 0.01; + centreOfMass (0 0 0); transform (1 0 0 0 1 0 0 0 1) (0 0 0); joint { @@ -37,6 +38,7 @@ bodies parent M; mass 6e3; radius 0.01; + centreOfMass (0 0 0); transform (1 0 0 0 1 0 0 0 1) (0 -5 0); mergeWith M; } diff --git a/src/OpenFOAM/meshes/polyMesh/polyBoundaryMesh/polyBoundaryMesh.H b/src/OpenFOAM/meshes/polyMesh/polyBoundaryMesh/polyBoundaryMesh.H index b0bfc8d58571d94fedfc4af53ca2ef102f13e2d3..b2783c5563e76c41e82a3f3a26ae742c77f9625c 100644 --- a/src/OpenFOAM/meshes/polyMesh/polyBoundaryMesh/polyBoundaryMesh.H +++ b/src/OpenFOAM/meshes/polyMesh/polyBoundaryMesh/polyBoundaryMesh.H @@ -233,10 +233,10 @@ public: void reorder(const labelUList&, const bool validBoundary); //- writeData member function required by regIOobject - bool writeData(Ostream&) const; + virtual bool writeData(Ostream&) const; //- Write using given format, version and form uncompression - bool writeObject + virtual bool writeObject ( IOstream::streamFormat fmt, IOstream::versionNumber ver, diff --git a/src/finiteVolume/fvMesh/wallDist/patchDistMethods/Poisson/PoissonPatchDistMethod.C b/src/finiteVolume/fvMesh/wallDist/patchDistMethods/Poisson/PoissonPatchDistMethod.C index 7dd34b9343e3f0d5f5f1183115df65b2c441c7ba..542dc624cf7bdff18b3057d2c30b8424788f9428 100644 --- a/src/finiteVolume/fvMesh/wallDist/patchDistMethods/Poisson/PoissonPatchDistMethod.C +++ b/src/finiteVolume/fvMesh/wallDist/patchDistMethods/Poisson/PoissonPatchDistMethod.C @@ -101,7 +101,18 @@ bool Foam::patchDistMethods::Poisson::correct volVectorField gradyPsi(fvc::grad(yPsi)); volScalarField magGradyPsi(mag(gradyPsi)); - y = sqrt(magSqr(gradyPsi) + 2*yPsi) - magGradyPsi; + // Need to stabilise the y for overset meshes since the holed cells + // keep the initial value (0.0) so the gradient of that will be + // zero as well. Turbulence models do not like zero wall distance. + y = max + ( + sqrt(magSqr(gradyPsi) + 2*yPsi) - magGradyPsi, + dimensionedScalar("smallY", dimLength, SMALL) + ); + + // For overset: enforce smooth y field (yPsi is smooth, magGradyPsi is + // not) + mesh_.interpolate(y); // Need to stabilise the y for overset meshes since the holed cells // keep the initial value (0.0) so the gradient of that will be diff --git a/src/overset/Make/files b/src/overset/Make/files index a285c4979cc925fc794b52b95129686c2bf1ccfa..14ce43d1f27894ad3e70dcc5ffe470a9d9806aaa 100644 --- a/src/overset/Make/files +++ b/src/overset/Make/files @@ -6,6 +6,7 @@ cellCellStencil/inverseDistance/waveMethod.C cellCellStencil/inverseDistance/meshToMeshData.C cellCellStencil/trackingInverseDistance/voxelMeshSearch.C cellCellStencil/trackingInverseDistance/trackingInverseDistanceCellCellStencil.C +cellCellStencil/leastSquares/leastSquaresCellCellStencil.C dynamicOversetFvMesh/dynamicOversetFvMesh.C @@ -21,6 +22,9 @@ oversetPolyPatch/oversetGAMGInterfaceField.C oversetPolyPatch/oversetPointPatch.C oversetPolyPatch/oversetPointPatchFields.C +oversetPolyPatch/semiImplicitOversetFvPatchFields.C +oversetPolyPatch/semiImplicitOversetGAMGInterfaceField.C + oversetAdjustPhi/oversetAdjustPhi.C regionsToCell/regionsToCell.C diff --git a/src/overset/cellCellStencil/cellCellStencil/cellCellStencil.C b/src/overset/cellCellStencil/cellCellStencil/cellCellStencil.C index 9a2851870d5b682fd916a6d179efb2986f2f1d6b..15b2c00a6ba335533bc319d28dd567e38a194d96 100644 --- a/src/overset/cellCellStencil/cellCellStencil/cellCellStencil.C +++ b/src/overset/cellCellStencil/cellCellStencil/cellCellStencil.C @@ -94,22 +94,22 @@ Foam::cellCellStencil::~cellCellStencil() // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // -const Foam::labelIOList& Foam::cellCellStencil::zoneID() const +const Foam::labelIOList& Foam::cellCellStencil::zoneID(const fvMesh& mesh) { - if (!mesh_.foundObject<labelIOList>("zoneID")) + if (!mesh.foundObject<labelIOList>("zoneID")) { labelIOList* zoneIDPtr = new labelIOList ( IOobject ( "zoneID", - mesh_.facesInstance(), + mesh.facesInstance(), polyMesh::meshSubDir, - mesh_, + mesh, IOobject::NO_READ, IOobject::NO_WRITE ), - mesh_.nCells() + mesh.nCells() ); labelIOList& zoneID = *zoneIDPtr; @@ -118,13 +118,13 @@ const Foam::labelIOList& Foam::cellCellStencil::zoneID() const IOobject ( "zoneID", - mesh_.time().findInstance(mesh_.dbDir(), "zoneID"), - mesh_, + mesh.time().findInstance(mesh.dbDir(), "zoneID"), + mesh, IOobject::MUST_READ, IOobject::NO_WRITE, false ), - mesh_ + mesh ); forAll(volZoneID, cellI) { @@ -133,7 +133,7 @@ const Foam::labelIOList& Foam::cellCellStencil::zoneID() const zoneIDPtr->store(); } - return mesh_.lookupObject<labelIOList>("zoneID"); + return mesh.lookupObject<labelIOList>("zoneID"); } diff --git a/src/overset/cellCellStencil/cellCellStencil/cellCellStencil.H b/src/overset/cellCellStencil/cellCellStencil/cellCellStencil.H index b46f5339932f504f7e94e431a75ea92cdec9110a..05a3d7cf590163ade3b6e00e012222808733222d 100644 --- a/src/overset/cellCellStencil/cellCellStencil/cellCellStencil.H +++ b/src/overset/cellCellStencil/cellCellStencil/cellCellStencil.H @@ -168,12 +168,27 @@ public: // calculated, 1 = use interpolated) virtual const scalarList& cellInterpolationWeight() const = 0; + //- Calculate weights for a single acceptor + virtual void stencilWeights + ( + const point& sample, + const pointList& donorCcs, + scalarList& weights + ) const = 0; + //- Helper: is stencil fully local bool localStencil(const labelUList&) const; //- Helper: get reference to registered zoneID. Loads volScalarField // if not registered. - const labelIOList& zoneID() const; + static const labelIOList& zoneID(const fvMesh&); + + //- Helper: get reference to registered zoneID. Loads volScalarField + // if not registered. + const labelIOList& zoneID() const + { + return zoneID(mesh_); + } //- Helper: create cell-cell addressing in global numbering static void globalCellCells diff --git a/src/overset/cellCellStencil/cellCellStencil/cellCellStencilObject.H b/src/overset/cellCellStencil/cellCellStencil/cellCellStencilObject.H index 2a0e3ca15df14c9560d36d9f46ab1025b4b965f7..c465b7c101dd5972a9e5277f52ce55487f0b12f9 100644 --- a/src/overset/cellCellStencil/cellCellStencil/cellCellStencilObject.H +++ b/src/overset/cellCellStencil/cellCellStencil/cellCellStencilObject.H @@ -154,6 +154,17 @@ public: { return stencilPtr_().cellInterpolationWeight(); } + + //- Calculate weights for a single acceptor + virtual void stencilWeights + ( + const point& sample, + const pointList& donorCcs, + scalarList& weights + ) const + { + stencilPtr_().stencilWeights(sample, donorCcs, weights); + } }; diff --git a/src/overset/cellCellStencil/cellVolumeWeight/cellVolumeWeightCellCellStencil.C b/src/overset/cellCellStencil/cellVolumeWeight/cellVolumeWeightCellCellStencil.C index 85c20494d7038fc188e459cee1d419eb943c0dd1..d030bc1623da30d8f09b38f64a8a2adb6f23c1c7 100644 --- a/src/overset/cellCellStencil/cellVolumeWeight/cellVolumeWeightCellCellStencil.C +++ b/src/overset/cellCellStencil/cellVolumeWeight/cellVolumeWeightCellCellStencil.C @@ -1100,4 +1100,39 @@ bool Foam::cellCellStencils::cellVolumeWeight::update() } +void Foam::cellCellStencils::cellVolumeWeight::stencilWeights +( + const point& sample, + const pointList& donorCcs, + scalarList& weights +) const +{ + // Inverse-distance weighting + + weights.setSize(donorCcs.size()); + scalar sum = 0.0; + forAll(donorCcs, i) + { + scalar d = mag(sample-donorCcs[i]); + + if (d > ROOTVSMALL) + { + weights[i] = 1.0/d; + sum += weights[i]; + } + else + { + // Short circuit + weights = 0.0; + weights[i] = 1.0; + return; + } + } + forAll(weights, i) + { + weights[i] /= sum; + } +} + + // ************************************************************************* // diff --git a/src/overset/cellCellStencil/cellVolumeWeight/cellVolumeWeightCellCellStencil.H b/src/overset/cellCellStencil/cellVolumeWeight/cellVolumeWeightCellCellStencil.H index 4331b1421f5e4c0b82b6c10fac66492e15c319ef..6c1a8003be768d320d44c8a484d095a6e8d954af 100644 --- a/src/overset/cellCellStencil/cellVolumeWeight/cellVolumeWeightCellCellStencil.H +++ b/src/overset/cellCellStencil/cellVolumeWeight/cellVolumeWeightCellCellStencil.H @@ -227,6 +227,15 @@ public: { return cellInterpolationWeight_; } + + //- Calculate inverse distance weights for a single acceptor. Revert + // to inverse distance (so not consistent with volume overlap!) + virtual void stencilWeights + ( + const point& sample, + const pointList& donorCcs, + scalarList& weights + ) const; }; diff --git a/src/overset/cellCellStencil/inverseDistance/inverseDistanceCellCellStencil.C b/src/overset/cellCellStencil/inverseDistance/inverseDistanceCellCellStencil.C index eb0d12915947bb00da7d9cb95b247efa0b871bcc..ef5a35724a3f3c9f0a8edd4838224541666a71d0 100644 --- a/src/overset/cellCellStencil/inverseDistance/inverseDistanceCellCellStencil.C +++ b/src/overset/cellCellStencil/inverseDistance/inverseDistanceCellCellStencil.C @@ -155,6 +155,7 @@ void Foam::cellCellStencils::inverseDistance::fill void Foam::cellCellStencils::inverseDistance::markBoundaries ( const fvMesh& mesh, + const vector& smallVec, const boundBox& bb, const labelVector& nDivs, @@ -188,6 +189,9 @@ void Foam::cellCellStencils::inverseDistance::markBoundaries // Mark in voxel mesh boundBox faceBb(pp.points(), pp[i], false); + faceBb.min() -= smallVec; + faceBb.max() += smallVec; + if (bb.overlaps(faceBb)) { fill(patchTypes, bb, nDivs, faceBb, patchCellType::PATCH); @@ -213,6 +217,9 @@ void Foam::cellCellStencils::inverseDistance::markBoundaries // Mark in voxel mesh boundBox faceBb(pp.points(), pp[i], false); + faceBb.min() -= smallVec; + faceBb.max() += smallVec; + if (bb.overlaps(faceBb)) { fill(patchTypes, bb, nDivs, faceBb, patchCellType::OVERSET); @@ -333,6 +340,10 @@ void Foam::cellCellStencils::inverseDistance::markPatchesAsHoles forAll(tgtCellMap, tgtCelli) { label celli = tgtCellMap[tgtCelli]; + treeBoundBox cBb(cellBb(mesh_, celli)); + cBb.min() -= smallVec_; + cBb.max() += smallVec_; + if ( overlaps @@ -340,7 +351,7 @@ void Foam::cellCellStencils::inverseDistance::markPatchesAsHoles srcPatchBb, zoneDivs, srcPatchTypes, - cellBb(mesh_, celli), + cBb, patchCellType::PATCH ) ) @@ -399,6 +410,9 @@ void Foam::cellCellStencils::inverseDistance::markPatchesAsHoles forAll(tgtCellMap, tgtCelli) { label celli = tgtCellMap[tgtCelli]; + treeBoundBox cBb(cellBb(mesh_, celli)); + cBb.min() -= smallVec_; + cBb.max() += smallVec_; if ( overlaps @@ -406,7 +420,7 @@ void Foam::cellCellStencils::inverseDistance::markPatchesAsHoles srcPatchBb, zoneDivs, srcPatchTypes, - cellBb(mesh_, celli), + cBb, patchCellType::PATCH ) ) @@ -501,7 +515,9 @@ void Foam::cellCellStencils::inverseDistance::markDonors label celli = tgtCellMap[tgtCelli]; if (allStencil[celli].empty()) { - const treeBoundBox subBb(cellBb(mesh_, celli)); + treeBoundBox subBb(cellBb(mesh_, celli)); + subBb.min() -= smallVec_; + subBb.max() += smallVec_; forAll(srcOverlapProcs, i) { @@ -1194,9 +1210,17 @@ void Foam::cellCellStencils::inverseDistance::walkFront { if (isA<oversetFvPatch>(fvm[patchI])) { - forAll(fvm[patchI], i) + const labelList& fc = fvm[patchI].faceCells(); + forAll(fc, i) { - isFront[fvm[patchI].start()+i] = true; + label cellI = fc[i]; + if (allCellTypes[cellI] == INTERPOLATED) + { + // Note that acceptors might have been marked hole if + // there are no donors in which case we do not want to + // walk this out. This is an extreme situation. + isFront[fvm[patchI].start()+i] = true; + } } } } @@ -1353,12 +1377,12 @@ void Foam::cellCellStencils::inverseDistance::walkFront } -void Foam::cellCellStencils::inverseDistance::calcStencilWeights +void Foam::cellCellStencils::inverseDistance::stencilWeights ( const point& sample, const pointList& donorCcs, scalarList& weights -) +) const { // Inverse-distance weighting @@ -1500,7 +1524,7 @@ void Foam::cellCellStencils::inverseDistance::createStencil { label cellI = donorCells[i]; const pointList& donorCentres = donorCellCentres[cellI]; - calcStencilWeights + stencilWeights ( samples[cellI], donorCentres, @@ -1565,6 +1589,7 @@ Foam::cellCellStencils::inverseDistance::inverseDistance : cellCellStencil(mesh), dict_(dict), + smallVec_(vector::zero), cellTypes_(labelList(mesh.nCells(), CALCULATED)), interpolationCells_(0), cellInterpolationMap_(), @@ -1605,6 +1630,9 @@ bool Foam::cellCellStencils::inverseDistance::update() { scalar layerRelax(dict_.lookupOrDefault("layerRelax", 1.0)); + scalar tol = dict_.lookupOrDefault("tolerance", 1e-10); + smallVec_ = mesh_.bounds().span()*tol; + const labelIOList& zoneID = this->zoneID(); label nZones = gMax(zoneID)+1; @@ -1745,6 +1773,7 @@ bool Foam::cellCellStencils::inverseDistance::update() markBoundaries ( meshParts[zoneI].subMesh(), + smallVec_, patchBb[zoneI][Pstream::myProcNo()], patchDivisions[zoneI], @@ -1758,7 +1787,7 @@ bool Foam::cellCellStencils::inverseDistance::update() // Print a bit { - Info<< typeName << " : detected " << nZones + Info<< type() << " : detected " << nZones << " mesh regions" << endl; Info<< incrIndent; forAll(nCellsPerZone, zoneI) @@ -1862,6 +1891,16 @@ bool Foam::cellCellStencils::inverseDistance::update() } else { + // If there are no donors we can either set the + // acceptor cell to 'hole' i.e. nothing gets calculated + // if the acceptor cells go outside the donor meshes or + // we can set it to 'calculated' to have something + // like an acmi type behaviour where only covered + // acceptor cell use the interpolation and non-covered + // become calculated. Uncomment below line. Note: this + // should be switchable? + //allCellTypes[cellI] = CALCULATED; + allCellTypes[cellI] = HOLE; } } @@ -1915,7 +1954,7 @@ bool Foam::cellCellStencils::inverseDistance::update() // Dump stencil mkDir(mesh_.time().timePath()); OBJstream str(mesh_.time().timePath()/"injectionStencil.obj"); - Pout<< typeName << " : dumping injectionStencil to " + Pout<< type() << " : dumping injectionStencil to " << str.name() << endl; pointField cc(mesh_.cellCentres()); cellInterpolationMap_.distribute(cc); @@ -1973,7 +2012,7 @@ bool Foam::cellCellStencils::inverseDistance::update() // Dump stencil mkDir(mesh_.time().timePath()); OBJstream str(mesh_.time().timePath()/"stencil.obj"); - Pout<< typeName << " : dumping to " << str.name() << endl; + Pout<< type() << " : dumping to " << str.name() << endl; pointField cc(mesh_.cellCentres()); cellInterpolationMap_.distribute(cc); diff --git a/src/overset/cellCellStencil/inverseDistance/inverseDistanceCellCellStencil.H b/src/overset/cellCellStencil/inverseDistance/inverseDistanceCellCellStencil.H index ffc9a291ef4b00cd6633f855bc57b38c62cb8b76..1a57c6034048986a1a4d0dc5be6a4d2c17cbacda 100644 --- a/src/overset/cellCellStencil/inverseDistance/inverseDistanceCellCellStencil.H +++ b/src/overset/cellCellStencil/inverseDistance/inverseDistanceCellCellStencil.H @@ -74,6 +74,9 @@ protected: //- Dictionary of motion control parameters const dictionary dict_; + //- Small perturbation vector for geometric tests + vector smallVec_; + //- Per cell the cell type labelList cellTypes_; @@ -143,6 +146,8 @@ protected: static void markBoundaries ( const fvMesh& mesh, + const vector& smallVec, + const boundBox& bb, const labelVector& nDivs, PackedList<2>& patchTypes, @@ -237,15 +242,6 @@ protected: scalarField& allWeight ) const; - - //- Calculate inverse distance weights - static void calcStencilWeights - ( - const point& sample, - const pointList& donorCcs, - scalarList& weights - ); - //- Create stencil starting from the donor containing the acceptor virtual void createStencil(const globalIndex&); @@ -319,6 +315,14 @@ public: { return cellInterpolationWeight_; } + + //- Calculate inverse distance weights for a single acceptor + virtual void stencilWeights + ( + const point& sample, + const pointList& donorCcs, + scalarList& weights + ) const; }; diff --git a/src/overset/cellCellStencil/leastSquares/leastSquaresCellCellStencil.C b/src/overset/cellCellStencil/leastSquares/leastSquaresCellCellStencil.C new file mode 100644 index 0000000000000000000000000000000000000000..8f2da7a0ba010e66b977be872121847797d8e5cd --- /dev/null +++ b/src/overset/cellCellStencil/leastSquares/leastSquaresCellCellStencil.C @@ -0,0 +1,177 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2017 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify i + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "leastSquaresCellCellStencil.H" +#include "addToRunTimeSelectionTable.H" +#include "SVD.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ +namespace cellCellStencils +{ + defineTypeNameAndDebug(leastSquares, 0); + addToRunTimeSelectionTable(cellCellStencil, leastSquares, mesh); +} +} + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +void Foam::cellCellStencils::leastSquares::stencilWeights +( + const point& sample, + const pointList& donorCcs, + scalarList& weights +) const +{ + // Implicit least squares weighting + // Number of donors + label nD = donorCcs.size(); + + weights.setSize(nD); + + // List for distance vectors and LSQ weights + List<vector> d(nD); + scalarList LSQw(nD); + + // Sum of weights + scalar W = 0; + + // Sum of weighted distance vectors + vector dw = vector::zero; + + RectangularMatrix<scalar> A(nD, 3); + + bool shortC = false; + + // Compute distance vectors and fill rectangular matrix + forAll(donorCcs, j) + { + // Neighbour weights + d[j] = donorCcs[j] - sample; + + // Check for short-circuiting if zero distance + // is detected with respect to any donor + if (mag(d[j]) < ROOTVSMALL) + { + shortC = true; + break; + } + + LSQw[j] = 1.0/magSqr(d[j]); + + // T matrix + vector wd = LSQw[j]*d[j]; + A[j][0] = wd.x(); + A[j][1] = wd.y(); + A[j][2] = wd.z(); + + // Sum of weighted distance vectors + dw += wd; + + // Sum of weights + W += LSQw[j]; + } + + if (!shortC) + { + // Use Singular Value Decomposition to avoid problems + // with 1D, 2D stencils + SVD svd(A.T()*A, SMALL); + + // Least squares vectors + RectangularMatrix<scalar> ATAinvAT(svd.VSinvUt()*A.T()); + + scalar saveDiag(W); + + // Diagonal coefficient + for (label i = 0; i < 3; i++) + { + // Get row + scalarList Row(UList<scalar>(ATAinvAT[i], nD)); + + forAll(donorCcs, j) + { + W -= Row[j]*LSQw[j]*dw[i]; + } + } + + if (mag(W) < SMALL*mag(saveDiag)) + { + shortC = true; + } + else + { + // Compute final neighbour weights with additional scaling + forAll(donorCcs, j) + { + weights[j] = + ( + LSQw[j] + - ATAinvAT[0][j]*LSQw[j]*dw[0] + - ATAinvAT[1][j]*LSQw[j]*dw[1] + - ATAinvAT[2][j]*LSQw[j]*dw[2] + ) + /W; + } + } + } + + if (shortC) + { + // Matrix ill conditioned. Use straight injection from central + // donor. + weights = 0.0; + weights[0] = 1.0; + } +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::cellCellStencils::leastSquares::leastSquares +( + const fvMesh& mesh, + const dictionary& dict, + const bool doUpdate +) +: + inverseDistance(mesh, dict, false) +{ + if (doUpdate) + { + update(); + } +} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::cellCellStencils::leastSquares::~leastSquares() +{} + + +// ************************************************************************* // diff --git a/src/overset/cellCellStencil/leastSquares/leastSquaresCellCellStencil.H b/src/overset/cellCellStencil/leastSquares/leastSquaresCellCellStencil.H new file mode 100644 index 0000000000000000000000000000000000000000..4d9b88eb0fe31347c5dc844fe31d208b950f79d3 --- /dev/null +++ b/src/overset/cellCellStencil/leastSquares/leastSquaresCellCellStencil.H @@ -0,0 +1,107 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2017 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::cellCellStencils::leastSquares + +Description + Least-squares-weighted interpolation stencil. + + Base machinery is similar to inverse distance interpolation stencil + but weights minimize error in LSQ sense recovering exact solution + for linear solution problems. Gradient and values are found + simultaneously. + +SourceFiles + leastSquaresCellCellStencil.C + +\*---------------------------------------------------------------------------*/ + +#ifndef cellCellStencils_leastSquares_H +#define cellCellStencils_leastSquares_H + +#include "inverseDistanceCellCellStencil.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +namespace cellCellStencils +{ + +/*---------------------------------------------------------------------------*\ + Class leastSquares Declaration +\*---------------------------------------------------------------------------*/ + +class leastSquares +: + public inverseDistance +{ + // Private Member Functions + + //- Disallow default bitwise copy construct + leastSquares(const leastSquares&); + + //- Disallow default bitwise assignment + void operator=(const leastSquares&); + + +public: + + //- Runtime type information + TypeName("leastSquares"); + + + // Constructors + + //- Construct from fvMesh + leastSquares(const fvMesh&, const dictionary&, const bool); + + + //- Destructor + virtual ~leastSquares(); + + + // Member Functions + + //- Calculate lsq weights for single acceptor + virtual void stencilWeights + ( + const point& sample, + const pointList& donorCcs, + scalarList& weights + ) const; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace cellCellStencils +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/overset/cellCellStencil/trackingInverseDistance/trackingInverseDistanceCellCellStencil.C b/src/overset/cellCellStencil/trackingInverseDistance/trackingInverseDistanceCellCellStencil.C index 7a9b2906f6bb08bcf37a48ef03a287182d6fd767..b2e3efccd50b3fd5129fae3e263fd3775c79c586 100644 --- a/src/overset/cellCellStencil/trackingInverseDistance/trackingInverseDistanceCellCellStencil.C +++ b/src/overset/cellCellStencil/trackingInverseDistance/trackingInverseDistanceCellCellStencil.C @@ -51,6 +51,7 @@ namespace cellCellStencils void Foam::cellCellStencils::trackingInverseDistance::markBoundaries ( const fvMesh& mesh, + const vector& smallVec, const boundBox& bb, const labelVector& nDivs, @@ -84,6 +85,9 @@ void Foam::cellCellStencils::trackingInverseDistance::markBoundaries // Mark in voxel mesh boundBox faceBb(pp.points(), pp[i], false); + faceBb.min() -= smallVec; + faceBb.max() += smallVec; + if (bb.overlaps(faceBb)) { voxelMeshSearch::fill @@ -116,6 +120,8 @@ void Foam::cellCellStencils::trackingInverseDistance::markBoundaries // Mark in voxel mesh boundBox faceBb(pp.points(), pp[i], false); + faceBb.min() -= smallVec; + faceBb.max() += smallVec; if (bb.overlaps(faceBb)) { voxelMeshSearch::fill @@ -165,6 +171,9 @@ void Foam::cellCellStencils::trackingInverseDistance::markPatchesAsHoles forAll(tgtCellMap, tgtCelli) { label celli = tgtCellMap[tgtCelli]; + boundBox cBb(allPoints, allCellPoints[celli], false); + cBb.min() -= smallVec_; + cBb.max() += smallVec_; if ( @@ -172,7 +181,7 @@ void Foam::cellCellStencils::trackingInverseDistance::markPatchesAsHoles ( srcPatchBb, srcDivs, - boundBox(allPoints, allCellPoints[celli], false), + cBb, srcPatchTypes, static_cast<unsigned int>(patchCellType::PATCH) ) @@ -231,13 +240,17 @@ void Foam::cellCellStencils::trackingInverseDistance::markPatchesAsHoles forAll(tgtCellMap, tgtCelli) { label celli = tgtCellMap[tgtCelli]; + boundBox cBb(allPoints, allCellPoints[celli], false); + cBb.min() -= smallVec_; + cBb.max() += smallVec_; + if ( voxelMeshSearch::overlaps ( srcPatchBb, srcDivs, - boundBox(allPoints, allCellPoints[celli], false), + cBb, srcPatchTypes, static_cast<unsigned int>(patchCellType::PATCH) ) @@ -628,6 +641,7 @@ bool Foam::cellCellStencils::trackingInverseDistance::update() markBoundaries ( meshParts_[zonei].subMesh(), + smallVec_, patchBb[zonei][Pstream::myProcNo()], patchDivisions[zonei], diff --git a/src/overset/cellCellStencil/trackingInverseDistance/trackingInverseDistanceCellCellStencil.H b/src/overset/cellCellStencil/trackingInverseDistance/trackingInverseDistanceCellCellStencil.H index f0cafa3521c7fa1ad541d4ff2fe54ab50710407b..bcc49000c445110fcedb022929d6af609261abc5 100644 --- a/src/overset/cellCellStencil/trackingInverseDistance/trackingInverseDistanceCellCellStencil.H +++ b/src/overset/cellCellStencil/trackingInverseDistance/trackingInverseDistanceCellCellStencil.H @@ -77,6 +77,7 @@ protected: static void markBoundaries ( const fvMesh& mesh, + const vector& smallVec, const boundBox& bb, const labelVector& nDivs, diff --git a/src/overset/dynamicOversetFvMesh/dynamicOversetFvMesh.C b/src/overset/dynamicOversetFvMesh/dynamicOversetFvMesh.C index deb346f0816a0fcf838e15ec09ecd91b9693e271..526e813b6c62bc8ba5c8695f2cc3bfa8dbad281a 100644 --- a/src/overset/dynamicOversetFvMesh/dynamicOversetFvMesh.C +++ b/src/overset/dynamicOversetFvMesh/dynamicOversetFvMesh.C @@ -228,7 +228,10 @@ Foam::dynamicOversetFvMesh::dynamicOversetFvMesh(const IOobject& io) : dynamicMotionSolverFvMesh(io), active_(false) -{} +{ + // Force loading zoneID field before time gets incremented + (void)cellCellStencil::zoneID(*this); +} // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // diff --git a/src/overset/dynamicOversetFvMesh/dynamicOversetFvMesh.H b/src/overset/dynamicOversetFvMesh/dynamicOversetFvMesh.H index 0b61ed42a70b2eb9bc51d0fe3e6f6b1e78d3fc96..3f8d9782f4846f6f855e417cf07a1ba5b37ef20e 100644 --- a/src/overset/dynamicOversetFvMesh/dynamicOversetFvMesh.H +++ b/src/overset/dynamicOversetFvMesh/dynamicOversetFvMesh.H @@ -38,6 +38,8 @@ SourceFiles #include "dynamicMotionSolverFvMesh.H" #include "labelIOList.H" #include "fvMeshPrimitiveLduAddressing.H" +#include "lduInterfaceFieldPtrsList.H" +#include "volFields.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -100,6 +102,14 @@ protected: template<class GeoField> void interpolate(GeoField& psi) const; + //- Freeze values at holes + template<class Type> + void freezeHoles(fvMatrix<Type>&) const; + + //- Get scalar interfaces of certain type + template<class GeoField, class PatchType> + lduInterfaceFieldPtrsList scalarInterfaces(const GeoField& psi) const; + //- Add interpolation to matrix (coefficients) template<class Type> void addInterpolation(fvMatrix<Type>&) const; @@ -112,25 +122,6 @@ protected: template<class GeoField> static void correctCoupledBoundaryConditions(GeoField& fld); - //- Use extended addressing - void active(const bool f) const - { - active_ = f; - - if (active_) - { - DebugInfo<< "Switching to extended addressing with nFaces:" - << primitiveLduAddr().lowerAddr().size() - << endl; - } - else - { - DebugInfo<< "Switching to base addressing with nFaces:" - << fvMesh::lduAddr().lowerAddr().size() - << endl; - } - } - private: @@ -164,12 +155,6 @@ public: // Extended addressing - //- Use extended addressing - bool active() const - { - return active_; - } - //- Return extended ldu addressing const fvMeshPrimitiveLduAddressing& primitiveLduAddr() const; @@ -177,6 +162,37 @@ public: // primitiveLduAddr virtual const lduAddressing& lduAddr() const; + //- Return old to new face addressing + const labelList& reverseFaceMap() const + { + return reverseFaceMap_; + } + + //- Return true if using extended addressing + bool active() const + { + return active_; + } + + //- Enable/disable extended addressing + void active(const bool f) const + { + active_ = f; + + if (active_) + { + DebugInfo<< "Switching to extended addressing with nFaces:" + << primitiveLduAddr().lowerAddr().size() + << endl; + } + else + { + DebugInfo<< "Switching to base addressing with nFaces:" + << fvMesh::lduAddr().lowerAddr().size() + << endl; + } + } + // Overset diff --git a/src/overset/dynamicOversetFvMesh/dynamicOversetFvMeshTemplates.C b/src/overset/dynamicOversetFvMesh/dynamicOversetFvMeshTemplates.C index dce8e9cd7a86c4d0848476f47db121147b6d4319..006c576d096686634fa77a71f733ef771d194771 100644 --- a/src/overset/dynamicOversetFvMesh/dynamicOversetFvMeshTemplates.C +++ b/src/overset/dynamicOversetFvMesh/dynamicOversetFvMeshTemplates.C @@ -26,6 +26,7 @@ License #include "volFields.H" #include "fvMatrix.H" #include "cellCellStencilObject.H" +#include "oversetFvPatchField.H" // * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * * // @@ -77,41 +78,34 @@ void Foam::dynamicOversetFvMesh::interpolate(GeoField& psi) const } -//template<class T> -//void Foam::dynamicOversetFvMesh::setReference(fvMatrix<T>& m) const -//{ -// const mapDistribute& map = cellInterpolationMap(); -// const List<scalarList>& wghts = cellInterpolationWeights(); -// const labelListList& stencil = cellStencil(); -// const labelList& cellIDs = interpolationCells(); -// const scalarList& factor = cellInterpolationWeight(); -// -// Field<T> work(m.psi()); -// 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]; -// -// //Pout<< "Interpolating " << celli << " from values:" << endl; -// T s(pTraits<T>::zero); -// forAll(nbrs, nbrI) -// { -// //Pout<< " " << work[nbrs[nbrI]] -// // << " from slot " << nbrs[nbrI] << endl; -// s += w[nbrI]*work[nbrs[nbrI]]; -// } -// //Pout<< "Interpolated value:" << s << endl; -// const T oldPsi = m.psi()[celli]; -// m.setReference(celli, (1.0-f)*oldPsi + f*s, true); -// Pout<< "psi was:" << oldPsi << " now forcing to:" -// << (1.0-f)*oldPsi + f*s << endl; -// } -//} +template<class GeoField, class PatchType> +Foam::lduInterfaceFieldPtrsList +Foam::dynamicOversetFvMesh::scalarInterfaces(const GeoField& psi) const +{ + const typename GeoField::Boundary& bpsi = psi.boundaryField(); + + lduInterfaceFieldPtrsList interfaces(bpsi.size()); + + forAll(interfaces, patchi) + { + if + ( + isA<lduInterfaceField>(bpsi[patchi]) + && isA<PatchType>(bpsi[patchi]) + ) + { + interfaces.set + ( + patchi, + &refCast<const lduInterfaceField> + ( + bpsi[patchi] + ) + ); + } + } + return interfaces; +} template<class Type> @@ -185,6 +179,7 @@ void Foam::dynamicOversetFvMesh::addInterpolation(fvMatrix<Type>& m) const } } + forAll(m.internalCoeffs(), patchI) { const labelUList& fc = addr.patchAddr(patchI); @@ -209,6 +204,76 @@ void Foam::dynamicOversetFvMesh::addInterpolation(fvMatrix<Type>& m) const } } + // NOTE: For a non-scalar matrix, in the function fvMatrix::solveSegregated + // it uses updateInterfaceMatrix to correct for remote source contributions. + // This unfortunately also triggers the overset interpolation which then + // produces a non-zero source for interpolated cells. + // The procedure below calculates this contribution 'correctionSource' + // and substracts it from the source later in order to compensate. + Field<Type> correctionSource(diag.size(), pTraits<Type>::zero); + + if (pTraits<Type>::nComponents > 1) + { + typedef GeometricField<Type, fvPatchField, volMesh> GeoField; + + typename pTraits<Type>::labelType validComponents + ( + this->template validComponents<Type>() + ); + + // Get all the overset lduInterfaces + lduInterfaceFieldPtrsList interfaces + ( + scalarInterfaces<GeoField, oversetFvPatchField<Type>> + ( + m.psi() + ) + ); + + const Field<Type>& psiInt = m.psi().primitiveField(); + + for (direction cmpt=0; cmpt<pTraits<Type>::nComponents; cmpt++) + { + if (component(validComponents, cmpt) != -1) + { + const scalarField psiCmpt(psiInt.component(cmpt)); + scalarField corrSourceCmpt(correctionSource.component(cmpt)); + + forAll(interfaces, patchi) + { + if (interfaces.set(patchi)) + { + interfaces[patchi].initInterfaceMatrixUpdate + ( + corrSourceCmpt, + true, + psiCmpt, + m.boundaryCoeffs()[patchi].component(cmpt), + cmpt, + Pstream::defaultCommsType + ); + } + } + forAll(interfaces, patchi) + { + if (interfaces.set(patchi)) + { + interfaces[patchi].updateInterfaceMatrix + ( + corrSourceCmpt, + true, + psiCmpt, + m.boundaryCoeffs()[patchi].component(cmpt), + cmpt, + Pstream::defaultCommsType + ); + } + } + correctionSource.replace(cmpt, corrSourceCmpt); + } + } + } + // Modify matrix @@ -271,12 +336,14 @@ void Foam::dynamicOversetFvMesh::addInterpolation(fvMatrix<Type>& m) const { // 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). diag[celli] *= (1.0-f); diag[celli] += normalisation*f; source[celli] *= (1.0-f); - source[celli] += normalisation*f*pTraits<Type>::zero; // dummy + source[celli] -= correctionSource[celli]; //Pout<< "Interpolating " << celli << " with factor:" << f // << " new diag:" << diag[celli] @@ -328,6 +395,39 @@ Foam::SolverPerformance<Type> Foam::dynamicOversetFvMesh::solve const dictionary& dict ) const { + // Check we're running with bcs that can handle implicit matrix manipulation + const typename GeometricField<Type, fvPatchField, volMesh>::Boundary bpsi = + m.psi().boundaryField(); + + bool hasOverset = false; + forAll(bpsi, patchi) + { + if (isA<oversetFvPatchField<Type>>(bpsi[patchi])) + { + hasOverset = true; + break; + } + } + + if (!hasOverset) + { + if (debug) + { + Pout<< "dynamicOversetFvMesh::solve() :" + << " bypassing matrix adjustment for field " << m.psi().name() + << endl; + } + return dynamicMotionSolverFvMesh::solve(m, dict); + } + + if (debug) + { + Pout<< "dynamicOversetFvMesh::solve() :" + << " adjusting matrix for interpolation for field " + << m.psi().name() << endl; + } + + // Switch to extended addressing (requires mesh::update() having been // called) active(true); @@ -346,8 +446,7 @@ Foam::SolverPerformance<Type> Foam::dynamicOversetFvMesh::solve // Use lower level solver SolverPerformance<Type> s(dynamicMotionSolverFvMesh::solve(m, dict)); - // Reset matrix (shuffle faces into original order) - //resetMatrix(m); + // Restore matrix m.upper().transfer(oldUpper); m.lower().transfer(oldLower); m.internalCoeffs().transfer(oldInt); diff --git a/src/overset/oversetAdjustPhi/oversetAdjustPhi.C b/src/overset/oversetAdjustPhi/oversetAdjustPhi.C index b6eb644b5502d8841ea896559eb4a116abff4933..28c533c761e9f0c22f5b4c9a38f0bd1f7f350145 100644 --- a/src/overset/oversetAdjustPhi/oversetAdjustPhi.C +++ b/src/overset/oversetAdjustPhi/oversetAdjustPhi.C @@ -92,7 +92,7 @@ bool Foam::oversetAdjustPhi else { adjustableMassOut[zonei] += flux; - } + } } } } diff --git a/src/overset/oversetPolyPatch/oversetFvPatchField.C b/src/overset/oversetPolyPatch/oversetFvPatchField.C index de61b8c118e6c335a50c73a4ff3ffd7f690041b0..da288827af0ab0ac8beeacb4f8ad92f0b559a3fc 100644 --- a/src/overset/oversetPolyPatch/oversetFvPatchField.C +++ b/src/overset/oversetPolyPatch/oversetFvPatchField.C @@ -24,6 +24,8 @@ License \*---------------------------------------------------------------------------*/ #include "volFields.H" +#include "cellCellStencil.H" +#include "dynamicOversetFvMesh.H" // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // @@ -34,9 +36,7 @@ Foam::oversetFvPatchField<Type>::oversetFvPatchField const DimensionedField<Type, volMesh>& iF ) : - LduInterfaceField<Type>(refCast<const oversetFvPatch>(p)), - zeroGradientFvPatchField<Type>(p, iF), - oversetPatch_(refCast<const oversetFvPatch>(p)) + semiImplicitOversetFvPatchField<Type>(p, iF) {} @@ -49,21 +49,8 @@ Foam::oversetFvPatchField<Type>::oversetFvPatchField const fvPatchFieldMapper& mapper ) : - LduInterfaceField<Type>(refCast<const oversetFvPatch>(p)), - zeroGradientFvPatchField<Type>(ptf, p, iF, mapper), - oversetPatch_(refCast<const oversetFvPatch>(p)) -{ - if (!isA<oversetFvPatch>(this->patch())) - { - FatalErrorInFunction - << " patch type '" << p.type() - << "' not constraint type '" << typeName << "'" - << "\n for patch " << p.name() - << " of field " << this->internalField().name() - << " in file " << this->internalField().objectPath() - << exit(FatalIOError); - } -} + semiImplicitOversetFvPatchField<Type>(ptf, p, iF, mapper) +{} template<class Type> @@ -74,26 +61,8 @@ Foam::oversetFvPatchField<Type>::oversetFvPatchField const dictionary& dict ) : - LduInterfaceField<Type>(refCast<const oversetFvPatch>(p)), - zeroGradientFvPatchField<Type>(p, iF, dict), - oversetPatch_(refCast<const oversetFvPatch>(p)) -{ - if (!isA<oversetFvPatch>(p)) - { - FatalIOErrorInFunction(dict) - << " patch type '" << p.type() - << "' not constraint type '" << typeName << "'" - << "\n for patch " << p.name() - << " of field " << this->internalField().name() - << " in file " << this->internalField().objectPath() - << exit(FatalIOError); - } - - if (!dict.found("value") && this->coupled()) - { - this->evaluate(Pstream::commsTypes::blocking); - } -} + semiImplicitOversetFvPatchField<Type>(p, iF, dict) +{} template<class Type> @@ -102,9 +71,7 @@ Foam::oversetFvPatchField<Type>::oversetFvPatchField const oversetFvPatchField<Type>& ptf ) : - LduInterfaceField<Type>(ptf.oversetPatch_), - zeroGradientFvPatchField<Type>(ptf), - oversetPatch_(ptf.oversetPatch_) + semiImplicitOversetFvPatchField<Type>(ptf) {} @@ -115,22 +82,19 @@ Foam::oversetFvPatchField<Type>::oversetFvPatchField const DimensionedField<Type, volMesh>& iF ) : - LduInterfaceField<Type>(ptf.oversetPatch_), - zeroGradientFvPatchField<Type>(ptf, iF), - oversetPatch_(ptf.oversetPatch_) + semiImplicitOversetFvPatchField<Type>(ptf, iF) {} // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // - template<class Type> void Foam::oversetFvPatchField<Type>::initEvaluate ( const Pstream::commsTypes commsType ) { - if (oversetPatch_.master()) + if (this->oversetPatch_.master()) { // Trigger interpolation const fvMesh& mesh = this->internalField().mesh(); @@ -139,24 +103,14 @@ void Foam::oversetFvPatchField<Type>::initEvaluate if (&mesh.lduAddr() != &mesh.fvMesh::lduAddr()) { - // Running extended addressing. Interpolate always. + // Running extended addressing. Flux correction already done + // in the linear solver (through the initUpdateInterfaceMatrix + // method below) if (debug) { - Info<< "Interpolating solved-for field " << fldName << endl; + Info<< "Skipping overset interpolation for solved-for field " + << fldName << endl; } - - // Interpolate without bc update (since would trigger infinite - // recursion back to oversetFvPatchField<Type>::evaluate) - // The only problem is bcs that use the new cell values - // (e.g. zeroGradient, processor). These need to appear -after- - // the 'overset' bc. - mesh.interpolate - ( - const_cast<Field<Type>&> - ( - this->primitiveField() - ) - ); } else if ( @@ -206,31 +160,6 @@ void Foam::oversetFvPatchField<Type>::initEvaluate } -template<class Type> -void Foam::oversetFvPatchField<Type>::evaluate(const Pstream::commsTypes) -{ - if (!this->updated()) - { - this->updateCoeffs(); - } - - zeroGradientFvPatchField<Type>::evaluate(); -} - - -template<class Type> -void Foam::oversetFvPatchField<Type>::initInterfaceMatrixUpdate -( - scalarField& result, - const bool add, - const scalarField& psiInternal, - const scalarField& coeffs, - const direction cmpt, - const Pstream::commsTypes commsType -) const -{} - - template<class Type> void Foam::oversetFvPatchField<Type>::updateInterfaceMatrix ( @@ -243,7 +172,10 @@ void Foam::oversetFvPatchField<Type>::updateInterfaceMatrix ) const { // Add remote values - if (oversetPatch_.master()) + + const oversetFvPatch& ovp = this->oversetPatch_; + + if (ovp.master()) { const fvMesh& mesh = this->patch().boundaryMesh().mesh(); @@ -251,11 +183,10 @@ void Foam::oversetFvPatchField<Type>::updateInterfaceMatrix // TBD. This should be cleaner. if (&mesh.lduAddr() == &mesh.fvMesh::lduAddr()) { - //Pout<< "** not running extended addressing..." << endl; return; } - const labelListList& stencil = oversetPatch_.stencil(); + const labelListList& stencil = ovp.stencil(); if (stencil.size() != psiInternal.size()) { @@ -263,12 +194,11 @@ void Foam::oversetFvPatchField<Type>::updateInterfaceMatrix << " stencil:" << stencil.size() << exit(FatalError); } - const mapDistribute& map = oversetPatch_.cellInterpolationMap(); - const List<scalarList>& wghts = - oversetPatch_.cellInterpolationWeights(); - const labelList& cellIDs = oversetPatch_.interpolationCells(); - const scalarList& factor = oversetPatch_.cellInterpolationWeight(); - const scalarField& normalisation = oversetPatch_.normalisation(); + 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 @@ -306,41 +236,4 @@ void Foam::oversetFvPatchField<Type>::updateInterfaceMatrix } -template<class Type> -void Foam::oversetFvPatchField<Type>::initInterfaceMatrixUpdate -( - Field<Type>&, - const bool add, - const Field<Type>&, - const scalarField&, - const Pstream::commsTypes commsType -) const -{ - NotImplemented; -} - - -template<class Type> -void Foam::oversetFvPatchField<Type>::updateInterfaceMatrix -( - Field<Type>& result, - const bool add, - const Field<Type>& psiInternal, - const scalarField&, - const Pstream::commsTypes -) const -{ - NotImplemented; -} - - -template<class Type> -void Foam::oversetFvPatchField<Type>::write(Ostream& os) const -{ - zeroGradientFvPatchField<Type>::write(os); - // Make sure to write the value for ease of postprocessing. - this->writeEntry("value", os); -} - - // ************************************************************************* // diff --git a/src/overset/oversetPolyPatch/oversetFvPatchField.H b/src/overset/oversetPolyPatch/oversetFvPatchField.H index b7c923fcd5f7875f74a0e091eb1a30fbd116c4e8..9cae63dc43caff5a9882fcb9114da016b45dc458 100644 --- a/src/overset/oversetPolyPatch/oversetFvPatchField.H +++ b/src/overset/oversetPolyPatch/oversetFvPatchField.H @@ -28,8 +28,9 @@ Group grpCoupledBoundaryConditions Description - -SeeAlso + 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. SourceFiles oversetFvPatchField.C @@ -39,9 +40,7 @@ SourceFiles #ifndef oversetFvPatchField_H #define oversetFvPatchField_H -#include "oversetFvPatch.H" -#include "zeroGradientFvPatchField.H" -#include "LduInterfaceField.H" +#include "semiImplicitOversetFvPatchField.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -55,18 +54,8 @@ namespace Foam template<class Type> class oversetFvPatchField : - public LduInterfaceField<Type>, - public zeroGradientFvPatchField<Type> + public semiImplicitOversetFvPatchField<Type> { - // Private data - - //- Local reference cast into the overset patch - const oversetFvPatch& oversetPatch_; - - //- Master patch ID - mutable label masterPatchID_; - - public: //- Runtime type information @@ -133,34 +122,11 @@ public: // Member functions - // Access - - //- Return local reference cast into the cyclic AMI patch - const oversetFvPatch& oversetPatch() const - { - return oversetPatch_; - } - - // Evaluation functions //- 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&, - const bool add, - const scalarField&, - const scalarField&, - const direction, - const Pstream::commsTypes commsType - ) const; - //- Update result field based on interface functionality virtual void updateInterfaceMatrix ( @@ -171,32 +137,6 @@ public: const direction cmpt, const Pstream::commsTypes commsType ) const; - - //- Initialise neighbour matrix update - virtual void initInterfaceMatrixUpdate - ( - Field<Type>&, - const bool add, - const Field<Type>&, - const scalarField&, - const Pstream::commsTypes commsType - ) const; - - //- Update result field based on interface functionality - virtual void updateInterfaceMatrix - ( - Field<Type>&, - const bool add, - const Field<Type>&, - const scalarField&, - const Pstream::commsTypes commsType - ) const; - - - // I-O - - //- Write - virtual void write(Ostream& os) const; }; diff --git a/src/overset/oversetPolyPatch/oversetGAMGInterfaceField.H b/src/overset/oversetPolyPatch/oversetGAMGInterfaceField.H index 3cd44fa3dba456cfa1505ef2f15d73b924a19020..e706be9c14ebba645885a1a125abeef519f15a18 100644 --- a/src/overset/oversetPolyPatch/oversetGAMGInterfaceField.H +++ b/src/overset/oversetPolyPatch/oversetGAMGInterfaceField.H @@ -52,12 +52,16 @@ class oversetGAMGInterfaceField : public GAMGInterfaceField { - // Private data +protected: + + // Protected data //- Local reference cast into the interface const oversetGAMGInterface& oversetInterface_; +private: + // Private Member Functions //- Disallow default bitwise copy construct diff --git a/src/overset/oversetPolyPatch/semiImplicitOversetFvPatchField.C b/src/overset/oversetPolyPatch/semiImplicitOversetFvPatchField.C new file mode 100644 index 0000000000000000000000000000000000000000..cd361f3ad8571c7abaa4a273a50ef610d214b670 --- /dev/null +++ b/src/overset/oversetPolyPatch/semiImplicitOversetFvPatchField.C @@ -0,0 +1,272 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2017 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "volFields.H" + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +template<class Type> +Foam::semiImplicitOversetFvPatchField<Type>::semiImplicitOversetFvPatchField +( + const fvPatch& p, + const DimensionedField<Type, volMesh>& iF +) +: + LduInterfaceField<Type>(refCast<const oversetFvPatch>(p)), + zeroGradientFvPatchField<Type>(p, iF), + oversetPatch_(refCast<const oversetFvPatch>(p)) +{} + + +template<class Type> +Foam::semiImplicitOversetFvPatchField<Type>::semiImplicitOversetFvPatchField +( + const semiImplicitOversetFvPatchField<Type>& ptf, + const fvPatch& p, + const DimensionedField<Type, volMesh>& iF, + const fvPatchFieldMapper& mapper +) +: + LduInterfaceField<Type>(refCast<const oversetFvPatch>(p)), + zeroGradientFvPatchField<Type>(ptf, p, iF, mapper), + oversetPatch_(refCast<const oversetFvPatch>(p)) +{ + if (!isA<oversetFvPatch>(this->patch())) + { + FatalErrorInFunction + << " patch type '" << p.type() + << "' not constraint type '" << typeName << "'" + << "\n for patch " << p.name() + << " of field " << this->internalField().name() + << " in file " << this->internalField().objectPath() + << exit(FatalIOError); + } +} + + +template<class Type> +Foam::semiImplicitOversetFvPatchField<Type>::semiImplicitOversetFvPatchField +( + const fvPatch& p, + const DimensionedField<Type, volMesh>& iF, + const dictionary& dict +) +: + LduInterfaceField<Type>(refCast<const oversetFvPatch>(p)), + zeroGradientFvPatchField<Type>(p, iF, dict), + oversetPatch_(refCast<const oversetFvPatch>(p)) +{ + if (!isA<oversetFvPatch>(p)) + { + FatalIOErrorInFunction(dict) + << " patch type '" << p.type() + << "' not constraint type '" << typeName << "'" + << "\n for patch " << p.name() + << " of field " << this->internalField().name() + << " in file " << this->internalField().objectPath() + << exit(FatalIOError); + } + + if (!dict.found("value") && this->coupled()) + { + this->evaluate(Pstream::commsTypes::blocking); + } +} + + +template<class Type> +Foam::semiImplicitOversetFvPatchField<Type>::semiImplicitOversetFvPatchField +( + const semiImplicitOversetFvPatchField<Type>& ptf +) +: + LduInterfaceField<Type>(ptf.oversetPatch_), + zeroGradientFvPatchField<Type>(ptf), + oversetPatch_(ptf.oversetPatch_) +{} + + +template<class Type> +Foam::semiImplicitOversetFvPatchField<Type>::semiImplicitOversetFvPatchField +( + const semiImplicitOversetFvPatchField<Type>& ptf, + const DimensionedField<Type, volMesh>& iF +) +: + LduInterfaceField<Type>(ptf.oversetPatch_), + zeroGradientFvPatchField<Type>(ptf, iF), + oversetPatch_(ptf.oversetPatch_) +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +template<class Type> +void Foam::semiImplicitOversetFvPatchField<Type>::evaluate +( + const Pstream::commsTypes +) +{ + if (debug) + { + Pout<< FUNCTION_NAME << " field " << this->internalField().name() + << " patch " << this->patch().name() << endl; + } + + + if (!this->updated()) + { + this->updateCoeffs(); + } + + zeroGradientFvPatchField<Type>::evaluate(); +} + + +template<class Type> +void Foam::semiImplicitOversetFvPatchField<Type>::initEvaluate +( + const Pstream::commsTypes commsType +) +{ + if (debug) + { + Pout<< FUNCTION_NAME << " field " << this->internalField().name() + << " patch " << this->patch().name() << endl; + } + + if (this->oversetPatch().master()) + { + // Trigger interpolation + const fvMesh& mesh = this->internalField().mesh(); + //const dictionary& fvSchemes = mesh.schemesDict(); + const word& fldName = this->internalField().name(); + + if (&mesh.lduAddr() != &mesh.fvMesh::lduAddr()) + { + // Running extended addressing so called from within fvMatrix::solve + FatalErrorInFunction + << "Running extended addressing is not allowed when solving " + << fldName + << " Please choose a dynamicFvMesh without matrix adaptation" + << exit(FatalError); + } + else + { + if (debug) + { + Info<< "Interpolating field " << fldName << endl; + } + + // Interpolate without bc update (since would trigger infinite + // recursion back to + // semiImplicitOversetFvPatchField<Type>::evaluate) + // The only problem is bcs that use the new cell values + // (e.g. zeroGradient, processor). These need to appear -after- + // the 'overset' bc. + mesh.interpolate + ( + const_cast<Field<Type>&> + ( + this->primitiveField() + ) + ); + } + } +} + + +template<class Type> +void Foam::semiImplicitOversetFvPatchField<Type>::updateInterfaceMatrix +( + scalarField& result, + const bool add, + const scalarField& psiInternal, + const scalarField& coeffs, + const direction cmpt, + const Pstream::commsTypes +) const +{ + if (debug) + { + Pout<< FUNCTION_NAME << " field " << this->internalField().name() + << " patch " << this->patch().name() << endl; + } + + const oversetFvPatch& ovp = this->oversetPatch(); + + // Set all interpolated cells + if (ovp.master()) + { + const labelListList& stencil = ovp.stencil(); + + if (stencil.size() != psiInternal.size()) + { + FatalErrorInFunction << "psiInternal:" << psiInternal.size() + << " stencil:" << stencil.size() << exit(FatalError); + } + + const mapDistribute& map = ovp.cellInterpolationMap(); + const List<scalarList>& wghts = ovp.cellInterpolationWeights(); + const labelList& cellIDs = ovp.interpolationCells(); + //const scalarList& factor = ovp.cellInterpolationWeight(); + + // Since we're inside initEvaluate/evaluate there might be processor + // comms underway. Change the tag we use. + scalarField work(psiInternal); + map.mapDistributeBase::distribute(work, UPstream::msgType()+1); + + forAll(cellIDs, i) + { + label celli = cellIDs[i]; + + const scalarList& w = wghts[celli]; + const labelList& nbrs = stencil[celli]; + + //scalar f = factor[celli]; + + scalar s(0.0); + forAll(nbrs, nbrI) + { + s += w[nbrI]*work[nbrs[nbrI]]; + } + + //Pout<< "cell:" << celli << " interpolated value:" << s << endl; + result[celli] = s; //(1.0-f)*result[celli] + f*s; + } + } +} + + +template<class Type> +void Foam::semiImplicitOversetFvPatchField<Type>::write(Ostream& os) const +{ + zeroGradientFvPatchField<Type>::write(os); + // Make sure to write the value for ease of postprocessing. + this->writeEntry("value", os); +} + + +// ************************************************************************* // diff --git a/src/overset/oversetPolyPatch/semiImplicitOversetFvPatchField.H b/src/overset/oversetPolyPatch/semiImplicitOversetFvPatchField.H new file mode 100644 index 0000000000000000000000000000000000000000..f01a412ec1fc62c020dfe43318bfbd7fcd6d527b --- /dev/null +++ b/src/overset/oversetPolyPatch/semiImplicitOversetFvPatchField.H @@ -0,0 +1,207 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2017 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::semiImplicitOversetFvPatchField + +Group + grpCoupledBoundaryConditions + +Description + Boundary condition for use on overset patches. Implements update of + interpolated cells inside the linear solvers. + +SeeAlso + +SourceFiles + semiImplicitOversetFvPatchField.C + +\*---------------------------------------------------------------------------*/ + +#ifndef semiImplicitOversetFvPatchField_H +#define semiImplicitOversetFvPatchField_H + +#include "oversetFvPatch.H" +#include "zeroGradientFvPatchField.H" +#include "LduInterfaceField.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class semiImplicitOversetFvPatchField Declaration +\*---------------------------------------------------------------------------*/ + +template<class Type> +class semiImplicitOversetFvPatchField +: + public LduInterfaceField<Type>, + public zeroGradientFvPatchField<Type> +{ +protected: + + // Protected data + + //- Local reference cast into the overset patch + const oversetFvPatch& oversetPatch_; + + //- Master patch ID + mutable label masterPatchID_; + + +public: + + //- Runtime type information + TypeName("semiImplicitOverset"); + + + // Constructors + + //- Construct from patch and internal field + semiImplicitOversetFvPatchField + ( + const fvPatch&, + const DimensionedField<Type, volMesh>& + ); + + //- Construct from patch, internal field and dictionary + semiImplicitOversetFvPatchField + ( + const fvPatch&, + const DimensionedField<Type, volMesh>&, + const dictionary& + ); + + //- Construct by mapping given semiImplicitOversetFvPatchField onto a + // new patch + semiImplicitOversetFvPatchField + ( + const semiImplicitOversetFvPatchField<Type>&, + const fvPatch&, + const DimensionedField<Type, volMesh>&, + const fvPatchFieldMapper& + ); + + //- Construct as copy + semiImplicitOversetFvPatchField + ( + const semiImplicitOversetFvPatchField<Type>& + ); + + //- Construct and return a clone + virtual tmp<fvPatchField<Type> > clone() const + { + return tmp<fvPatchField<Type> > + ( + new semiImplicitOversetFvPatchField<Type>(*this) + ); + } + + //- Construct as copy setting internal field reference + semiImplicitOversetFvPatchField + ( + const semiImplicitOversetFvPatchField<Type>&, + const DimensionedField<Type, volMesh>& + ); + + //- Construct and return a clone setting internal field reference + virtual tmp<fvPatchField<Type> > clone + ( + const DimensionedField<Type, volMesh>& iF + ) const + { + return tmp<fvPatchField<Type> > + ( + new semiImplicitOversetFvPatchField<Type>(*this, iF) + ); + } + + + // Member functions + + // Access + + //- Return local reference cast into the cyclic AMI patch + const oversetFvPatch& oversetPatch() const + { + return oversetPatch_; + } + + + // Evaluation functions + + //- Evaluate the patch field + virtual void evaluate(const Pstream::commsTypes commsType); + + //- Initialise the evaluation of the patch field + virtual void initEvaluate(const Pstream::commsTypes commsType); + + //- Update result field based on interface functionality + virtual void updateInterfaceMatrix + ( + scalarField& result, + const bool add, + const scalarField& psiInternal, + const scalarField& coeffs, + const direction cmpt, + const Pstream::commsTypes commsType + ) const; + + //- Update result field based on interface functionality + virtual void updateInterfaceMatrix + ( + Field<Type>&, + const bool add, + const Field<Type>&, + const scalarField&, + const Pstream::commsTypes commsType + ) const + { + NotImplemented; + } + + + // I-O + + //- Write + virtual void write(Ostream& os) const; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#ifdef NoRepository +# include "semiImplicitOversetFvPatchField.C" +#endif + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/overset/oversetPolyPatch/semiImplicitOversetFvPatchFields.C b/src/overset/oversetPolyPatch/semiImplicitOversetFvPatchFields.C new file mode 100644 index 0000000000000000000000000000000000000000..1471e28ca46542c307ab22d146e6d41d8d69a798 --- /dev/null +++ b/src/overset/oversetPolyPatch/semiImplicitOversetFvPatchFields.C @@ -0,0 +1,43 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "semiImplicitOversetFvPatchFields.H" +#include "addToRunTimeSelectionTable.H" +#include "volFields.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +makePatchFields(semiImplicitOverset); + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// ************************************************************************* // diff --git a/src/overset/oversetPolyPatch/semiImplicitOversetFvPatchFields.H b/src/overset/oversetPolyPatch/semiImplicitOversetFvPatchFields.H new file mode 100644 index 0000000000000000000000000000000000000000..e943538791499b24b75237ad34ccebef975c66fb --- /dev/null +++ b/src/overset/oversetPolyPatch/semiImplicitOversetFvPatchFields.H @@ -0,0 +1,49 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2017 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#ifndef semiImplicitOversetFvPatchFields_H +#define semiImplicitOversetFvPatchFields_H + +#include "semiImplicitOversetFvPatchField.H" +#include "fieldTypes.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +makePatchTypeFieldTypedefs(semiImplicitOverset); + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/overset/oversetPolyPatch/semiImplicitOversetGAMGInterfaceField.C b/src/overset/oversetPolyPatch/semiImplicitOversetGAMGInterfaceField.C new file mode 100644 index 0000000000000000000000000000000000000000..cf624a85ac6eff547e92002c56b4ae510e63525a --- /dev/null +++ b/src/overset/oversetPolyPatch/semiImplicitOversetGAMGInterfaceField.C @@ -0,0 +1,122 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2017 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "semiImplicitOversetGAMGInterfaceField.H" +#include "addToRunTimeSelectionTable.H" +#include "lduMatrix.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ + defineTypeNameAndDebug(semiImplicitOversetGAMGInterfaceField, 0); + addToRunTimeSelectionTable + ( + GAMGInterfaceField, + semiImplicitOversetGAMGInterfaceField, + lduInterfaceField + ); +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::semiImplicitOversetGAMGInterfaceField:: +semiImplicitOversetGAMGInterfaceField +( + const GAMGInterface& GAMGCp, + const lduInterfaceField& fineInterface +) +: + oversetGAMGInterfaceField(GAMGCp, fineInterface) +{} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::semiImplicitOversetGAMGInterfaceField:: +~semiImplicitOversetGAMGInterfaceField() +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void Foam::semiImplicitOversetGAMGInterfaceField::updateInterfaceMatrix +( + scalarField& result, + const bool add, + const scalarField& psiInternal, + const scalarField& coeffs, + const direction cmpt, + const Pstream::commsTypes commsType +) const +{ + // Add remote values + if (oversetInterface_.master()) + { + const labelListList& stencil = oversetInterface_.stencil(); + + if (stencil.size() != psiInternal.size()) + { + FatalErrorInFunction << "psiInternal:" << psiInternal.size() + << " stencil:" << stencil.size() << exit(FatalError); + } + + const mapDistribute& map = oversetInterface_.cellInterpolationMap(); + const List<scalarList>& wghts = + oversetInterface_.cellInterpolationWeights(); + const labelList& cellIDs = oversetInterface_.interpolationCells(); + const scalarList& factor = oversetInterface_.cellInterpolationWeight(); + const scalarField& normalisation = oversetInterface_.normalisation(); + + scalarField work(psiInternal); + map.mapDistributeBase::distribute(work, UPstream::msgType()+1); + + forAll(cellIDs, i) + { + label celli = cellIDs[i]; + + const scalarList& w = wghts[celli]; + const labelList& nbrs = stencil[celli]; + const scalar f = factor[celli]; + + scalar s(0.0); + forAll(nbrs, nbrI) + { + label slotI = nbrs[nbrI]; + s += w[nbrI]*work[slotI]; + } + if (add) + { + s = -1.0*s; + } + + result[celli] += normalisation[celli]*f*s; + } + } +} + + +// ************************************************************************* // diff --git a/src/overset/oversetPolyPatch/semiImplicitOversetGAMGInterfaceField.H b/src/overset/oversetPolyPatch/semiImplicitOversetGAMGInterfaceField.H new file mode 100644 index 0000000000000000000000000000000000000000..c80bb384575b688deb970a5665cba0a03c521cd4 --- /dev/null +++ b/src/overset/oversetPolyPatch/semiImplicitOversetGAMGInterfaceField.H @@ -0,0 +1,108 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2017 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::semiImplicitOversetGAMGInterfaceField + +Description + GAMG agglomerated processor interface field. + +SourceFiles + processorGAMGInterfaceField.C + +\*---------------------------------------------------------------------------*/ + +#ifndef semiImplicitOversetGAMGInterfaceField_H +#define semiImplicitOversetGAMGInterfaceField_H + +#include "oversetGAMGInterfaceField.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class semiImplicitOversetGAMGInterfaceField Declaration +\*---------------------------------------------------------------------------*/ + +class semiImplicitOversetGAMGInterfaceField +: + public oversetGAMGInterfaceField +{ + // Private Member Functions + + //- Disallow default bitwise copy construct + semiImplicitOversetGAMGInterfaceField + ( + const semiImplicitOversetGAMGInterfaceField& + ); + + //- Disallow default bitwise assignment + void operator=(const semiImplicitOversetGAMGInterfaceField&); + + +public: + + //- Runtime type information + TypeName("semiImplicitOverset"); + + + // Constructors + + //- Construct from GAMG interface and fine level interface field + semiImplicitOversetGAMGInterfaceField + ( + const GAMGInterface& GAMGCp, + const lduInterfaceField& fineInterface + ); + + + //- Destructor + virtual ~semiImplicitOversetGAMGInterfaceField(); + + + // Member Functions + + //- Update result field based on interface functionality + virtual void updateInterfaceMatrix + ( + scalarField& result, + const bool add, + const scalarField& psiInternal, + const scalarField& coeffs, + const direction cmpt, + const Pstream::commsTypes commsType + ) const; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/tutorials/incompressible/overPimpleDyMFoam/simpleRotor/system/fvSchemes b/tutorials/incompressible/overPimpleDyMFoam/simpleRotor/system/fvSchemes index d31d118e8aa254accf6dfed3d899f1794d7e7c0b..2d4f3b5ee274849ee2f6277b024af248d687f9f9 100644 --- a/tutorials/incompressible/overPimpleDyMFoam/simpleRotor/system/fvSchemes +++ b/tutorials/incompressible/overPimpleDyMFoam/simpleRotor/system/fvSchemes @@ -56,7 +56,10 @@ snGradSchemes oversetInterpolation { - method inverseDistance; + method inverseDistance; + + searchBox (0 0 0)(0.01 0.01 0.01); + searchBoxDivisions (100 100 1); } fluxRequired diff --git a/tutorials/incompressible/overSimpleFoam/aeroFoil/background_overset/system/decomposeParDict b/tutorials/incompressible/overSimpleFoam/aeroFoil/background_overset/system/decomposeParDict index f1b18226f652df92338ddc7a533bc2ef1b91a1ef..602c82d2c25a5c2589f61729d55fea62c8bcdce8 100644 --- a/tutorials/incompressible/overSimpleFoam/aeroFoil/background_overset/system/decomposeParDict +++ b/tutorials/incompressible/overSimpleFoam/aeroFoil/background_overset/system/decomposeParDict @@ -16,11 +16,11 @@ FoamFile numberOfSubdomains 8; -method hierarchical; +method scotch; //hierarchical; coeffs { - n (8 1 1); + n (4 2 1); //delta 0.001; // default=0.001 //order xyz; // default=xzy } diff --git a/tutorials/incompressible/overSimpleFoam/aeroFoil/background_overset/system/fvSolution b/tutorials/incompressible/overSimpleFoam/aeroFoil/background_overset/system/fvSolution index 71cf71b4055b1515b1cc3ee9dc493bac665f7088..84de10a190be830b9f3dd55543d1bb7318032dba 100644 --- a/tutorials/incompressible/overSimpleFoam/aeroFoil/background_overset/system/fvSolution +++ b/tutorials/incompressible/overSimpleFoam/aeroFoil/background_overset/system/fvSolution @@ -60,6 +60,7 @@ solvers SIMPLE { + momentumPredictor true; nOuterCorrectors 1; nCorrectors 2; nNonOrthogonalCorrectors 0; diff --git a/tutorials/multiphase/overInterDyMFoam/floatingBody/background/system/fvSolution b/tutorials/multiphase/overInterDyMFoam/floatingBody/background/system/fvSolution index 04bfe4172aac70c8c36cf696d63b290cfb3af21b..f1aaf2b011a9244978117b7e2e8c5e48963b66f1 100644 --- a/tutorials/multiphase/overInterDyMFoam/floatingBody/background/system/fvSolution +++ b/tutorials/multiphase/overInterDyMFoam/floatingBody/background/system/fvSolution @@ -29,8 +29,8 @@ solvers "alpha.water.*" { - nAlphaCorr 2; - nAlphaSubCycles 1; + nAlphaCorr 3; + nAlphaSubCycles 2; cAlpha 1; icAlpha 0; @@ -82,8 +82,12 @@ PIMPLE nCorrectors 2; nNonOrthogonalCorrectors 0; - ddtCorr yes; - correctPhi no; + ddtCorr yes; + correctPhi no; + massFluxInterpolation no; + + moveMeshOuterCorrectors no; + turbOnFinalIterOnly no; oversetAdjustPhi no;