Commit a13e00b5 authored by Andrew Heather's avatar Andrew Heather Committed by Andrew Heather
Browse files

ENH: AMI - multiple updates

- start of work to create a 1-to-1 face mapping across AMI patches
- faces are inserted according to the AMI addressing based on Horacio's method
- removed 'updated' flag and reworked some demand driven updates
- updated to handle 'walking' through baffles
- use bitSet instead of boolList
- moved update of meshPhi to movePoints() functions at fvPatch level
- moved scaling of areas to movePoints() functions at fvPatch level
- rehomed topology change code to own file
- added warning re: geometry construction

ACMI
- split srcMask into srcMask and srcAreaMask
  - former in range 0-1, and latter has bounding or tol to (1-tol) to avoid
    sigFpe's
parent b61dd6fd
......@@ -45,6 +45,7 @@ void Foam::polyMesh::updateMesh(const mapPolyMesh& mpm)
<< "Updating addressing and (optional) pointMesh/pointFields" << endl;
// Update boundaryMesh (note that patches themselves already ok)
// boundary_.updateMesh(mpm);
boundary_.updateMesh();
// Update zones
......
......@@ -63,6 +63,7 @@ void Foam::polyPatch::movePoints(PstreamBuffers&, const pointField& p)
primitivePatch::movePoints(p);
}
void Foam::polyPatch::updateMesh(PstreamBuffers&)
{
primitivePatch::clearGeom();
......
......@@ -55,6 +55,7 @@ namespace Foam
// Forward declarations
class polyBoundaryMesh;
class polyPatch;
class polyTopoChange;
class PstreamBuffers;
Ostream& operator<<(Ostream&, const polyPatch&);
......@@ -419,6 +420,19 @@ public:
labelList& rotation
) const;
//- For dynamic mesh cases - return true if this patch will change the
//- topology
virtual bool changeTopology() const
{
return false;
}
//- Collect topology changes in a polyTopoChange object
virtual bool setTopology(polyTopoChange&)
{
return false;
}
// Member operators
......
......@@ -10,4 +10,9 @@ dynamicMotionSolverListFvMesh/dynamicMotionSolverListFvMesh.C
simplifiedDynamicFvMesh/simplifiedDynamicFvMeshes.C
simplifiedDynamicFvMesh/simplifiedDynamicFvMesh.C
dynamicMotionSolverFvMeshAMI/dynamicMotionSolverFvMeshAMI.C
LIB = $(FOAM_LIBBIN)/libdynamicFvMesh
......@@ -92,6 +92,9 @@ const Foam::motionSolver& Foam::dynamicMotionSolverFvMesh::motion() const
bool Foam::dynamicMotionSolverFvMesh::update()
{
// Scan through AMI patches and update
fvMesh::movePoints(motionPtr_->newPoints());
volVectorField* Uptr = getObjectPtr<volVectorField>("U");
......
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
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 "dynamicMotionSolverFvMeshAMI.H"
#include "addToRunTimeSelectionTable.H"
#include "motionSolver.H"
#include "volFields.H"
#include "surfaceFields.H"
#include "cyclicAMIPolyPatch.H"
#include "polyTopoChange.H"
#include "MeshObject.H"
#include "lduMesh.H"
#include "processorFvPatch.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(dynamicMotionSolverFvMeshAMI, 0);
addToRunTimeSelectionTable
(
dynamicFvMesh,
dynamicMotionSolverFvMeshAMI,
IOobject
);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::dynamicMotionSolverFvMeshAMI::dynamicMotionSolverFvMeshAMI
(
const IOobject& io
)
:
dynamicFvMesh(io),
motionPtr_(motionSolver::New(*this))
{}
Foam::dynamicMotionSolverFvMeshAMI::dynamicMotionSolverFvMeshAMI
(
const IOobject& io,
pointField&& points,
faceList&& faces,
labelList&& allOwner,
labelList&& allNeighbour,
const bool syncPar
)
:
dynamicFvMesh
(
io,
std::move(points),
std::move(faces),
std::move(allOwner),
std::move(allNeighbour),
syncPar
),
motionPtr_(motionSolver::New(*this))
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
const Foam::motionSolver& Foam::dynamicMotionSolverFvMeshAMI::motion() const
{
return *motionPtr_;
}
bool Foam::dynamicMotionSolverFvMeshAMI::update()
{
// Mesh not moved/changed yet
moving(false);
topoChanging(false);
if (debug)
{
for (const fvPatch& fvp : boundary())
{
if (!isA<processorFvPatch>(fvp))
{
Info<< "1 --- patch:" << fvp.patch().name()
<< " area:" << gSum(fvp.magSf()) << endl;
}
}
}
pointField newPoints(motionPtr_->curPoints());
polyBoundaryMesh& pbm = const_cast<polyBoundaryMesh&>(boundaryMesh());
// Scan all patches and see if we want to apply a mesh topology update
bool changeRequired = false;
for (polyPatch& pp : pbm)
{
DebugInfo
<< "pre-topology change: patch " << pp.name()
<< " size:" << returnReduce(pp.size(), sumOp<label>())
<< " mag(faceAreas):" << gSum(mag(pp.faceAreas())) << endl;
//changeRequired = pp.changeTopology(newPoints) || changeRequired;
changeRequired = pp.changeTopology() || changeRequired;
}
reduce(changeRequired, orOp<bool>());
if (changeRequired)
{
polyTopoChange polyTopo(*this);
// Set new point positions in polyTopo object
polyTopo.movePoints(newPoints);
// Accumulate the patch-based mesh changes on the current mesh
// Note:
// - updates the AMIs using the new points
// - creates a topo change object that removes old added faces and
// adds the new faces
for (polyPatch& pp : pbm)
{
pp.setTopology(polyTopo);
}
// Update geometry
// Note
// - changeMesh leads to polyMesh::resetPrimitives which will also
// trigger polyBoundaryMesh::updateMesh (init and update) and
// ::calcGeometry (with topoChanging = false)
// - BUT: mesh still corresponds to original (non-extended mesh) so
// we want to bypass these calls...
// - after changes topoChanging = true
autoPtr<mapPolyMesh> map =
polyTopo.changeMesh
(
*this,
true // We will be calling movePoints after this update
);
// Apply topology change - update fv geometry and map fields
// - polyMesh::updateMesh
// - fires initUpdateMesh and updateMesh in AMI BCs - called before
// mapFields
// - AMI addressing must be up-to-date - used by, e.g. FaceCellWave
// - will trigger (again) polyBoundaryMesh::updateMesh (init and update)
updateMesh(map());
// Move points and update derived properties
// Note:
// - resets face areas based on raw point locations!
// - polyBoundaryMesh::updateMesh (init and update)
// Note:
// - processorPolyPatches will trigger calculation of faceCentres
// (and therefore cell volumes), so need to update faceAreas in
// initMovePoints since proc patches will be evaluated later than
// AMI patches
if (map().hasMotionPoints())
{
movePoints(map().preMotionPoints());
}
}
else
{
fvMesh::movePoints(newPoints);
}
volVectorField* Uptr = getObjectPtr<volVectorField>("U");
if (Uptr)
{
Uptr->correctBoundaryConditions();
}
if (debug)
{
for (const fvPatch& fvp : boundary())
{
if (!isA<processorFvPatch>(fvp))
{
Info<< "2 --- patch:" << fvp.patch().name()
<< " area:" << gSum(fvp.magSf()) << endl;
}
}
}
return true;
}
// ************************************************************************* //
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
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::dynamicMotionSolverFvMeshAMI
Description
The dynamicMotionSolverFvMeshAMI
SourceFiles
dynamicMotionSolverFvMeshAMI.C
\*---------------------------------------------------------------------------*/
#ifndef dynamicMotionSolverFvMeshAMI_H
#define dynamicMotionSolverFvMeshAMI_H
#include "dynamicFvMesh.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
class motionSolver;
/*---------------------------------------------------------------------------*\
Class dynamicMotionSolverFvMeshAMI Declaration
\*---------------------------------------------------------------------------*/
class dynamicMotionSolverFvMeshAMI
:
public dynamicFvMesh
{
// Private data
autoPtr<motionSolver> motionPtr_;
// Private Member Functions
//- No copy construct
dynamicMotionSolverFvMeshAMI
(
const dynamicMotionSolverFvMeshAMI&
) = delete;
//- No copy assignment
void operator=(const dynamicMotionSolverFvMeshAMI&) = delete;
public:
//- Runtime type information
TypeName("dynamicMotionSolverFvMeshAMI");
// Constructors
//- Construct from IOobject
dynamicMotionSolverFvMeshAMI(const IOobject& io);
//- Construct from components without boundary.
// Boundary is added using addFvPatches() member function
dynamicMotionSolverFvMeshAMI
(
const IOobject& io,
pointField&& points,
faceList&& faces,
labelList&& allOwner,
labelList&& allNeighbour,
const bool syncPar = true
);
//- Destructor
virtual ~dynamicMotionSolverFvMeshAMI() = default;
// Member Functions
//- Return the motionSolver
const motionSolver& motion() const;
//- Update the mesh for both mesh motion and topology change
virtual bool update();
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //
EXE_INC = \
-I$(LIB_SRC)/fileFormats/lnInclude \
-I$(LIB_SRC)/surfMesh/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/dynamicMesh/lnInclude
LIB_LIBS = \
-lOpenFOAM \
......
......@@ -173,7 +173,7 @@ public:
//- Return true if this patch field fixes a value
// Needed to check if a level has to be specified while solving
// Poissons equations
// Poisson equations
virtual bool fixesValue() const
{
const scalarField& mask =
......
......@@ -726,6 +726,8 @@ void Foam::fvMesh::mapFields(const mapPolyMesh& meshMap)
Foam::tmp<Foam::scalarField> Foam::fvMesh::movePoints(const pointField& p)
{
DebugInFunction << endl;
// Grab old time volumes if the time has been incremented
// This will update V0, V00
if (curTimeIndex_ < time().timeIndex())
......@@ -733,6 +735,14 @@ Foam::tmp<Foam::scalarField> Foam::fvMesh::movePoints(const pointField& p)
storeOldVol(V());
}
// Move the polyMesh and set the mesh motion fluxes to the swept-volumes
scalar rDeltaT = 1.0/time().deltaTValue();
tmp<scalarField> tsweptVols = polyMesh::movePoints(p);
scalarField& sweptVols = tsweptVols.ref();
if (!phiPtr_)
{
// Create mesh motion flux
......@@ -761,14 +771,6 @@ Foam::tmp<Foam::scalarField> Foam::fvMesh::movePoints(const pointField& p)
}
surfaceScalarField& phi = *phiPtr_;
// Move the polyMesh and set the mesh motion fluxes to the swept-volumes
scalar rDeltaT = 1.0/time().deltaTValue();
tmp<scalarField> tsweptVols = polyMesh::movePoints(p);
scalarField& sweptVols = tsweptVols.ref();
phi.primitiveFieldRef() =
scalarField::subField(sweptVols, nInternalFaces());
phi.primitiveFieldRef() *= rDeltaT;
......@@ -776,7 +778,6 @@ Foam::tmp<Foam::scalarField> Foam::fvMesh::movePoints(const pointField& p)
const fvPatchList& patches = boundary();
surfaceScalarField::Boundary& phibf = phi.boundaryFieldRef();
forAll(patches, patchi)
{
phibf[patchi] = patches[patchi].patchSlice(sweptVols);
......@@ -805,6 +806,8 @@ Foam::tmp<Foam::scalarField> Foam::fvMesh::movePoints(const pointField& p)
void Foam::fvMesh::updateMesh(const mapPolyMesh& mpm)
{
DebugInFunction << endl;
// Update polyMesh. This needs to keep volume existent!
polyMesh::updateMesh(mpm);
......
......@@ -91,6 +91,8 @@ class fvMesh
public fvSolution,
public data
{
protected:
// Private data
//- Boundary mesh
......
......@@ -6,6 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2013-2016 OpenFOAM Foundation
Copyright (C) 2019 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
......@@ -26,9 +27,10 @@ License
\*---------------------------------------------------------------------------*/
#include "cyclicACMIFvPatch.H"
#include "addToRunTimeSelectionTable.H"
#include "fvMesh.H"
#include "transform.H"
#include "surfaceFields.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
......@@ -41,45 +43,13 @@ namespace Foam
// * * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * //
void Foam::cyclicACMIFvPatch::updateAreas() const
void Foam::cyclicACMIFvPatch::resetPatchAreas(const fvPatch& fvp) const
{
if (cyclicACMIPolyPatch_.updated())
{
if (debug)
{
Pout<< "cyclicACMIFvPatch::updateAreas() : updating fv areas for "
<< name() << " and " << this->nonOverlapPatch().name()
<< endl;
}
const_cast<vectorField&>(fvp.Sf()) = fvp.patch().faceAreas();
const_cast<scalarField&>(fvp.magSf()) = mag(fvp.patch().faceAreas());
// owner couple
const_cast<vectorField&>(Sf()) = patch().faceAreas();
const_cast<scalarField&>(magSf()) = mag(patch().faceAreas());
// owner non-overlapping
const fvPatch& nonOverlapPatch = this->nonOverlapPatch();
const_cast<vectorField&>(nonOverlapPatch.Sf()) =
nonOverlapPatch.patch().faceAreas();
const_cast<scalarField&>(nonOverlapPatch.magSf()) =
mag(nonOverlapPatch.patch().faceAreas());
// neighbour couple
const cyclicACMIFvPatch& nbrACMI = neighbPatch();
const_cast<vectorField&>(nbrACMI.Sf()) =
nbrACMI.patch().faceAreas();
const_cast<scalarField&>(nbrACMI.magSf()) =
mag(nbrACMI.patch().faceAreas());
// neighbour non-overlapping
const fvPatch& nbrNonOverlapPatch = nbrACMI.nonOverlapPatch();
const_cast<vectorField&>(nbrNonOverlapPatch.Sf()) =
nbrNonOverlapPatch.patch().faceAreas();
const_cast<scalarField&>(nbrNonOverlapPatch.magSf()) =
mag(nbrNonOverlapPatch.patch().faceAreas());
// set the updated flag
cyclicACMIPolyPatch_.setUpdated(false);
}
DebugPout
<< fvp.patch().name() << " area:" << sum(fvp.magSf()) << endl;
}
......@@ -100,13 +70,13 @@ void Foam::cyclicACMIFvPatch::makeWeights(scalarField& w) const
)
);
scalar tol = cyclicACMIPolyPatch::tolerance();
const scalar tol = cyclicACMIPolyPatch::tolerance();
forAll(deltas, facei)
{
scalar di = deltas[facei];
scalar dni = nbrDeltas[facei];
scalar di = mag(deltas[facei]);
scalar dni = mag(nbrDeltas[facei]);
if (dni < tol)
{
......@@ -147,7 +117,6 @@ Foam::tmp<Foam::vectorField> Foam::cyclicACMIFvPatch::delta() const
vectorField nbrPatchD(interpolate(nbrPatch.coupledFvPatch::delta()));
tmp<vectorField> tpdv(new vectorField(patchD.size()));
vectorField& pdv = tpdv.ref();
......@@ -201,4 +170,94 @@ Foam::tmp<Foam::labelField> Foam::cyclicACMIFvPatch::internalFieldTransfer
}
void Foam::cyclicACMIFvPatch::movePoints()
{
if (!cyclicACMIPolyPatch_.owner())
{
return;
}
// Set the patch face areas to be consistent with the changes made at the
// polyPatch level
const fvPatch& nonOverlapPatch = this->nonOverlapPatch();
const cyclicACMIFvPatch& nbrACMI = neighbPatch();