Merge branch 'feature-solid-body-mesh-motion-optimisation' into 'develop'

New solid body motion mesh update optimisations

See merge request Development/openfoam!537
This commit is contained in:
Mattijs Janssens
2022-05-19 16:19:47 +00:00
43 changed files with 1115 additions and 276 deletions

View File

@ -217,6 +217,10 @@ void uniqueOrder
); );
//- Return sorted list with removal of duplicates
template<class T>
List<T> uniqueSort(const UList<T>& input);
//- Inplace sorting and removal of duplicates. //- Inplace sorting and removal of duplicates.
// Do not use FixedList for the input list, since it doesn't resize. // Do not use FixedList for the input list, since it doesn't resize.
template<class ListType> template<class ListType>

View File

@ -424,6 +424,33 @@ void Foam::uniqueOrder
} }
template<class T>
Foam::List<T> Foam::uniqueSort(const UList<T>& input)
{
List<T> output(input);
const label len = output.size();
if (len > 1)
{
Foam::stableSort(output);
label count = 0;
for (label i = 1; i < len; ++i)
{
if (output[count] != output[i])
{
output[++count] = output[i];
}
}
output.resize(count+1);
}
return output;
}
template<class ListType> template<class ListType>
void Foam::inplaceUniqueSort(ListType& input) void Foam::inplaceUniqueSort(ListType& input)
{ {

View File

@ -1156,10 +1156,7 @@ const Foam::pointField& Foam::polyMesh::oldCellCentres() const
} }
Foam::tmp<Foam::scalarField> Foam::polyMesh::movePoints void Foam::polyMesh::movePoints(const pointField& newPoints)
(
const pointField& newPoints
)
{ {
DebugInFunction DebugInFunction
<< "Moving points for time " << time().value() << "Moving points for time " << time().value()
@ -1227,11 +1224,17 @@ Foam::tmp<Foam::scalarField> Foam::polyMesh::movePoints
tetBasePtIsPtr_->eventNo() = getEvent(); tetBasePtIsPtr_->eventNo() = getEvent();
} }
tmp<scalarField> sweptVols = primitiveMesh::movePoints // Currently a no-op; earlier versions set meshPhi and call
( // primitiveMesh::clearGeom
points_, (void)primitiveMesh::movePoints(points_, oldPoints());
oldPoints()
); // Update the mesh geometry (via fvGeometryScheme)
// - updateGeom is virtual -> calls fvMesh::updateGeom (or higher)
// - fvMesh::updateGeom defers to surfaceInterpolation::updateGeom(),
// which defers to fvGeometryScheme::movePoints()
// - set the mesh flux
// - clear out/recalculate stale geometry
updateGeom();
// Adjust parallel shared points // Adjust parallel shared points
if (globalMeshDataPtr_) if (globalMeshDataPtr_)
@ -1279,8 +1282,6 @@ Foam::tmp<Foam::scalarField> Foam::polyMesh::movePoints
// e.g. fvMesh::write since meshPhi not yet complete. // e.g. fvMesh::write since meshPhi not yet complete.
polyMesh::write(); polyMesh::write();
} }
return sweptVols;
} }

View File

@ -556,8 +556,8 @@ public:
return (moving() || topoChanging()); return (moving() || topoChanging());
} }
//- Move points, returns volumes swept by faces in motion //- Move points
virtual tmp<scalarField> movePoints(const pointField&); virtual void movePoints(const pointField&);
//- Reset motion //- Reset motion
void resetMotion() const; void resetMotion() const;

View File

@ -6,6 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -136,7 +137,7 @@ bool Foam::primitiveMesh::calcPointOrder
// Internal points are points that are not used by a boundary face. // Internal points are points that are not used by a boundary face.
// Map from old to new position // Map from old to new position
oldToNew.setSize(nPoints); oldToNew.resize_nocopy(nPoints);
oldToNew = -1; oldToNew = -1;
@ -144,14 +145,12 @@ bool Foam::primitiveMesh::calcPointOrder
// from 0 inside oldToNew. (shifted up later on) // from 0 inside oldToNew. (shifted up later on)
label nBoundaryPoints = 0; label nBoundaryPoints = 0;
for (label facei = nInternalFaces; facei < faces.size(); facei++) for (label facei = nInternalFaces; facei < faces.size(); ++facei)
{ {
const face& f = faces[facei]; const face& f = faces[facei];
forAll(f, fp) for (label pointi : f)
{ {
label pointi = f[fp];
if (oldToNew[pointi] == -1) if (oldToNew[pointi] == -1)
{ {
oldToNew[pointi] = nBoundaryPoints++; oldToNew[pointi] = nBoundaryPoints++;
@ -184,10 +183,8 @@ bool Foam::primitiveMesh::calcPointOrder
{ {
const face& f = faces[facei]; const face& f = faces[facei];
forAll(f, fp) for (label pointi : f)
{ {
label pointi = f[fp];
if (oldToNew[pointi] == -1) if (oldToNew[pointi] == -1)
{ {
if (pointi >= nInternalPoints) if (pointi >= nInternalPoints)
@ -318,35 +315,17 @@ void Foam::primitiveMesh::resetGeometry
} }
Foam::tmp<Foam::scalarField> Foam::primitiveMesh::movePoints void Foam::primitiveMesh::movePoints
( (
const pointField& newPoints, const pointField& newPoints,
const pointField& oldPoints const pointField& oldPoints
) )
{ {
if (newPoints.size() < nPoints() || oldPoints.size() < nPoints()) // Note: the following clearout is now handled by the fvGeometryScheme
{ // triggered by the call to updateGeom() in polyMesh::movePoints
FatalErrorInFunction
<< "Cannot move points: size of given point list smaller "
<< "than the number of active points"
<< abort(FatalError);
}
// Create swept volumes
const faceList& fcs = faces();
auto tsweptVols = tmp<scalarField>::New(fcs.size());
auto& sweptVols = tsweptVols.ref();
forAll(fcs, facei)
{
sweptVols[facei] = fcs[facei].sweptVol(oldPoints, newPoints);
}
// Force recalculation of all geometric data with new points // Force recalculation of all geometric data with new points
clearGeom(); //clearGeom();
return tsweptVols;
} }
@ -361,7 +340,6 @@ const Foam::cellShapeList& Foam::primitiveMesh::cellShapes() const
} }
void Foam::primitiveMesh::updateGeom() void Foam::primitiveMesh::updateGeom()
{ {
if (!faceCentresPtr_ || !faceAreasPtr_) if (!faceCentresPtr_ || !faceAreasPtr_)

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2018 OpenCFD Ltd. Copyright (C) 2018-2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -598,8 +598,8 @@ public:
// Mesh motion // Mesh motion
//- Move points, returns volumes swept by faces in motion //- Move points
tmp<scalarField> movePoints void movePoints
( (
const pointField& p, const pointField& p,
const pointField& oldP const pointField& oldP

View File

@ -6,6 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -52,11 +53,11 @@ void Foam::primitiveMesh::calcCellCentresAndVols() const
} }
// set the accumulated cell centre to zero vector // set the accumulated cell centre to zero vector
cellCentresPtr_ = new vectorField(nCells()); cellCentresPtr_ = new vectorField(nCells(), Zero);
vectorField& cellCtrs = *cellCentresPtr_; vectorField& cellCtrs = *cellCentresPtr_;
// Initialise cell volumes to 0 // Initialise cell volumes to 0
cellVolumesPtr_ = new scalarField(nCells()); cellVolumesPtr_ = new scalarField(nCells(), Zero);
scalarField& cellVols = *cellVolumesPtr_; scalarField& cellVols = *cellVolumesPtr_;
// Make centres and volumes // Make centres and volumes

View File

@ -34,6 +34,172 @@ License
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
void Foam::primitiveMeshTools::updateFaceCentresAndAreas
(
const primitiveMesh& mesh,
const UList<label>& faceIDs,
const pointField& p,
vectorField& fCtrs,
vectorField& fAreas
)
{
const faceList& fs = mesh.faces();
for (const label facei : faceIDs)
{
const labelList& f = fs[facei];
const label nPoints = f.size();
// If the face is a triangle, do a direct calculation for efficiency
// and to avoid round-off error-related problems
if (nPoints == 3)
{
fCtrs[facei] = (1.0/3.0)*(p[f[0]] + p[f[1]] + p[f[2]]);
fAreas[facei] = 0.5*((p[f[1]] - p[f[0]])^(p[f[2]] - p[f[0]]));
}
else
{
typedef Vector<solveScalar> solveVector;
solveVector sumN = Zero;
solveScalar sumA = 0.0;
solveVector sumAc = Zero;
solveVector fCentre = p[f[0]];
for (label pi = 1; pi < nPoints; ++pi)
{
fCentre += solveVector(p[f[pi]]);
}
fCentre /= nPoints;
for (label pi = 0; pi < nPoints; ++pi)
{
const label nextPi(pi == nPoints-1 ? 0 : pi+1);
const solveVector nextPoint(p[f[nextPi]]);
const solveVector thisPoint(p[f[pi]]);
solveVector c = thisPoint + nextPoint + fCentre;
solveVector n = (nextPoint - thisPoint)^(fCentre - thisPoint);
solveScalar a = mag(n);
sumN += n;
sumA += a;
sumAc += a*c;
}
// This is to deal with zero-area faces. Mark very small faces
// to be detected in e.g., processorPolyPatch.
if (sumA < ROOTVSMALL)
{
fCtrs[facei] = fCentre;
fAreas[facei] = Zero;
}
else
{
fCtrs[facei] = (1.0/3.0)*sumAc/sumA;
fAreas[facei] = 0.5*sumN;
}
}
}
}
void Foam::primitiveMeshTools::updateCellCentresAndVols
(
const primitiveMesh& mesh,
const vectorField& fCtrs,
const vectorField& fAreas,
const List<label>& cellIDs,
const List<cell>& cells,
vectorField& cellCtrs_s,
scalarField& cellVols_s
)
{
typedef Vector<solveScalar> solveVector;
PrecisionAdaptor<solveVector, vector> tcellCtrs(cellCtrs_s, false);
PrecisionAdaptor<solveScalar, scalar> tcellVols(cellVols_s, false);
Field<solveVector>& cellCtrs = tcellCtrs.ref();
Field<solveScalar>& cellVols = tcellVols.ref();
// Use current cell centres as estimates for the new cell centres
// Note - not currently used
// - Introduces a small difference (seen when write precision extended to
// 16) to the cell centre and volume values, typically last 4 digits
//const vectorField Cc0(cellCtrs, cellIDs);
// Estimate cell centres using current face centres
// - Same method as used by makeCellCentresAndVols()
vectorField Cc0(cellIDs.size(), Zero);
{
labelField nCellFaces(cellIDs.size(), Zero);
const auto& cells = mesh.cells();
forAll(cellIDs, i)
{
const label celli = cellIDs[i];
const cell& c = cells[celli];
for (const auto facei : c)
{
Cc0[i] += fCtrs[facei];
++nCellFaces[i];
}
}
forAll(Cc0, i)
{
Cc0[i] /= nCellFaces[i];
}
}
// Clear the fields for accumulation
for (const label celli : cellIDs)
{
cellCtrs[celli] = Zero;
cellVols[celli] = Zero;
}
const auto& own = mesh.faceOwner();
forAll(cellIDs, i)
{
const label celli = cellIDs[i];
const auto& c = cells[celli];
const solveVector cc(Cc0[i]);
for (const label facei : c)
{
const solveVector fc(fCtrs[facei]);
const solveVector fA(fAreas[facei]);
const solveScalar pyr3Vol = own[facei] == celli
? fA & (fc - cc)
: fA & (cc - fc);
// Calculate face-pyramid centre
const solveVector pc = (3.0/4.0)*fc + (1.0/4.0)*cc;
// Accumulate volume-weighted face-pyramid centre
cellCtrs[celli] += pyr3Vol*pc;
// Accumulate face-pyramid volume
cellVols[celli] += pyr3Vol;
}
if (mag(cellVols[celli]) > VSMALL)
{
cellCtrs[celli] /= cellVols[celli];
cellVols[celli] *= (1.0/3.0);
}
else
{
cellCtrs[celli] = Cc0[i];
}
}
}
void Foam::primitiveMeshTools::makeFaceCentresAndAreas void Foam::primitiveMeshTools::makeFaceCentresAndAreas
( (
const UList<face>& fcs, const UList<face>& fcs,
@ -164,8 +330,7 @@ void Foam::primitiveMeshTools::makeCellCentresAndVols
const solveVector fA(fAreas[facei]); const solveVector fA(fAreas[facei]);
// Calculate 3*face-pyramid volume // Calculate 3*face-pyramid volume
solveScalar pyr3Vol = solveScalar pyr3Vol = fA & (fc - cEst[own[facei]]);
fA & (fc - cEst[own[facei]]);
// Calculate face-pyramid centre // Calculate face-pyramid centre
solveVector pc = (3.0/4.0)*fc + (1.0/4.0)*cEst[own[facei]]; solveVector pc = (3.0/4.0)*fc + (1.0/4.0)*cEst[own[facei]];
@ -183,8 +348,7 @@ void Foam::primitiveMeshTools::makeCellCentresAndVols
const solveVector fA(fAreas[facei]); const solveVector fA(fAreas[facei]);
// Calculate 3*face-pyramid volume // Calculate 3*face-pyramid volume
solveScalar pyr3Vol = solveScalar pyr3Vol = fA & (cEst[nei[facei]] - fc);
fA & (cEst[nei[facei]] - fc);
// Calculate face-pyramid centre // Calculate face-pyramid centre
solveVector pc = (3.0/4.0)*fc + (1.0/4.0)*cEst[nei[facei]]; solveVector pc = (3.0/4.0)*fc + (1.0/4.0)*cEst[nei[facei]];

View File

@ -48,6 +48,7 @@ namespace Foam
{ {
// Forward Declarations // Forward Declarations
class cell;
class face; class face;
class primitiveMesh; class primitiveMesh;
@ -59,6 +60,28 @@ class primitiveMeshTools
{ {
public: public:
//- Update face centres and areas for the faces in the set faceIDs
static void updateFaceCentresAndAreas
(
const primitiveMesh& mesh,
const UList<label>& faceIDs,
const pointField& p,
vectorField& fCtrs,
vectorField& fAreas
);
//- Update cell centres and volumes for the cells in the set cellIDs
static void updateCellCentresAndVols
(
const primitiveMesh& mesh,
const vectorField& fCtrs,
const vectorField& fAreas,
const List<label>& cellIDs,
const List<cell>& cells,
vectorField& cellCtrs_s,
scalarField& cellVols_s
);
//- Calculate face centres and areas for specified faces. //- Calculate face centres and areas for specified faces.
// Adjusts the lengths of centres and area normals if required. // Adjusts the lengths of centres and area normals if required.
static void makeFaceCentresAndAreas static void makeFaceCentresAndAreas
@ -117,7 +140,7 @@ public:
const vectorField& cellCtrs const vectorField& cellCtrs
); );
//- Generate cell openness and cell ascpect ratio field //- Generate cell openness and cell aspect ratio field
static void cellClosedness static void cellClosedness
( (
const primitiveMesh& mesh, const primitiveMesh& mesh,

View File

@ -6,6 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2012 OpenFOAM Foundation Copyright (C) 2011-2012 OpenFOAM Foundation
Copyright (C) 2018-2020 OpenCFD Ltd. Copyright (C) 2018-2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -27,6 +27,7 @@ License
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "dynamicFvMesh.H" #include "dynamicFvMesh.H"
#include "profiling.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@ -174,6 +175,7 @@ bool Foam::dynamicFvMesh::controlledUpdate()
<< timeControl_.type() << nl; << timeControl_.type() << nl;
} }
addProfiling(mesh, "mesh.update()");
return this->update(); return this->update();
} }

View File

@ -30,6 +30,7 @@ License
#include "addToRunTimeSelectionTable.H" #include "addToRunTimeSelectionTable.H"
#include "motionSolver.H" #include "motionSolver.H"
#include "volFields.H" #include "volFields.H"
#include "zoneMotion.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@ -104,12 +105,6 @@ Foam::dynamicMotionSolverFvMesh::dynamicMotionSolverFvMesh
{} {}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::dynamicMotionSolverFvMesh::~dynamicMotionSolverFvMesh()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
const Foam::motionSolver& Foam::dynamicMotionSolverFvMesh::motion() const const Foam::motionSolver& Foam::dynamicMotionSolverFvMesh::motion() const
@ -120,9 +115,6 @@ const Foam::motionSolver& Foam::dynamicMotionSolverFvMesh::motion() const
bool Foam::dynamicMotionSolverFvMesh::update() bool Foam::dynamicMotionSolverFvMesh::update()
{ {
// Scan through AMI patches and update
fvMesh::movePoints(motionPtr_->newPoints()); fvMesh::movePoints(motionPtr_->newPoints());
volVectorField* Uptr = getObjectPtr<volVectorField>("U"); volVectorField* Uptr = getObjectPtr<volVectorField>("U");

View File

@ -94,7 +94,7 @@ public:
//- Destructor //- Destructor
~dynamicMotionSolverFvMesh(); virtual ~dynamicMotionSolverFvMesh() = default;
// Member Functions // Member Functions

View File

@ -29,7 +29,7 @@ License
#include "simplifiedDynamicFvMesh.H" #include "simplifiedDynamicFvMesh.H"
#include "staticFvMesh.H" #include "staticFvMesh.H"
#include "dynamicMotionSolverFvMesh.H" #include "dynamicMotionSolverFvMesh.H"
#include "motionSolver.H"
namespace Foam namespace Foam
{ {

View File

@ -134,10 +134,4 @@ Foam::displacementMotionSolver::New
} }
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::displacementMotionSolver::~displacementMotionSolver()
{}
// ************************************************************************* // // ************************************************************************* //

View File

@ -133,7 +133,7 @@ public:
//- Destructor //- Destructor
virtual ~displacementMotionSolver(); virtual ~displacementMotionSolver() = default;
// Member Functions // Member Functions

View File

@ -98,16 +98,14 @@ Foam::zoneMotion::zoneMotion
{ {
boolList movePts(mesh.nPoints(), false); boolList movePts(mesh.nPoints(), false);
forAll(cellIDs, i) for (label celli : cellIDs)
{ {
label celli = cellIDs[i];
const cell& c = mesh.cells()[celli]; const cell& c = mesh.cells()[celli];
forAll(c, j) for (label cellFacei : c)
{ {
const face& f = mesh.faces()[c[j]]; const face& f = mesh.faces()[cellFacei];
forAll(f, k) for (label pointi : f)
{ {
label pointi = f[k];
movePts[pointi] = true; movePts[pointi] = true;
} }
} }

View File

@ -142,12 +142,6 @@ Foam::points0MotionSolver::points0MotionSolver
} }
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::points0MotionSolver::~points0MotionSolver()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::points0MotionSolver::movePoints(const pointField&) void Foam::points0MotionSolver::movePoints(const pointField&)

View File

@ -106,7 +106,7 @@ public:
//- Destructor //- Destructor
virtual ~points0MotionSolver(); virtual ~points0MotionSolver() = default;
// Member Functions // Member Functions

View File

@ -133,12 +133,6 @@ Foam::multiSolidBodyMotionSolver::multiSolidBodyMotionSolver
} }
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::multiSolidBodyMotionSolver::~multiSolidBodyMotionSolver()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::tmp<Foam::pointField> Foam::multiSolidBodyMotionSolver::curPoints() const Foam::tmp<Foam::pointField> Foam::multiSolidBodyMotionSolver::curPoints() const

View File

@ -92,7 +92,7 @@ public:
//- Destructor //- Destructor
~multiSolidBodyMotionSolver(); virtual ~multiSolidBodyMotionSolver() = default;
// Member Functions // Member Functions

View File

@ -118,16 +118,14 @@ Foam::solidBodyMotionSolver::solidBodyMotionSolver
boolList movePts(mesh.nPoints(), false); boolList movePts(mesh.nPoints(), false);
forAll(cellIDs, i) for (label celli : cellIDs)
{ {
label celli = cellIDs[i];
const cell& c = mesh.cells()[celli]; const cell& c = mesh.cells()[celli];
forAll(c, j) for (label cellFacei : c)
{ {
const face& f = mesh.faces()[c[j]]; const face& f = mesh.faces()[cellFacei];
forAll(f, k) for (label pointi : f)
{ {
label pointi = f[k];
movePts[pointi] = true; movePts[pointi] = true;
} }
} }
@ -149,12 +147,6 @@ Foam::solidBodyMotionSolver::solidBodyMotionSolver
} }
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::solidBodyMotionSolver::~solidBodyMotionSolver()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::tmp<Foam::pointField> Foam::solidBodyMotionSolver::curPoints() const Foam::tmp<Foam::pointField> Foam::solidBodyMotionSolver::curPoints() const
@ -165,7 +157,7 @@ Foam::tmp<Foam::pointField> Foam::solidBodyMotionSolver::curPoints() const
} }
else else
{ {
tmp<pointField> ttransformedPts(new pointField(mesh().points())); auto ttransformedPts = tmp<pointField>::New(mesh().points());
pointField& transformedPts = ttransformedPts.ref(); pointField& transformedPts = ttransformedPts.ref();
UIndirectList<point>(transformedPts, pointIDs_) = transformPoints UIndirectList<point>(transformedPts, pointIDs_) = transformPoints

View File

@ -92,7 +92,7 @@ public:
//- Destructor //- Destructor
~solidBodyMotionSolver(); virtual ~solidBodyMotionSolver() = default;
// Member Functions // Member Functions

View File

@ -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

View File

@ -55,11 +55,14 @@ Foam::basicFvGeometryScheme::basicFvGeometryScheme
void Foam::basicFvGeometryScheme::movePoints() void Foam::basicFvGeometryScheme::movePoints()
{ {
fvGeometryScheme::movePoints();
if (debug) if (debug)
{ {
Pout<< "basicFvGeometryScheme::movePoints() : " Pout<< "basicFvGeometryScheme::movePoints() : "
<< "recalculating primitiveMesh centres" << endl; << "recalculating primitiveMesh centres" << endl;
} }
// Use lower level to calculate the geometry // Use lower level to calculate the geometry
const_cast<fvMesh&>(mesh_).primitiveMesh::updateGeom(); const_cast<fvMesh&>(mesh_).primitiveMesh::updateGeom();
} }
@ -74,9 +77,8 @@ Foam::tmp<Foam::surfaceScalarField> Foam::basicFvGeometryScheme::weights() const
<< endl; << endl;
} }
tmp<surfaceScalarField> tweights auto tweights =
( tmp<surfaceScalarField>::New
new surfaceScalarField
( (
IOobject IOobject
( (
@ -89,9 +91,9 @@ Foam::tmp<Foam::surfaceScalarField> Foam::basicFvGeometryScheme::weights() const
), ),
mesh_, mesh_,
dimless dimless
) );
);
surfaceScalarField& weights = tweights.ref(); auto& weights = tweights.ref();
weights.setOriented(); weights.setOriented();
// Set local references to mesh data // Set local references to mesh data
@ -128,7 +130,7 @@ Foam::tmp<Foam::surfaceScalarField> Foam::basicFvGeometryScheme::weights() const
} }
} }
surfaceScalarField::Boundary& wBf = weights.boundaryFieldRef(); auto& wBf = weights.boundaryFieldRef();
forAll(mesh_.boundary(), patchi) forAll(mesh_.boundary(), patchi)
{ {
@ -159,9 +161,8 @@ Foam::basicFvGeometryScheme::deltaCoeffs() const
// needed to make sure deltaCoeffs are calculated for parallel runs. // needed to make sure deltaCoeffs are calculated for parallel runs.
(void)mesh_.weights(); (void)mesh_.weights();
tmp<surfaceScalarField> tdeltaCoeffs auto tdeltaCoeffs =
( tmp<surfaceScalarField>::New
new surfaceScalarField
( (
IOobject IOobject
( (
@ -174,14 +175,14 @@ Foam::basicFvGeometryScheme::deltaCoeffs() const
), ),
mesh_, mesh_,
dimless/dimLength dimless/dimLength
) );
);
surfaceScalarField& deltaCoeffs = tdeltaCoeffs.ref(); auto& deltaCoeffs = tdeltaCoeffs.ref();
deltaCoeffs.setOriented(); deltaCoeffs.setOriented();
// Set local references to mesh data // Set local references to mesh data
const volVectorField& C = mesh_.C(); const vectorField& C = mesh_.cellCentres();
const labelUList& owner = mesh_.owner(); const labelUList& owner = mesh_.owner();
const labelUList& neighbour = mesh_.neighbour(); const labelUList& neighbour = mesh_.neighbour();
@ -190,8 +191,7 @@ Foam::basicFvGeometryScheme::deltaCoeffs() const
deltaCoeffs[facei] = 1.0/mag(C[neighbour[facei]] - C[owner[facei]]); deltaCoeffs[facei] = 1.0/mag(C[neighbour[facei]] - C[owner[facei]]);
} }
surfaceScalarField::Boundary& deltaCoeffsBf = auto& deltaCoeffsBf = deltaCoeffs.boundaryFieldRef();
deltaCoeffs.boundaryFieldRef();
forAll(deltaCoeffsBf, patchi) forAll(deltaCoeffsBf, patchi)
{ {
@ -220,9 +220,8 @@ Foam::basicFvGeometryScheme::nonOrthDeltaCoeffs() const
// needed to make sure deltaCoeffs are calculated for parallel runs. // needed to make sure deltaCoeffs are calculated for parallel runs.
weights(); weights();
tmp<surfaceScalarField> tnonOrthDeltaCoeffs auto tnonOrthDeltaCoeffs =
( tmp<surfaceScalarField>::New
new surfaceScalarField
( (
IOobject IOobject
( (
@ -235,9 +234,9 @@ Foam::basicFvGeometryScheme::nonOrthDeltaCoeffs() const
), ),
mesh_, mesh_,
dimless/dimLength dimless/dimLength
) );
);
surfaceScalarField& nonOrthDeltaCoeffs = tnonOrthDeltaCoeffs.ref(); auto& nonOrthDeltaCoeffs = tnonOrthDeltaCoeffs.ref();
nonOrthDeltaCoeffs.setOriented(); nonOrthDeltaCoeffs.setOriented();
@ -266,8 +265,7 @@ Foam::basicFvGeometryScheme::nonOrthDeltaCoeffs() const
nonOrthDeltaCoeffs[facei] = 1.0/max(unitArea & delta, 0.05*mag(delta)); nonOrthDeltaCoeffs[facei] = 1.0/max(unitArea & delta, 0.05*mag(delta));
} }
surfaceScalarField::Boundary& nonOrthDeltaCoeffsBf = auto& nonOrthDeltaCoeffsBf = nonOrthDeltaCoeffs.boundaryFieldRef();
nonOrthDeltaCoeffs.boundaryFieldRef();
forAll(nonOrthDeltaCoeffsBf, patchi) forAll(nonOrthDeltaCoeffsBf, patchi)
{ {
@ -306,9 +304,8 @@ Foam::basicFvGeometryScheme::nonOrthCorrectionVectors() const
<< endl; << endl;
} }
tmp<surfaceVectorField> tnonOrthCorrectionVectors auto tnonOrthCorrectionVectors =
( tmp<surfaceVectorField>::New
new surfaceVectorField
( (
IOobject IOobject
( (
@ -321,9 +318,9 @@ Foam::basicFvGeometryScheme::nonOrthCorrectionVectors() const
), ),
mesh_, mesh_,
dimless dimless
) );
);
surfaceVectorField& corrVecs = tnonOrthCorrectionVectors.ref(); auto& corrVecs = tnonOrthCorrectionVectors.ref();
corrVecs.setOriented(); corrVecs.setOriented();
// Set local references to mesh data // Set local references to mesh data
@ -337,8 +334,8 @@ Foam::basicFvGeometryScheme::nonOrthCorrectionVectors() const
forAll(owner, facei) forAll(owner, facei)
{ {
vector unitArea = Sf[facei]/magSf[facei]; vector unitArea(Sf[facei]/magSf[facei]);
vector delta = C[neighbour[facei]] - C[owner[facei]]; vector delta(C[neighbour[facei]] - C[owner[facei]]);
corrVecs[facei] = unitArea - delta*NonOrthDeltaCoeffs[facei]; corrVecs[facei] = unitArea - delta*NonOrthDeltaCoeffs[facei];
} }
@ -347,7 +344,7 @@ Foam::basicFvGeometryScheme::nonOrthCorrectionVectors() const
// and calculated consistently with internal corrections for // and calculated consistently with internal corrections for
// coupled patches // coupled patches
surfaceVectorField::Boundary& corrVecsBf = corrVecs.boundaryFieldRef(); auto& corrVecsBf = corrVecs.boundaryFieldRef();
forAll(corrVecsBf, patchi) forAll(corrVecsBf, patchi)
{ {
@ -361,7 +358,7 @@ Foam::basicFvGeometryScheme::nonOrthCorrectionVectors() const
} }
else else
{ {
const fvsPatchScalarField& patchNonOrthDeltaCoeffs = const auto& patchNonOrthDeltaCoeffs =
NonOrthDeltaCoeffs.boundaryField()[patchi]; NonOrthDeltaCoeffs.boundaryField()[patchi];
const vectorField patchDeltas(mesh_.boundary()[patchi].delta()); const vectorField patchDeltas(mesh_.boundary()[patchi].delta());

View File

@ -26,6 +26,8 @@ License
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "fvGeometryScheme.H" #include "fvGeometryScheme.H"
#include "fvMesh.H"
#include "surfaceFields.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@ -37,10 +39,63 @@ namespace Foam
} }
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
bool Foam::fvGeometryScheme::setMeshPhi() const
{
if (!mesh_.moving())
{
return false;
}
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 faceList& faces = mesh_.faces();
const scalar rdt = 1.0/mesh_.time().deltaTValue();
auto& meshPhi = const_cast<fvMesh&>(mesh_).setPhi();
auto& meshPhii = meshPhi.primitiveFieldRef();
forAll(meshPhii, facei)
{
const face& f = faces[facei];
meshPhii[facei] = f.sweptVol(oldPoints, currPoints)*rdt;
}
auto& meshPhiBf = meshPhi.boundaryFieldRef();
for (auto& meshPhip : meshPhiBf)
{
if (!meshPhip.size())
{
// Empty patches
continue;
}
const auto& pp = meshPhip.patch().patch();
forAll(pp, facei)
{
const face& f = pp[facei];
meshPhip[facei] = f.sweptVol(oldPoints, currPoints)*rdt;
}
}
return true;
}
// * * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * //
Foam::tmp<Foam::fvGeometryScheme> Foam::tmp<Foam::fvGeometryScheme> Foam::fvGeometryScheme::New
Foam::fvGeometryScheme::New
( (
const fvMesh& mesh, const fvMesh& mesh,
const dictionary& dict, const dictionary& dict,
@ -55,10 +110,7 @@ Foam::fvGeometryScheme::New
: dict.getOrDefault<word>("type", defaultScheme) : dict.getOrDefault<word>("type", defaultScheme)
); );
if (debug) DebugInFunction << "Geometry scheme = " << schemeName << endl;
{
InfoInFunction << "Geometry scheme = " << schemeName << endl;
}
auto* ctorPtr = dictConstructorTable(schemeName); auto* ctorPtr = dictConstructorTable(schemeName);
@ -77,4 +129,24 @@ Foam::fvGeometryScheme::New
} }
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::fvGeometryScheme::movePoints()
{
if (mesh_.moving())
{
// Set the mesh motion fluxes
setMeshPhi();
// Clear out old geometry
// Note: this recreates the old primitiveMesh::movePoints behaviour
const_cast<fvMesh&>(mesh_).primitiveMesh::clearGeom();
}
}
void Foam::fvGeometryScheme::updateMesh(const mapPolyMesh& mpm)
{}
// ************************************************************************* // // ************************************************************************* //

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com \\ / A nd | www.openfoam.com
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2020 OpenCFD Ltd. Copyright (C) 2020-2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -69,10 +69,18 @@ class fvGeometryScheme
protected: protected:
// Protected Data
//- Hold reference to mesh //- Hold reference to mesh
const fvMesh& mesh_; const fvMesh& mesh_;
// Protected Member Functions
//- Set the mesh motion flux
bool setMeshPhi() const;
public: public:
//- Runtime type information //- Runtime type information
@ -127,8 +135,10 @@ public:
} }
//- Update basic geometric properties from provided points //- Update basic geometric properties from provided points
virtual void movePoints() virtual void movePoints();
{}
//- Update mesh for topology changes
virtual void updateMesh(const mapPolyMesh& mpm);
//- Return linear difference weighting factors //- Return linear difference weighting factors
virtual tmp<surfaceScalarField> weights() const = 0; virtual tmp<surfaceScalarField> weights() const = 0;

View File

@ -387,6 +387,9 @@ Foam::highAspectRatioFvGeometryScheme::highAspectRatioFvGeometryScheme
void Foam::highAspectRatioFvGeometryScheme::movePoints() void Foam::highAspectRatioFvGeometryScheme::movePoints()
{ {
//basicFvGeometryScheme::movePoints();
fvGeometryScheme::movePoints();
if (debug) if (debug)
{ {
Pout<< "highAspectRatioFvGeometryScheme::movePoints() : " Pout<< "highAspectRatioFvGeometryScheme::movePoints() : "

View File

@ -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;
}
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -157,6 +157,8 @@ Foam::stabilisedFvGeometryScheme::stabilisedFvGeometryScheme
void Foam::stabilisedFvGeometryScheme::movePoints() void Foam::stabilisedFvGeometryScheme::movePoints()
{ {
fvGeometryScheme::movePoints();
if (debug) if (debug)
{ {
Pout<< "stabilisedFvGeometryScheme::movePoints() : " Pout<< "stabilisedFvGeometryScheme::movePoints() : "

View File

@ -90,18 +90,22 @@ void Foam::fvMesh::updateGeomNotOldVol()
{ {
(void)V(); (void)V();
} }
if (haveSf) if (haveSf)
{ {
(void)Sf(); (void)Sf();
} }
if (haveMagSf) if (haveMagSf)
{ {
(void)magSf(); (void)magSf();
} }
if (haveCP) if (haveCP)
{ {
(void)C(); (void)C();
} }
if (haveCf) if (haveCf)
{ {
(void)Cf(); (void)Cf();
@ -277,7 +281,7 @@ bool Foam::fvMesh::init(const bool doInit)
// doing anything with primitiveMesh::cellCentres etc. // doing anything with primitiveMesh::cellCentres etc.
(void)geometry(); (void)geometry();
// Intialise my data // Initialise my data
polyMesh::init(doInit); polyMesh::init(doInit);
} }
@ -285,6 +289,10 @@ bool Foam::fvMesh::init(const bool doInit)
// and set the storage of V00 // and set the storage of V00
if (fileHandler().isFile(time().timePath()/dbDir()/"V0")) if (fileHandler().isFile(time().timePath()/dbDir()/"V0"))
{ {
// Set the moving flag early in case the demand-driven geometry
// construction checks for it
moving(true);
V0Ptr_ = new DimensionedField<scalar, volMesh> V0Ptr_ = new DimensionedField<scalar, volMesh>
( (
IOobject IOobject
@ -306,6 +314,10 @@ bool Foam::fvMesh::init(const bool doInit)
// mesh to be moving // mesh to be moving
if (fileHandler().isFile(time().timePath()/dbDir()/"meshPhi")) if (fileHandler().isFile(time().timePath()/dbDir()/"meshPhi"))
{ {
// Set the moving flag early in case the demand-driven geometry
// construction checks for it
moving(true);
phiPtr_ = new surfaceScalarField phiPtr_ = new surfaceScalarField
( (
IOobject IOobject
@ -339,8 +351,6 @@ bool Foam::fvMesh::init(const bool doInit)
V() V()
); );
} }
moving(true);
} }
// Assume something changed // Assume something changed
@ -643,7 +653,7 @@ void Foam::fvMesh::removeFvBoundary()
Foam::polyMesh::readUpdateState Foam::fvMesh::readUpdate() Foam::polyMesh::readUpdateState Foam::fvMesh::readUpdate()
{ {
DebugInFunction << "Updating fvMesh. "; DebugInFunction << "Updating fvMesh";
polyMesh::readUpdateState state = polyMesh::readUpdate(); polyMesh::readUpdateState state = polyMesh::readUpdate();
@ -861,7 +871,8 @@ void Foam::fvMesh::mapFields(const mapPolyMesh& meshMap)
} }
Foam::tmp<Foam::scalarField> Foam::fvMesh::movePoints(const pointField& p)
void Foam::fvMesh::movePoints(const pointField& p)
{ {
DebugInFunction << endl; DebugInFunction << endl;
@ -873,12 +884,8 @@ Foam::tmp<Foam::scalarField> Foam::fvMesh::movePoints(const pointField& p)
} }
// Move the polyMesh and set the mesh motion fluxes to the swept-volumes // Move the polyMesh and initialise the mesh motion fluxes field
// Note: mesh flux updated by the fvGeometryScheme
scalar rDeltaT = 1.0/time().deltaTValue();
tmp<scalarField> tsweptVols = polyMesh::movePoints(p);
scalarField& sweptVols = tsweptVols.ref();
if (!phiPtr_) if (!phiPtr_)
{ {
@ -895,7 +902,7 @@ Foam::tmp<Foam::scalarField> Foam::fvMesh::movePoints(const pointField& p)
false false
), ),
*this, *this,
dimVolume/dimTime dimensionedScalar(dimVolume/dimTime, Zero)
); );
} }
else else
@ -907,19 +914,7 @@ Foam::tmp<Foam::scalarField> Foam::fvMesh::movePoints(const pointField& p)
} }
} }
surfaceScalarField& phi = *phiPtr_; polyMesh::movePoints(p);
phi.primitiveFieldRef() =
scalarField::subField(sweptVols, nInternalFaces());
phi.primitiveFieldRef() *= rDeltaT;
const fvPatchList& patches = boundary();
surfaceScalarField::Boundary& phibf = phi.boundaryFieldRef();
forAll(patches, patchi)
{
phibf[patchi] = patches[patchi].patchSlice(sweptVols);
phibf[patchi] *= rDeltaT;
}
// Update or delete the local geometric properties as early as possible so // Update or delete the local geometric properties as early as possible so
// they can be used if necessary. These get recreated here instead of // they can be used if necessary. These get recreated here instead of
@ -929,20 +924,21 @@ Foam::tmp<Foam::scalarField> Foam::fvMesh::movePoints(const pointField& p)
// should use the local geometric properties. // should use the local geometric properties.
updateGeomNotOldVol(); updateGeomNotOldVol();
// Update other local data // Update other local data
boundary_.movePoints(); boundary_.movePoints();
surfaceInterpolation::movePoints();
// Clear weights, deltaCoeffs, nonOrthoDeltaCoeffs, nonOrthCorrectionVectors
surfaceInterpolation::clearOut();
meshObject::movePoints<fvMesh>(*this); meshObject::movePoints<fvMesh>(*this);
meshObject::movePoints<lduMesh>(*this); meshObject::movePoints<lduMesh>(*this);
return tsweptVols;
} }
void Foam::fvMesh::updateGeom() void Foam::fvMesh::updateGeom()
{ {
DebugInFunction << endl;
// Let surfaceInterpolation handle geometry calculation. Note: this does // Let surfaceInterpolation handle geometry calculation. Note: this does
// lower levels updateGeom // lower levels updateGeom
surfaceInterpolation::updateGeom(); surfaceInterpolation::updateGeom();
@ -1003,7 +999,7 @@ void Foam::fvMesh::updateMesh(const mapPolyMesh& mpm)
mapFields(mpm); mapFields(mpm);
// Clear the current volume and other geometry factors // Clear the current volume and other geometry factors
surfaceInterpolation::clearOut(); surfaceInterpolation::updateMesh(mpm);
// Clear any non-updateable addressing // Clear any non-updateable addressing
clearAddressing(true); clearAddressing(true);

View File

@ -469,7 +469,7 @@ public:
using surfaceInterpolation::movePoints; using surfaceInterpolation::movePoints;
//- Move points, returns volumes swept by faces in motion //- Move points, returns volumes swept by faces in motion
virtual tmp<scalarField> movePoints(const pointField&); virtual void movePoints(const pointField&);
//- Update all geometric data. This gets redirected up from //- Update all geometric data. This gets redirected up from
//- primitiveMesh level //- primitiveMesh level

View File

@ -48,6 +48,8 @@ namespace Foam
void Foam::surfaceInterpolation::clearOut() void Foam::surfaceInterpolation::clearOut()
{ {
// TBD: potential to apply partial clear out only?
// Move to fvGeometryScheme?
weights_.clear(); weights_.clear();
deltaCoeffs_.clear(); deltaCoeffs_.clear();
nonOrthDeltaCoeffs_.clear(); nonOrthDeltaCoeffs_.clear();
@ -161,10 +163,7 @@ bool Foam::surfaceInterpolation::movePoints()
// Do any primitive geometry calculation // Do any primitive geometry calculation
const_cast<fvGeometryScheme&>(geometry()).movePoints(); const_cast<fvGeometryScheme&>(geometry()).movePoints();
weights_.clear(); clearOut();
deltaCoeffs_.clear();
nonOrthDeltaCoeffs_.clear();
nonOrthCorrectionVectors_.clear();
return true; return true;
} }
@ -179,6 +178,22 @@ void Foam::surfaceInterpolation::updateGeom()
} }
const_cast<fvGeometryScheme&>(geometry()).movePoints(); const_cast<fvGeometryScheme&>(geometry()).movePoints();
clearOut();
}
void Foam::surfaceInterpolation::updateMesh(const mapPolyMesh& mpm)
{
if (debug)
{
Pout<< "surfaceInterpolation::updateMesh() : "
<< "Updating geometric properties" << endl;
}
const_cast<fvGeometryScheme&>(geometry()).updateMesh(mpm);
clearOut();
} }

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011 OpenFOAM Foundation Copyright (C) 2011 OpenFOAM Foundation
Copyright (C) 2020 OpenCFD Ltd. Copyright (C) 2020-2022 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -52,6 +52,7 @@ namespace Foam
// Forward Declarations // Forward Declarations
class fvMesh; class fvMesh;
class fvGeometryScheme; class fvGeometryScheme;
class mapPolyMesh;
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
Class surfaceInterpolation Declaration Class surfaceInterpolation Declaration
@ -141,6 +142,9 @@ public:
//- Has weights //- Has weights
bool hasWeights() const noexcept { return bool(weights_); } bool hasWeights() const noexcept { return bool(weights_); }
//- Update mesh for topology changes
virtual void updateMesh(const mapPolyMesh& mpm);
}; };

View File

@ -60,6 +60,22 @@ Foam::functionObjects::writeObjects::writeOptionNames_
{ writeOption::ANY_WRITE, "anyWrite" }, { writeOption::ANY_WRITE, "anyWrite" },
}); });
const Foam::objectRegistry& setRegistry
(
const Foam::Time& runTime,
const Foam::dictionary& dict
)
{
const Foam::word regionName =
dict.getOrDefault("region", Foam::polyMesh::defaultRegion);
if (regionName == "__TIME__")
{
return runTime;
}
return runTime.lookupObject<Foam::objectRegistry>(regionName);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
@ -71,13 +87,7 @@ Foam::functionObjects::writeObjects::writeObjects
) )
: :
functionObject(name), functionObject(name),
obr_ obr_(setRegistry(runTime, dict)),
(
runTime.lookupObject<objectRegistry>
(
dict.getOrDefault("region", polyMesh::defaultRegion)
)
),
writeOption_(ANY_WRITE), writeOption_(ANY_WRITE),
objectNames_() objectNames_()
{ {

View File

@ -1135,6 +1135,10 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::doRemoveCells
meshMod meshMod
); );
// Remove any unnecessary fields
mesh_.clearOut();
mesh_.moving(false);
// Change the mesh (no inflation) // Change the mesh (no inflation)
autoPtr<mapPolyMesh> mapPtr = meshMod.changeMesh(mesh_, false, true); autoPtr<mapPolyMesh> mapPtr = meshMod.changeMesh(mesh_, false, true);
mapPolyMesh& map = *mapPtr; mapPolyMesh& map = *mapPtr;
@ -1327,6 +1331,10 @@ Foam::label Foam::meshRefinement::splitFacesUndo
// Insert the mesh changes // Insert the mesh changes
doSplitFaces(splitFaces, splits, meshMod); doSplitFaces(splitFaces, splits, meshMod);
// Remove any unnecessary fields
mesh_.clearOut();
mesh_.moving(false);
// Change the mesh (no inflation) // Change the mesh (no inflation)
autoPtr<mapPolyMesh> mapPtr = meshMod.changeMesh(mesh_, false, true); autoPtr<mapPolyMesh> mapPtr = meshMod.changeMesh(mesh_, false, true);
mapPolyMesh& map = *mapPtr; mapPolyMesh& map = *mapPtr;
@ -1339,6 +1347,10 @@ Foam::label Foam::meshRefinement::splitFacesUndo
{ {
mesh_.movePoints(map.preMotionPoints()); mesh_.movePoints(map.preMotionPoints());
} }
else
{
mesh_.clearOut();
}
// Reset the instance for if in overwrite mode // Reset the instance for if in overwrite mode
mesh_.setInstance(timeName()); mesh_.setInstance(timeName());
@ -1550,6 +1562,10 @@ Foam::label Foam::meshRefinement::splitFacesUndo
nSplit -= n; nSplit -= n;
// Remove any unnecessary fields
mesh_.clearOut();
mesh_.moving(false);
// Change the mesh (no inflation) // Change the mesh (no inflation)
autoPtr<mapPolyMesh> mapPtr = meshMod.changeMesh(mesh_, false, true); autoPtr<mapPolyMesh> mapPtr = meshMod.changeMesh(mesh_, false, true);
mapPolyMesh& map = *mapPtr; mapPolyMesh& map = *mapPtr;
@ -1562,6 +1578,10 @@ Foam::label Foam::meshRefinement::splitFacesUndo
{ {
mesh_.movePoints(map.preMotionPoints()); mesh_.movePoints(map.preMotionPoints());
} }
else
{
mesh_.clearOut();
}
// Reset the instance for if in overwrite mode // Reset the instance for if in overwrite mode
mesh_.setInstance(timeName()); mesh_.setInstance(timeName());

View File

@ -600,6 +600,10 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::createBaffles
autoPtr<mapPolyMesh> mapPtr; autoPtr<mapPolyMesh> mapPtr;
if (returnReduce(nBaffles, sumOp<label>())) if (returnReduce(nBaffles, sumOp<label>()))
{ {
// Remove any unnecessary fields
mesh_.clearOut();
mesh_.moving(false);
// Change the mesh (no inflation, parallel sync) // Change the mesh (no inflation, parallel sync)
mapPtr = meshMod.changeMesh(mesh_, false, true); mapPtr = meshMod.changeMesh(mesh_, false, true);
mapPolyMesh& map = *mapPtr; mapPolyMesh& map = *mapPtr;
@ -1314,6 +1318,10 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::mergeBaffles
} }
// Remove any unnecessary fields
mesh_.clearOut();
mesh_.moving(false);
// Change the mesh (no inflation) // Change the mesh (no inflation)
mapPtr = meshMod.changeMesh(mesh_, false, true); mapPtr = meshMod.changeMesh(mesh_, false, true);
mapPolyMesh& map = *mapPtr; mapPolyMesh& map = *mapPtr;
@ -5346,6 +5354,10 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::dupNonManifoldPoints
// Insert changes into meshMod // Insert changes into meshMod
pointDuplicator.setRefinement(regionSide, meshMod); pointDuplicator.setRefinement(regionSide, meshMod);
// Remove any unnecessary fields
mesh_.clearOut();
mesh_.moving(false);
// Change the mesh (no inflation, parallel sync) // Change the mesh (no inflation, parallel sync)
mapPtr = meshMod.changeMesh(mesh_, false, true); mapPtr = meshMod.changeMesh(mesh_, false, true);
mapPolyMesh& map = *mapPtr; mapPolyMesh& map = *mapPtr;
@ -5421,6 +5433,10 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::mergePoints
// Insert changes // Insert changes
polyMeshAdder::mergePoints(mesh_, pointToMaster, meshMod); polyMeshAdder::mergePoints(mesh_, pointToMaster, meshMod);
// Remove any unnecessary fields
mesh_.clearOut();
mesh_.moving(false);
// Change the mesh (no inflation, parallel sync) // Change the mesh (no inflation, parallel sync)
mapPtr = meshMod.changeMesh(mesh_, false, true); mapPtr = meshMod.changeMesh(mesh_, false, true);
mapPolyMesh& map = *mapPtr; mapPolyMesh& map = *mapPtr;
@ -5988,6 +6004,10 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::zonify
meshMod meshMod
); );
// Remove any unnecessary fields
mesh_.clearOut();
mesh_.moving(false);
// Change the mesh (no inflation, parallel sync) // Change the mesh (no inflation, parallel sync)
autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh_, false, true); autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh_, false, true);

View File

@ -108,6 +108,10 @@ Foam::label Foam::meshRefinement::mergePatchFaces
// unused points. // unused points.
faceCombiner.setRefinement(mergeSets, meshMod); faceCombiner.setRefinement(mergeSets, meshMod);
// Remove any unnecessary fields
mesh_.clearOut();
mesh_.moving(false);
// Change the mesh (no inflation) // Change the mesh (no inflation)
autoPtr<mapPolyMesh> mapPtr = meshMod.changeMesh(mesh_, false, true); autoPtr<mapPolyMesh> mapPtr = meshMod.changeMesh(mesh_, false, true);
mapPolyMesh& map = *mapPtr; mapPolyMesh& map = *mapPtr;
@ -197,6 +201,10 @@ Foam::label Foam::meshRefinement::mergePatchFaces
// //
// pointRemover.setRefinement(pointCanBeDeleted, meshMod); // pointRemover.setRefinement(pointCanBeDeleted, meshMod);
// //
// // Remove any unnecessary fields
// mesh_.clearOut();
// mesh_.moving(false);
//
// // Change the mesh (no inflation) // // Change the mesh (no inflation)
// map = meshMod.changeMesh(mesh_, false, true); // map = meshMod.changeMesh(mesh_, false, true);
// //
@ -359,6 +367,10 @@ Foam::label Foam::meshRefinement::mergePatchFacesUndo
labelList(0) // cells to store labelList(0) // cells to store
); );
// Remove any unnecessary fields
mesh_.clearOut();
mesh_.moving(false);
// Change the mesh (no inflation) // Change the mesh (no inflation)
autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh_, false, true); autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh_, false, true);
@ -544,6 +556,10 @@ Foam::label Foam::meshRefinement::mergePatchFacesUndo
restoredCells restoredCells
); );
// Remove any unnecessary fields
mesh_.clearOut();
mesh_.moving(false);
// Change the mesh (no inflation) // Change the mesh (no inflation)
autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh_, false, true); autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh_, false, true);
@ -629,6 +645,10 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::doRemovePoints
pointRemover.setRefinement(pointCanBeDeleted, meshMod); pointRemover.setRefinement(pointCanBeDeleted, meshMod);
// Remove any unnecessary fields
mesh_.clearOut();
mesh_.moving(false);
// Change the mesh (no inflation) // Change the mesh (no inflation)
autoPtr<mapPolyMesh> mapPtr = meshMod.changeMesh(mesh_, false, true); autoPtr<mapPolyMesh> mapPtr = meshMod.changeMesh(mesh_, false, true);
mapPolyMesh& map = *mapPtr; mapPolyMesh& map = *mapPtr;
@ -702,6 +722,10 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::doRestorePoints
meshMod meshMod
); );
// Remove any unnecessary fields
mesh_.clearOut();
mesh_.moving(false);
// Change the mesh (no inflation) // Change the mesh (no inflation)
autoPtr<mapPolyMesh> mapPtr = meshMod.changeMesh(mesh_, false, true); autoPtr<mapPolyMesh> mapPtr = meshMod.changeMesh(mesh_, false, true);
mapPolyMesh& map = *mapPtr; mapPolyMesh& map = *mapPtr;

View File

@ -2352,6 +2352,10 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::refine
// Play refinement commands into mesh changer. // Play refinement commands into mesh changer.
meshCutter_.setRefinement(cellsToRefine, meshMod); meshCutter_.setRefinement(cellsToRefine, meshMod);
// Remove any unnecessary fields
mesh_.clearOut();
mesh_.moving(false);
// Create mesh (no inflation), return map from old to new mesh. // Create mesh (no inflation), return map from old to new mesh.
autoPtr<mapPolyMesh> mapPtr = meshMod.changeMesh(mesh_, false); autoPtr<mapPolyMesh> mapPtr = meshMod.changeMesh(mesh_, false);
mapPolyMesh& map = *mapPtr; mapPolyMesh& map = *mapPtr;
@ -2774,6 +2778,10 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::directionalRefine
// Insert mesh refinement into polyTopoChange. // Insert mesh refinement into polyTopoChange.
meshRefiner.setRefinement(cuts, meshMod); meshRefiner.setRefinement(cuts, meshMod);
// Remove any unnecessary fields
mesh_.clearOut();
mesh_.moving(false);
autoPtr<mapPolyMesh> morphMap = meshMod.changeMesh(mesh_, false); autoPtr<mapPolyMesh> morphMap = meshMod.changeMesh(mesh_, false);
// Update fields // Update fields

View File

@ -30,6 +30,7 @@ License
#include "SubField.H" #include "SubField.H"
#include "Time.H" #include "Time.H"
#include "addToRunTimeSelectionTable.H" #include "addToRunTimeSelectionTable.H"
#include "primitiveMeshTools.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -191,8 +192,7 @@ void Foam::cyclicACMIPolyPatch::scalePatchFaceAreas
const vectorList& noFaceArea // nonOverlapPatch.faceAreas() const vectorList& noFaceArea // nonOverlapPatch.faceAreas()
) )
{ {
// Primitive patch face areas have been cleared/reset based on the raw // Set/scale polyPatch face areas to avoid double-accounting of face areas
// points - need to reset to avoid double-accounting of face areas
const scalar maxTol = scalar(1) - tolerance_; const scalar maxTol = scalar(1) - tolerance_;
@ -251,14 +251,31 @@ void Foam::cyclicACMIPolyPatch::scalePatchFaceAreas
{ {
scalar& sum = weightsSum[i]; scalar& sum = weightsSum[i];
forAll(wghts, j) for (scalar& w : wghts)
{ {
wghts[j] /= sum; w /= sum;
} }
sum = 1.0; sum = 1.0;
} }
} }
} }
const polyMesh& mesh = boundaryMesh().mesh();
// Recompute the cell volumes adjacent to the patches since the cells with
// duplicate faces are only closed after the duplicate faces have been
// scaled.
primitiveMeshTools::updateCellCentresAndVols
(
mesh,
mesh.faceCentres(),
mesh.faceAreas(), // already scaled
uniqueSort(acmipp.faceCells()), // unique cells only
mesh.cells(),
const_cast<vectorField&>(mesh.cellCentres()),
const_cast<scalarField&>(mesh.cellVolumes())
);
} }
@ -284,22 +301,6 @@ void Foam::cyclicACMIPolyPatch::resetAMI(const UList<point>& points) const
const polyMesh& mesh = boundaryMesh().mesh(); const polyMesh& mesh = boundaryMesh().mesh();
if (!createAMIFaces_ && mesh.hasCellCentres())
{
DebugPout
<< "cyclicACMIPolyPatch::resetAMI : clearing cellCentres"
<< " for " << name() << " and " << nonOverlapPatch.name() << nl
<< "The mesh already has cellCentres calculated when"
<< " resetting ACMI " << name() << "." << nl
<< "This is a problem since ACMI adapts the face areas"
<< " (to close cells) so this has" << nl
<< "to be done before cell centre calculation." << nl
<< "This can happen if e.g. the cyclicACMI is after"
<< " any processor patches in the boundary." << endl;
const_cast<polyMesh&>(mesh).primitiveMesh::clearCellGeom();
}
// At this point we want face geometry but not cell geometry since we want // At this point we want face geometry but not cell geometry since we want
// correct the face area on duplicate baffles before calculating the cell // correct the face area on duplicate baffles before calculating the cell
// centres and volumes. // centres and volumes.
@ -363,6 +364,8 @@ void Foam::cyclicACMIPolyPatch::scalePatchFaceAreas()
if (srcScalePtr_) if (srcScalePtr_)
{ {
// Use primitivePatch::faceAreas() to avoid need for additional copy?
// Save overlap geometry for later scaling // Save overlap geometry for later scaling
thisSf_ = this->faceAreas(); thisSf_ = this->faceAreas();
thisNoSf_ = nonOverlapPatch.faceAreas(); thisNoSf_ = nonOverlapPatch.faceAreas();
@ -370,24 +373,53 @@ void Foam::cyclicACMIPolyPatch::scalePatchFaceAreas()
nbrNoSf_ = nbrNonOverlapPatch.faceAreas(); nbrNoSf_ = nbrNonOverlapPatch.faceAreas();
} }
// In-place scale the patch areas // In-place scale the polyPatch face areas
// Note
// - using primitivePatch face areas since these are based on the raw
// point locations (not affected by ACMI scaling)
scalePatchFaceAreas scalePatchFaceAreas
( (
*this, *this,
srcMask_, // unscaled mask srcMask_, // unscaled mask
this->faceAreas(), this->primitivePatch::faceAreas(),
nonOverlapPatch.faceAreas() nonOverlapPatch.primitivePatch::faceAreas()
); );
scalePatchFaceAreas scalePatchFaceAreas
( (
nbrPatch, nbrPatch,
tgtMask_, // unscaled mask tgtMask_, // unscaled mask
nbrPatch.faceAreas(), nbrPatch.primitivePatch::faceAreas(),
nbrNonOverlapPatch.faceAreas() nbrNonOverlapPatch.primitivePatch::faceAreas()
); );
// Mark current AMI as up to date with points // Mark current AMI as up to date with points
boundaryMesh().mesh().setUpToDatePoints(AMITime_); boundaryMesh().mesh().setUpToDatePoints(AMITime_);
if (debug)
{
const auto& acmipp = *this;
const auto& mesh = boundaryMesh().mesh();
const auto& vols = mesh.cellVolumes();
Info<< "cyclicACMI PP: " << acmipp.name()
<< " V:" << sum(scalarField(vols, acmipp.faceCells()))
<< nl
<< "cyclicACMI N-O PP: " << nonOverlapPatch.name()
<< " V:" << sum(scalarField(vols, nonOverlapPatch.faceCells()))
<< nl
<< "cyclicACMI NBR PP: " << nbrPatch.name()
<< " V:" << sum(scalarField(vols, nbrPatch.faceCells()))
<< nl
<< "cyclicACMI NBR N-O PP: " << nbrNonOverlapPatch.name()
<< " V:" << sum(scalarField(vols, nbrNonOverlapPatch.faceCells()))
<< nl
<< "cyclicACMI PP+N-O AREA: "
<< sum(faceAreas() + nonOverlapPatch.faceAreas()) << nl
<< "cyclicACMI NBR PP+N-O AREA: "
<< sum(nbrPatch.faceAreas() + nbrNonOverlapPatch.faceAreas())
<< endl;
}
} }
@ -735,13 +767,13 @@ void Foam::cyclicACMIPolyPatch::newInternalProcFaces
const scalarField& fMask = srcMask(); const scalarField& fMask = srcMask();
// Add new faces as many weights for AMI // Add new faces as many weights for AMI
forAll (addSourceFaces, faceI) forAll(addSourceFaces, faceI)
{ {
if (fMask[faceI] > tolerance_) if (fMask[faceI] > tolerance_)
{ {
const labelList& nbrFaceIs = addSourceFaces[faceI]; const labelList& nbrFaceIs = addSourceFaces[faceI];
forAll (nbrFaceIs, j) forAll(nbrFaceIs, j)
{ {
label nbrFaceI = nbrFaceIs[j]; label nbrFaceI = nbrFaceIs[j];
@ -761,20 +793,21 @@ void Foam::cyclicACMIPolyPatch::newInternalProcFaces
} }
Foam::refPtr<Foam::labelListList> Foam::cyclicACMIPolyPatch::mapCollocatedFaces() const Foam::refPtr<Foam::labelListList>
Foam::cyclicACMIPolyPatch::mapCollocatedFaces() const
{ {
const scalarField& fMask = srcMask(); const scalarField& fMask = srcMask();
const labelListList& srcFaces = AMI().srcAddress(); const labelListList& srcFaces = AMI().srcAddress();
labelListList dOverFaces; labelListList dOverFaces;
dOverFaces.setSize(srcFaces.size()); dOverFaces.setSize(srcFaces.size());
forAll (dOverFaces, faceI) forAll(dOverFaces, faceI)
{ {
if (fMask[faceI] > tolerance_) if (fMask[faceI] > tolerance_)
{ {
dOverFaces[faceI].setSize(srcFaces[faceI].size()); dOverFaces[faceI].setSize(srcFaces[faceI].size());
forAll (dOverFaces[faceI], subFaceI) forAll(dOverFaces[faceI], subFaceI)
{ {
dOverFaces[faceI][subFaceI] = srcFaces[faceI][subFaceI]; dOverFaces[faceI][subFaceI] = srcFaces[faceI][subFaceI];
} }

View File

@ -106,7 +106,7 @@ private:
//- Weighting for target mask //- Weighting for target mask
mutable autoPtr<PatchFunction1<scalar>> tgtScalePtr_; mutable autoPtr<PatchFunction1<scalar>> tgtScalePtr_;
//- Stored face areas //- Stored raw/non-scaled face areas
mutable vectorField thisSf_; mutable vectorField thisSf_;
mutable vectorField thisNoSf_; mutable vectorField thisNoSf_;
mutable vectorField nbrSf_; mutable vectorField nbrSf_;

View File

@ -49,10 +49,8 @@ void Foam::primitiveMeshGeometry::updateFaceCentresAndAreas
{ {
const faceList& fs = mesh_.faces(); const faceList& fs = mesh_.faces();
forAll(changedFaces, i) for (label facei : changedFaces)
{ {
label facei = changedFaces[i];
const labelList& f = fs[facei]; const labelList& f = fs[facei];
label nPoints = f.size(); label nPoints = f.size();
@ -70,19 +68,19 @@ void Foam::primitiveMeshGeometry::updateFaceCentresAndAreas
vector sumAc = Zero; vector sumAc = Zero;
point fCentre = p[f[0]]; point fCentre = p[f[0]];
for (label pi = 1; pi < nPoints; pi++) for (label pi = 1; pi < nPoints; ++pi)
{ {
fCentre += p[f[pi]]; fCentre += p[f[pi]];
} }
fCentre /= nPoints; fCentre /= nPoints;
for (label pi = 0; pi < nPoints; pi++) for (label pi = 0; pi < nPoints; ++pi)
{ {
const point& nextPoint = p[f[(pi + 1) % nPoints]]; const point& nextPoint = p[f[(pi + 1) % nPoints]];
vector c = p[f[pi]] + nextPoint + fCentre; vector c(p[f[pi]] + nextPoint + fCentre);
vector n = (nextPoint - p[f[pi]])^(fCentre - p[f[pi]]); vector n((nextPoint - p[f[pi]])^(fCentre - p[f[pi]]));
scalar a = mag(n); scalar a = mag(n);
sumN += n; sumN += n;
@ -117,9 +115,8 @@ void Foam::primitiveMeshGeometry::updateCellCentresAndVols
scalarField nCellFaces(mesh_.nCells()); scalarField nCellFaces(mesh_.nCells());
UIndirectList<scalar>(nCellFaces, changedCells) = 0.0; UIndirectList<scalar>(nCellFaces, changedCells) = 0.0;
forAll(changedFaces, i) for (label facei : changedFaces)
{ {
label facei = changedFaces[i];
cEst[own[facei]] += faceCentres_[facei]; cEst[own[facei]] += faceCentres_[facei];
nCellFaces[own[facei]] += 1; nCellFaces[own[facei]] += 1;
@ -130,16 +127,13 @@ void Foam::primitiveMeshGeometry::updateCellCentresAndVols
} }
} }
forAll(changedCells, i) for (label celli : changedCells)
{ {
label celli = changedCells[i];
cEst[celli] /= nCellFaces[celli]; cEst[celli] /= nCellFaces[celli];
} }
forAll(changedFaces, i) for (label facei : changedFaces)
{ {
label facei = changedFaces[i];
// Calculate 3*face-pyramid volume // Calculate 3*face-pyramid volume
scalar pyr3Vol = max scalar pyr3Vol = max
( (
@ -198,10 +192,8 @@ Foam::labelList Foam::primitiveMeshGeometry::affectedCells
labelHashSet affectedCells(2*changedFaces.size()); labelHashSet affectedCells(2*changedFaces.size());
forAll(changedFaces, i) for (label facei : changedFaces)
{ {
label facei = changedFaces[i];
affectedCells.insert(own[facei]); affectedCells.insert(own[facei]);
if (mesh_.isInternalFace(facei)) if (mesh_.isInternalFace(facei))
@ -213,10 +205,8 @@ Foam::labelList Foam::primitiveMeshGeometry::affectedCells
} }
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
// Construct from components
Foam::primitiveMeshGeometry::primitiveMeshGeometry Foam::primitiveMeshGeometry::primitiveMeshGeometry
( (
const primitiveMesh& mesh const primitiveMesh& mesh
@ -228,9 +218,6 @@ Foam::primitiveMeshGeometry::primitiveMeshGeometry
} }
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::primitiveMeshGeometry::correct() void Foam::primitiveMeshGeometry::correct()
@ -312,7 +299,7 @@ bool Foam::primitiveMeshGeometry::checkFaceDotProduct
setPtr->insert(facei); setPtr->insert(facei);
} }
severeNonOrth++; ++severeNonOrth;
} }
else else
{ {
@ -328,7 +315,7 @@ bool Foam::primitiveMeshGeometry::checkFaceDotProduct
<< " deg." << endl; << " deg." << endl;
} }
errorNonOrth++; ++errorNonOrth;
if (setPtr) if (setPtr)
{ {
@ -415,10 +402,8 @@ bool Foam::primitiveMeshGeometry::checkFacePyramids
label nErrorPyrs = 0; label nErrorPyrs = 0;
forAll(checkFaces, i) for (label facei : checkFaces)
{ {
label facei = checkFaces[i];
// Create the owner pyramid - it will have negative volume // Create the owner pyramid - it will have negative volume
scalar pyrVol = pyramidPointFaceRef scalar pyrVol = pyramidPointFaceRef
( (
@ -448,7 +433,7 @@ bool Foam::primitiveMeshGeometry::checkFacePyramids
setPtr->insert(facei); setPtr->insert(facei);
} }
nErrorPyrs++; ++nErrorPyrs;
} }
if (mesh.isInternalFace(facei)) if (mesh.isInternalFace(facei))
@ -478,7 +463,7 @@ bool Foam::primitiveMeshGeometry::checkFacePyramids
setPtr->insert(facei); setPtr->insert(facei);
} }
nErrorPyrs++; ++nErrorPyrs;
} }
} }
} }
@ -529,10 +514,8 @@ bool Foam::primitiveMeshGeometry::checkFaceSkewness
label nWarnSkew = 0; label nWarnSkew = 0;
forAll(checkFaces, i) for (label facei : checkFaces)
{ {
label facei = checkFaces[i];
if (mesh.isInternalFace(facei)) if (mesh.isInternalFace(facei))
{ {
scalar dOwn = mag(faceCentres[facei] - cellCentres[own[facei]]); scalar dOwn = mag(faceCentres[facei] - cellCentres[own[facei]]);
@ -565,7 +548,7 @@ bool Foam::primitiveMeshGeometry::checkFaceSkewness
setPtr->insert(facei); setPtr->insert(facei);
} }
nWarnSkew++; ++nWarnSkew;
} }
if (skewness > maxSkew) if (skewness > maxSkew)
@ -606,7 +589,7 @@ bool Foam::primitiveMeshGeometry::checkFaceSkewness
setPtr->insert(facei); setPtr->insert(facei);
} }
nWarnSkew++; ++nWarnSkew;
} }
if (skewness > maxSkew) if (skewness > maxSkew)
@ -664,10 +647,8 @@ bool Foam::primitiveMeshGeometry::checkFaceWeights
label nWarnWeight = 0; label nWarnWeight = 0;
forAll(checkFaces, i) for (label facei : checkFaces)
{ {
label facei = checkFaces[i];
if (mesh.isInternalFace(facei)) if (mesh.isInternalFace(facei))
{ {
const point& fc = faceCentres[facei]; const point& fc = faceCentres[facei];
@ -690,7 +671,7 @@ bool Foam::primitiveMeshGeometry::checkFaceWeights
setPtr->insert(facei); setPtr->insert(facei);
} }
nWarnWeight++; ++nWarnWeight;
} }
minWeight = min(minWeight, weight); minWeight = min(minWeight, weight);
@ -755,10 +736,8 @@ bool Foam::primitiveMeshGeometry::checkFaceAngles
label errorFacei = -1; label errorFacei = -1;
forAll(checkFaces, i) for (label facei : checkFaces)
{ {
label facei = checkFaces[i];
const face& f = fcs[facei]; const face& f = fcs[facei];
const vector faceNormal = normalised(faceAreas[facei]); const vector faceNormal = normalised(faceAreas[facei]);
@ -795,7 +774,7 @@ bool Foam::primitiveMeshGeometry::checkFaceAngles
{ {
// Count only one error per face. // Count only one error per face.
errorFacei = facei; errorFacei = facei;
nConcave++; ++nConcave;
} }
if (setPtr) if (setPtr)
@ -916,13 +895,13 @@ bool Foam::primitiveMeshGeometry::checkFaceAngles
// scalar flatness = magArea / (sumA+VSMALL); // scalar flatness = magArea / (sumA+VSMALL);
// //
// sumFlatness += flatness; // sumFlatness += flatness;
// nSummed++; // ++nSummed;
// //
// minFlatness = min(minFlatness, flatness); // minFlatness = min(minFlatness, flatness);
// //
// if (flatness < warnFlatness) // if (flatness < warnFlatness)
// { // {
// nWarped++; // ++nWarped;
// //
// if (setPtr) // if (setPtr)
// { // {
@ -1098,17 +1077,15 @@ bool Foam::primitiveMeshGeometry::checkFaceArea
{ {
label nZeroArea = 0; label nZeroArea = 0;
forAll(checkFaces, i) for (label facei : checkFaces)
{ {
label facei = checkFaces[i];
if (mag(faceAreas[facei]) < minArea) if (mag(faceAreas[facei]) < minArea)
{ {
if (setPtr) if (setPtr)
{ {
setPtr->insert(facei); setPtr->insert(facei);
} }
nZeroArea++; ++nZeroArea;
} }
} }
@ -1163,9 +1140,9 @@ bool Foam::primitiveMeshGeometry::checkCellDeterminant
label nSumDet = 0; label nSumDet = 0;
label nWarnDet = 0; label nWarnDet = 0;
forAll(affectedCells, i) for (label celli : affectedCells)
{ {
const cell& cFaces = cells[affectedCells[i]]; const cell& cFaces = cells[celli];
tensor areaSum(Zero); tensor areaSum(Zero);
scalar magAreaSum = 0; scalar magAreaSum = 0;
@ -1184,7 +1161,7 @@ bool Foam::primitiveMeshGeometry::checkCellDeterminant
minDet = min(minDet, scaledDet); minDet = min(minDet, scaledDet);
sumDet += scaledDet; sumDet += scaledDet;
nSumDet++; ++nSumDet;
if (scaledDet < warnDet) if (scaledDet < warnDet)
{ {
@ -1197,7 +1174,7 @@ bool Foam::primitiveMeshGeometry::checkCellDeterminant
setPtr->insert(facei); setPtr->insert(facei);
} }
} }
nWarnDet++; ++nWarnDet;
} }
} }