mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: Added new solidBodyFvGeometryScheme
Geometry calculation scheme that performs geometry updates only in regions
where the mesh has changed, identified by comparing current and old points.
Example usage in fvSchemes:
geometry
{
type solidBody;
// Optional entries
// If set to false, update the entire mesh
partialUpdate yes;
// Cache the motion addressing (changed points, faces, cells etc)
cacheMotion yes;
}
This commit is contained in:
committed by
Andrew Heather
parent
f1dfaa90a7
commit
6a8ddbb296
@ -8,6 +8,7 @@ $(fvGeometryScheme)/highAspectRatio/highAspectRatioFvGeometryScheme.C
|
|||||||
$(fvGeometryScheme)/highAspectRatio/cellAspectRatio.C
|
$(fvGeometryScheme)/highAspectRatio/cellAspectRatio.C
|
||||||
$(fvGeometryScheme)/averageNeighbour/averageNeighbourFvGeometryScheme.C
|
$(fvGeometryScheme)/averageNeighbour/averageNeighbourFvGeometryScheme.C
|
||||||
$(fvGeometryScheme)/stabilised/stabilisedFvGeometryScheme.C
|
$(fvGeometryScheme)/stabilised/stabilisedFvGeometryScheme.C
|
||||||
|
$(fvGeometryScheme)/solidBody/solidBodyFvGeometryScheme.C
|
||||||
|
|
||||||
surfaceInterpolation = interpolation/surfaceInterpolation
|
surfaceInterpolation = interpolation/surfaceInterpolation
|
||||||
$(surfaceInterpolation)/surfaceInterpolation/surfaceInterpolation.C
|
$(surfaceInterpolation)/surfaceInterpolation/surfaceInterpolation.C
|
||||||
|
|||||||
@ -0,0 +1,341 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 2021-2022 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 "solidBodyFvGeometryScheme.H"
|
||||||
|
#include "addToRunTimeSelectionTable.H"
|
||||||
|
#include "surfaceFields.H"
|
||||||
|
#include "primitiveMeshTools.H"
|
||||||
|
#include "emptyPolyPatch.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
defineTypeNameAndDebug(solidBodyFvGeometryScheme, 0);
|
||||||
|
addToRunTimeSelectionTable
|
||||||
|
(
|
||||||
|
fvGeometryScheme,
|
||||||
|
solidBodyFvGeometryScheme,
|
||||||
|
dict
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::solidBodyFvGeometryScheme::setMeshMotionData()
|
||||||
|
{
|
||||||
|
if (!cacheInitialised_ || !cacheMotion_)
|
||||||
|
{
|
||||||
|
DebugInFunction << "Creating cache" << endl;
|
||||||
|
|
||||||
|
changedFaceIDs_.clear(); // used for face areas, meshPhi
|
||||||
|
changedPatchIDs_.clear(); // used for meshPhi
|
||||||
|
changedCellIDs_.clear(); // used for cell volumes
|
||||||
|
|
||||||
|
const pointField& oldPoints = mesh_.oldPoints();
|
||||||
|
const pointField& currPoints = mesh_.points();
|
||||||
|
|
||||||
|
if (oldPoints.size() != currPoints.size())
|
||||||
|
{
|
||||||
|
FatalErrorInFunction
|
||||||
|
<< "Old and current points sizes must be the same. "
|
||||||
|
<< "Old points:" << oldPoints.size()
|
||||||
|
<< " Current points:" << currPoints.size()
|
||||||
|
<< abort(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
bitSet changedPoints(oldPoints.size());
|
||||||
|
|
||||||
|
// Check for non-identical points
|
||||||
|
forAll(changedPoints, pointi)
|
||||||
|
{
|
||||||
|
changedPoints.set(pointi, oldPoints[pointi] != currPoints[pointi]);
|
||||||
|
}
|
||||||
|
|
||||||
|
DebugInfo
|
||||||
|
<< "SBM --- Changed points:"
|
||||||
|
<< returnReduce(changedPoints.count(), sumOp<label>())
|
||||||
|
<< endl;
|
||||||
|
|
||||||
|
// Quick return if no points have moved
|
||||||
|
if (returnReduce(changedPoints.none(), andOp<label>()))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bitSet cellIDs(mesh_.nCells());
|
||||||
|
bitSet faceIDs(mesh_.nFaces());
|
||||||
|
|
||||||
|
const auto& pointFaces = mesh_.pointFaces();
|
||||||
|
const auto& own = mesh_.faceOwner();
|
||||||
|
const auto& nbr = mesh_.faceNeighbour();
|
||||||
|
|
||||||
|
// Identify faces and cells attached to moving points
|
||||||
|
for (const label pointi : changedPoints)
|
||||||
|
{
|
||||||
|
for (const auto facei : pointFaces[pointi])
|
||||||
|
{
|
||||||
|
faceIDs.set(facei);
|
||||||
|
|
||||||
|
cellIDs.set(own[facei]);
|
||||||
|
if (facei < mesh_.nInternalFaces())
|
||||||
|
{
|
||||||
|
cellIDs.set(nbr[facei]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
changedCellIDs_ = cellIDs.toc();
|
||||||
|
|
||||||
|
DebugInfo
|
||||||
|
<< "SBM --- Changed cells:"
|
||||||
|
<< returnReduce(changedCellIDs_.size(), sumOp<label>())
|
||||||
|
<< endl;
|
||||||
|
|
||||||
|
|
||||||
|
// Construct face and patch ID info
|
||||||
|
|
||||||
|
const auto changedFaceFlag = faceIDs.values();
|
||||||
|
|
||||||
|
DynamicList<label> changedFaceIDs(faceIDs.count());
|
||||||
|
DynamicList<label> changedPatchIDs(faceIDs.count());
|
||||||
|
for (label facei = 0; facei < mesh_.nInternalFaces(); ++facei)
|
||||||
|
{
|
||||||
|
if (changedFaceFlag[facei])
|
||||||
|
{
|
||||||
|
changedFaceIDs.append(facei);
|
||||||
|
changedPatchIDs.append(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& pbm = mesh_.boundaryMesh();
|
||||||
|
for (label patchi = 0; patchi < pbm.size(); ++patchi)
|
||||||
|
{
|
||||||
|
const polyPatch& pp = pbm[patchi];
|
||||||
|
|
||||||
|
for (const label meshFacei : pp.range())
|
||||||
|
{
|
||||||
|
if (changedFaceFlag[meshFacei])
|
||||||
|
{
|
||||||
|
changedFaceIDs.append(meshFacei);
|
||||||
|
changedPatchIDs.append(patchi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
changedFaceIDs_.transfer(changedFaceIDs);
|
||||||
|
changedPatchIDs_.transfer(changedPatchIDs);
|
||||||
|
}
|
||||||
|
|
||||||
|
cacheInitialised_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::solidBodyFvGeometryScheme::solidBodyFvGeometryScheme
|
||||||
|
(
|
||||||
|
const fvMesh& mesh,
|
||||||
|
const dictionary& dict
|
||||||
|
)
|
||||||
|
:
|
||||||
|
basicFvGeometryScheme(mesh, dict),
|
||||||
|
partialUpdate_(dict.getOrDefault<bool>("partialUpdate", true)),
|
||||||
|
cacheMotion_(dict.getOrDefault<bool>("cacheMotion", true)),
|
||||||
|
cacheInitialised_(false),
|
||||||
|
changedFaceIDs_(),
|
||||||
|
changedPatchIDs_(),
|
||||||
|
changedCellIDs_()
|
||||||
|
{
|
||||||
|
DebugInFunction
|
||||||
|
<< "partialUpdate:" << partialUpdate_
|
||||||
|
<< " cacheMotion:" << cacheMotion_
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
void Foam::solidBodyFvGeometryScheme::movePoints()
|
||||||
|
{
|
||||||
|
// Note: not calling fvGeometryScheme::movePoints since we want to perform
|
||||||
|
// our own geometry manipulations
|
||||||
|
|
||||||
|
bool haveGeometry =
|
||||||
|
mesh_.hasCellCentres()
|
||||||
|
&& mesh_.hasFaceCentres()
|
||||||
|
&& mesh_.hasCellVolumes()
|
||||||
|
&& mesh_.hasFaceAreas();
|
||||||
|
|
||||||
|
if (!haveGeometry)
|
||||||
|
{
|
||||||
|
DebugInFunction
|
||||||
|
<< "Creating initial geometry using primitiveMesh::updateGeom"
|
||||||
|
<< endl;
|
||||||
|
|
||||||
|
const_cast<fvMesh&>(mesh_).primitiveMesh::updateGeom();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mesh_.moving())
|
||||||
|
{
|
||||||
|
setMeshMotionData();
|
||||||
|
|
||||||
|
DebugInFunction << "Performing partial meshPhi construction" << endl;
|
||||||
|
|
||||||
|
const pointField& oldPoints = mesh_.oldPoints();
|
||||||
|
const pointField& currPoints = mesh_.points();
|
||||||
|
|
||||||
|
if (oldPoints.size() != currPoints.size())
|
||||||
|
{
|
||||||
|
FatalErrorInFunction
|
||||||
|
<< "Old and current points sizes must be the same. "
|
||||||
|
<< "Old points:" << oldPoints.size()
|
||||||
|
<< " Current points:" << currPoints.size()
|
||||||
|
<< abort(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
const polyBoundaryMesh& pbm = mesh_.boundaryMesh();
|
||||||
|
const faceList& faces = mesh_.faces();
|
||||||
|
const scalar rdt = 1.0/mesh_.time().deltaTValue();
|
||||||
|
|
||||||
|
// Set the mesh flux
|
||||||
|
auto& meshPhi = const_cast<fvMesh&>(mesh_).setPhi();
|
||||||
|
auto& meshPhii = meshPhi.primitiveFieldRef();
|
||||||
|
auto& meshPhiBf = meshPhi.boundaryFieldRef();
|
||||||
|
|
||||||
|
//meshPhi == dimensionedScalar(dimVolume/dimTime, Zero);
|
||||||
|
meshPhii = Zero;
|
||||||
|
meshPhiBf == Zero;
|
||||||
|
|
||||||
|
forAll(changedFaceIDs_, i)
|
||||||
|
{
|
||||||
|
const face& f = faces[changedFaceIDs_[i]];
|
||||||
|
|
||||||
|
if (changedPatchIDs_[i] == -1)
|
||||||
|
{
|
||||||
|
const label facei = changedFaceIDs_[i];
|
||||||
|
meshPhii[facei] = f.sweptVol(oldPoints, currPoints)*rdt;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const label patchi = changedPatchIDs_[i];
|
||||||
|
const polyPatch& pp = pbm[patchi];
|
||||||
|
|
||||||
|
if (isA<emptyPolyPatch>(pp))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const label patchFacei = changedFaceIDs_[i] - pp.start();
|
||||||
|
|
||||||
|
meshPhiBf[patchi][patchFacei] =
|
||||||
|
f.sweptVol(oldPoints, currPoints)*rdt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (partialUpdate_ && haveGeometry)
|
||||||
|
{
|
||||||
|
// Keep base geometry and update as needed
|
||||||
|
DebugInFunction << "Performing partial geometry update" << endl;
|
||||||
|
|
||||||
|
// Initialise geometry using the old/existing values
|
||||||
|
vectorField faceCentres(mesh_.faceCentres());
|
||||||
|
vectorField faceAreas(mesh_.faceAreas());
|
||||||
|
|
||||||
|
// Make face centres and areas consistent with new points
|
||||||
|
primitiveMeshTools::updateFaceCentresAndAreas
|
||||||
|
(
|
||||||
|
mesh_,
|
||||||
|
changedFaceIDs_,
|
||||||
|
mesh_.points(),
|
||||||
|
faceCentres,
|
||||||
|
faceAreas
|
||||||
|
);
|
||||||
|
|
||||||
|
vectorField cellCentres(mesh_.cellCentres());
|
||||||
|
scalarField cellVolumes(mesh_.cellVolumes());
|
||||||
|
|
||||||
|
primitiveMeshTools::updateCellCentresAndVols
|
||||||
|
(
|
||||||
|
mesh_,
|
||||||
|
faceCentres,
|
||||||
|
faceAreas,
|
||||||
|
changedCellIDs_,
|
||||||
|
mesh_.cells(),
|
||||||
|
cellCentres,
|
||||||
|
cellVolumes
|
||||||
|
);
|
||||||
|
|
||||||
|
const_cast<fvMesh&>(mesh_).primitiveMesh::resetGeometry
|
||||||
|
(
|
||||||
|
std::move(faceCentres),
|
||||||
|
std::move(faceAreas),
|
||||||
|
std::move(cellCentres),
|
||||||
|
std::move(cellVolumes)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
for (const auto& p : mesh_.boundaryMesh())
|
||||||
|
{
|
||||||
|
Pout<< "SBM --- " << p.name()
|
||||||
|
<< " sum(Sf)=" << sum(p.faceAreas())
|
||||||
|
<< " sum(mag(Sf))=" << sum(mag(p.faceAreas()))
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DebugInFunction
|
||||||
|
<< "Performing complete geometry clear and update" << endl;
|
||||||
|
|
||||||
|
// Clear out old geometry
|
||||||
|
// Note: this recreates the old primitiveMesh::movePoints behaviour
|
||||||
|
const_cast<fvMesh&>(mesh_).primitiveMesh::clearGeom();
|
||||||
|
|
||||||
|
// Use lower level to calculate the geometry
|
||||||
|
const_cast<fvMesh&>(mesh_).primitiveMesh::updateGeom();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DebugInFunction << "Performing complete geometry update" << endl;
|
||||||
|
|
||||||
|
// Use lower level to calculate the geometry
|
||||||
|
const_cast<fvMesh&>(mesh_).primitiveMesh::updateGeom();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::solidBodyFvGeometryScheme::updateMesh(const mapPolyMesh& mpm)
|
||||||
|
{
|
||||||
|
cacheInitialised_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,141 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 2021-2022 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::solidBodyFvGeometryScheme
|
||||||
|
|
||||||
|
Description
|
||||||
|
Geometry calculation scheme that performs geometry updates only in regions
|
||||||
|
where the mesh has changed.
|
||||||
|
|
||||||
|
Example usage in fvSchemes:
|
||||||
|
|
||||||
|
\verbatim
|
||||||
|
geometry
|
||||||
|
{
|
||||||
|
type solidBody;
|
||||||
|
|
||||||
|
// Optional entries
|
||||||
|
|
||||||
|
// If set to false, update the entire mesh
|
||||||
|
partialUpdate yes;
|
||||||
|
|
||||||
|
// Cache the motion addressing (changed points, faces, cells etc)
|
||||||
|
cacheMotion yes;
|
||||||
|
}
|
||||||
|
\endverbatim
|
||||||
|
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
solidBodyFvGeometryScheme.C
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef solidBodyFvGeometryScheme_H
|
||||||
|
#define solidBodyFvGeometryScheme_H
|
||||||
|
|
||||||
|
#include "basicFvGeometryScheme.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class solidBodyFvGeometryScheme Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class solidBodyFvGeometryScheme
|
||||||
|
:
|
||||||
|
public basicFvGeometryScheme
|
||||||
|
{
|
||||||
|
// Private Data
|
||||||
|
|
||||||
|
//- Partial update flag
|
||||||
|
bool partialUpdate_;
|
||||||
|
|
||||||
|
//- Cache mesh motion flag
|
||||||
|
bool cacheMotion_;
|
||||||
|
|
||||||
|
//- Flag to indicate that the cache has been initialised
|
||||||
|
bool cacheInitialised_;
|
||||||
|
|
||||||
|
//- Changed face IDs
|
||||||
|
labelList changedFaceIDs_;
|
||||||
|
|
||||||
|
//- Changed patch IDs
|
||||||
|
labelList changedPatchIDs_;
|
||||||
|
|
||||||
|
//- Changed cell IDs
|
||||||
|
labelList changedCellIDs_;
|
||||||
|
|
||||||
|
|
||||||
|
// Private Member Functions
|
||||||
|
|
||||||
|
//- Set the mesh motion data (point, face IDs)
|
||||||
|
void setMeshMotionData();
|
||||||
|
|
||||||
|
//- No copy construct
|
||||||
|
solidBodyFvGeometryScheme(const solidBodyFvGeometryScheme&) = delete;
|
||||||
|
|
||||||
|
//- No copy assignment
|
||||||
|
void operator=(const solidBodyFvGeometryScheme&) = delete;
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//- Runtime type information
|
||||||
|
TypeName("solidBody");
|
||||||
|
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
//- Construct from mesh
|
||||||
|
solidBodyFvGeometryScheme(const fvMesh& mesh, const dictionary& dict);
|
||||||
|
|
||||||
|
|
||||||
|
//- Destructor
|
||||||
|
virtual ~solidBodyFvGeometryScheme() = default;
|
||||||
|
|
||||||
|
|
||||||
|
// Member Functions
|
||||||
|
|
||||||
|
//- Do what is necessary if the mesh has moved
|
||||||
|
virtual void movePoints();
|
||||||
|
|
||||||
|
//- Update mesh for topology changes
|
||||||
|
virtual void updateMesh(const mapPolyMesh& mpm);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
Reference in New Issue
Block a user