mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: add faMeshTools for new/load mesh, proc addressing etc
ENH: simple faMeshSubset (zero-sized meshes only) ENH: additional access methods for faMesh, primitive geometry mode - wrapped walking of boundary edgeLabels as list of list (similar to edgeFaces). - primitive finiteArea geometry mode with reduced communication: primarily interesting for decomposition/redistribution (#2436) ENH: extra vtk debug outputs for checkFaMesh - report per-processor sizes in the mesh summary
This commit is contained in:
@ -6,7 +6,7 @@
|
|||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2016-2017 Wikki Ltd
|
Copyright (C) 2016-2017 Wikki Ltd
|
||||||
Copyright (C) 2021 OpenCFD Ltd.
|
Copyright (C) 2021-2022 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -46,6 +46,8 @@ Original Authors
|
|||||||
#include "edgeFields.H"
|
#include "edgeFields.H"
|
||||||
#include "processorFaPatch.H"
|
#include "processorFaPatch.H"
|
||||||
#include "foamVtkIndPatchWriter.H"
|
#include "foamVtkIndPatchWriter.H"
|
||||||
|
#include "foamVtkLineWriter.H"
|
||||||
|
#include "faMeshTools.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -66,11 +68,27 @@ int main(int argc, char *argv[])
|
|||||||
"Write mesh as a vtp (vtk) file for display or debugging"
|
"Write mesh as a vtp (vtk) file for display or debugging"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
argList::addOption
|
||||||
|
(
|
||||||
|
"geometryOrder",
|
||||||
|
"N",
|
||||||
|
"Test different geometry order - experimental!!",
|
||||||
|
true // Advanced option
|
||||||
|
);
|
||||||
|
|
||||||
#include "addRegionOption.H"
|
#include "addRegionOption.H"
|
||||||
#include "setRootCase.H"
|
#include "setRootCase.H"
|
||||||
#include "createTime.H"
|
#include "createTime.H"
|
||||||
#include "createNamedPolyMesh.H"
|
#include "createNamedPolyMesh.H"
|
||||||
|
|
||||||
|
int geometryOrder(1);
|
||||||
|
if (args.readIfPresent("geometryOrder", geometryOrder))
|
||||||
|
{
|
||||||
|
Info<< "Setting faMesh::geometryOrder = " << geometryOrder << nl
|
||||||
|
<< "(experimental)" << nl << endl;
|
||||||
|
|
||||||
|
faMesh::geometryOrder(geometryOrder);
|
||||||
|
}
|
||||||
|
|
||||||
// Create
|
// Create
|
||||||
faMesh aMesh(mesh);
|
faMesh aMesh(mesh);
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2021 OpenCFD Ltd.
|
Copyright (C) 2021-2022 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
|
This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
|
||||||
@ -16,7 +16,7 @@ Description
|
|||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
{
|
{
|
||||||
// finiteArea
|
// finiteArea - faces
|
||||||
vtk::uindirectPatchWriter writer
|
vtk::uindirectPatchWriter writer
|
||||||
(
|
(
|
||||||
aMesh.patch(),
|
aMesh.patch(),
|
||||||
@ -29,9 +29,23 @@ Description
|
|||||||
|
|
||||||
writer.writeGeometry();
|
writer.writeGeometry();
|
||||||
|
|
||||||
|
globalIndex procAddr(aMesh.nFaces());
|
||||||
|
labelList cellIDs;
|
||||||
|
|
||||||
|
if (Pstream::master())
|
||||||
|
{
|
||||||
|
cellIDs.resize(procAddr.totalSize());
|
||||||
|
for (const labelRange& range : procAddr.ranges())
|
||||||
|
{
|
||||||
|
auto slice = cellIDs.slice(range);
|
||||||
|
slice = identity(range);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// CellData
|
// CellData
|
||||||
writer.beginCellData(3);
|
writer.beginCellData(4);
|
||||||
writer.writeProcIDs();
|
writer.writeProcIDs();
|
||||||
|
writer.write("cellID", cellIDs);
|
||||||
writer.write("area", aMesh.S().field());
|
writer.write("area", aMesh.S().field());
|
||||||
writer.write("normal", aMesh.faceAreaNormals());
|
writer.write("normal", aMesh.faceAreaNormals());
|
||||||
|
|
||||||
@ -43,5 +57,79 @@ Description
|
|||||||
<< "Wrote faMesh in vtk format: " << writer.output().name() << nl;
|
<< "Wrote faMesh in vtk format: " << writer.output().name() << nl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// finiteArea - edges
|
||||||
|
vtk::lineWriter writer
|
||||||
|
(
|
||||||
|
aMesh.points(),
|
||||||
|
aMesh.edges(),
|
||||||
|
// vtk::formatType::INLINE_ASCII,
|
||||||
|
fileName
|
||||||
|
(
|
||||||
|
aMesh.mesh().time().globalPath() / "finiteArea-edges"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
writer.writeGeometry();
|
||||||
|
|
||||||
|
// CellData
|
||||||
|
writer.beginCellData(4);
|
||||||
|
writer.writeProcIDs();
|
||||||
|
{
|
||||||
|
// Use primitive patch order
|
||||||
|
Field<scalar> fld
|
||||||
|
(
|
||||||
|
faMeshTools::flattenEdgeField(aMesh.magLe(), true)
|
||||||
|
);
|
||||||
|
writer.write("magLe", fld);
|
||||||
|
}
|
||||||
|
|
||||||
|
// PointData
|
||||||
|
writer.beginPointData(1);
|
||||||
|
writer.write("normal", aMesh.pointAreaNormals());
|
||||||
|
|
||||||
|
Info<< nl
|
||||||
|
<< "Wrote faMesh in vtk format: " << writer.output().name() << nl;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// finiteArea - edgeCentres
|
||||||
|
// (no other convenient way to display vectors on the edges)
|
||||||
|
vtk::lineWriter writer
|
||||||
|
(
|
||||||
|
aMesh.edgeCentres(),
|
||||||
|
edgeList::null(),
|
||||||
|
// vtk::formatType::INLINE_ASCII,
|
||||||
|
fileName
|
||||||
|
(
|
||||||
|
aMesh.mesh().time().globalPath() / "finiteArea-edgesCentres"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
writer.writeGeometry();
|
||||||
|
|
||||||
|
// PointData
|
||||||
|
writer.beginPointData(4);
|
||||||
|
{
|
||||||
|
// Use primitive patch order
|
||||||
|
Field<vector> fld
|
||||||
|
(
|
||||||
|
faMeshTools::flattenEdgeField(aMesh.Le(), true)
|
||||||
|
);
|
||||||
|
writer.write("Le", fld);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// Use primitive patch order
|
||||||
|
Field<vector> fld
|
||||||
|
(
|
||||||
|
faMeshTools::flattenEdgeField(aMesh.edgeAreaNormals(), true)
|
||||||
|
);
|
||||||
|
writer.write("normal", fld);
|
||||||
|
}
|
||||||
|
|
||||||
|
Info<< nl
|
||||||
|
<< "Wrote faMesh in vtk format: " << writer.output().name() << nl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
// ************************************************************************* //
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2021 OpenCFD Ltd.
|
Copyright (C) 2021-2022 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
|
This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
|
||||||
@ -20,24 +20,7 @@ Description
|
|||||||
const label nNonProcessor = patches.nNonProcessor();
|
const label nNonProcessor = patches.nNonProcessor();
|
||||||
const label nPatches = patches.size();
|
const label nPatches = patches.size();
|
||||||
|
|
||||||
Info<< "----------------" << nl
|
label nLocalProcEdges = 0;
|
||||||
<< "Mesh Information" << nl
|
|
||||||
<< "----------------" << nl
|
|
||||||
<< " " << "boundingBox: " << boundBox(aMesh.points()) << nl;
|
|
||||||
|
|
||||||
Info<< " Number of points: "
|
|
||||||
<< returnReduce(aMesh.nPoints(), sumOp<label>()) << nl
|
|
||||||
<< " Number of faces: "
|
|
||||||
<< returnReduce(aMesh.nFaces(), sumOp<label>()) << nl;
|
|
||||||
|
|
||||||
Info<< " Number of edges: "
|
|
||||||
<< returnReduce(aMesh.nEdges(), sumOp<label>()) << nl
|
|
||||||
<< " Number of internal edges: "
|
|
||||||
<< returnReduce(aMesh.nInternalEdges(), sumOp<label>()) << nl;
|
|
||||||
|
|
||||||
|
|
||||||
label nProcEdges = 0;
|
|
||||||
|
|
||||||
if (Pstream::parRun())
|
if (Pstream::parRun())
|
||||||
{
|
{
|
||||||
for (const faPatch& fap : patches)
|
for (const faPatch& fap : patches)
|
||||||
@ -46,22 +29,84 @@ Description
|
|||||||
|
|
||||||
if (cpp)
|
if (cpp)
|
||||||
{
|
{
|
||||||
nProcEdges += fap.nEdges();
|
nLocalProcEdges += fap.nEdges();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const label nBoundEdges = aMesh.nBoundaryEdges() - nProcEdges;
|
const labelList nFaces
|
||||||
|
(
|
||||||
|
UPstream::listGatherValues<label>(aMesh.nFaces())
|
||||||
|
);
|
||||||
|
const labelList nPoints
|
||||||
|
(
|
||||||
|
UPstream::listGatherValues<label>(aMesh.nPoints())
|
||||||
|
);
|
||||||
|
const labelList nEdges
|
||||||
|
(
|
||||||
|
UPstream::listGatherValues<label>(aMesh.nEdges())
|
||||||
|
);
|
||||||
|
const labelList nIntEdges
|
||||||
|
(
|
||||||
|
UPstream::listGatherValues<label>(aMesh.nInternalEdges())
|
||||||
|
);
|
||||||
|
|
||||||
Info<< " Number of boundary edges: "
|
// The "real" (non-processor) boundary edges
|
||||||
<< returnReduce(nBoundEdges - nProcEdges, sumOp<label>()) << nl;
|
const labelList nBndEdges
|
||||||
|
(
|
||||||
|
UPstream::listGatherValues<label>
|
||||||
|
(
|
||||||
|
aMesh.nBoundaryEdges() - nLocalProcEdges
|
||||||
|
)
|
||||||
|
);
|
||||||
|
const labelList nProcEdges
|
||||||
|
(
|
||||||
|
UPstream::listGatherValues<label>(nLocalProcEdges)
|
||||||
|
);
|
||||||
|
|
||||||
if (Pstream::parRun())
|
|
||||||
|
// Format output as
|
||||||
|
// Number of faces: ...
|
||||||
|
// per-proc: (...)
|
||||||
|
|
||||||
|
const auto reporter =
|
||||||
|
[&](const char* tag, const labelList& list)
|
||||||
|
{
|
||||||
|
Info<< " Number of " << tag << ": " << sum(list) << nl;
|
||||||
|
if (Pstream::parRun())
|
||||||
|
{
|
||||||
|
int padding = static_cast<int>
|
||||||
|
(
|
||||||
|
// strlen(" Number of ") - strlen("per-proc")
|
||||||
|
(12 - 8)
|
||||||
|
+ strlen(tag)
|
||||||
|
);
|
||||||
|
|
||||||
|
do { Info<< ' '; } while (--padding > 0);
|
||||||
|
|
||||||
|
Info<< "per-proc: " << flatOutput(list) << nl;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Info<< "----------------" << nl
|
||||||
|
<< "Mesh Information" << nl
|
||||||
|
<< "----------------" << nl
|
||||||
|
<< " " << "boundingBox: " << boundBox(aMesh.points()) << nl;
|
||||||
|
|
||||||
|
if (Pstream::master())
|
||||||
{
|
{
|
||||||
Info<< " Number of processor edges: "
|
reporter("faces", nFaces);
|
||||||
<< returnReduce(nProcEdges, sumOp<label>()) << nl;
|
reporter("points", nPoints);
|
||||||
}
|
reporter("edges", nEdges);
|
||||||
|
reporter("internal edges", nIntEdges);
|
||||||
|
reporter("boundary edges", nBndEdges);
|
||||||
|
|
||||||
|
if (Pstream::parRun())
|
||||||
|
{
|
||||||
|
reporter("processor edges", nProcEdges);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Info<< "----------------" << nl
|
Info<< "----------------" << nl
|
||||||
<< "Patches" << nl
|
<< "Patches" << nl
|
||||||
|
|||||||
@ -9,6 +9,10 @@ faMesh/faMeshBoundaryHalo.C
|
|||||||
faMesh/faBoundaryMesh/faBoundaryMesh.C
|
faMesh/faBoundaryMesh/faBoundaryMesh.C
|
||||||
faMesh/faBoundaryMesh/faBoundaryMeshEntries.C
|
faMesh/faBoundaryMesh/faBoundaryMeshEntries.C
|
||||||
|
|
||||||
|
faMesh/faMeshSubset/faMeshSubset.C
|
||||||
|
faMesh/faMeshTools/faMeshTools.C
|
||||||
|
faMesh/faMeshTools/faMeshToolsProcAddr.C
|
||||||
|
|
||||||
faPatches = faMesh/faPatches
|
faPatches = faMesh/faPatches
|
||||||
$(faPatches)/faPatch/faPatch.C
|
$(faPatches)/faPatch/faPatch.C
|
||||||
$(faPatches)/faPatch/faPatchData.C
|
$(faPatches)/faPatch/faPatchData.C
|
||||||
|
|||||||
@ -235,6 +235,22 @@ void Foam::faBoundaryMesh::calcGeometry()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::UPtrList<const Foam::labelUList>
|
||||||
|
Foam::faBoundaryMesh::edgeLabels() const
|
||||||
|
{
|
||||||
|
const faPatchList& patches = *this;
|
||||||
|
|
||||||
|
UPtrList<const labelUList> list(patches.size());
|
||||||
|
|
||||||
|
forAll(list, patchi)
|
||||||
|
{
|
||||||
|
list.set(patchi, &patches[patchi].edgeLabels());
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Foam::UPtrList<const Foam::labelUList>
|
Foam::UPtrList<const Foam::labelUList>
|
||||||
Foam::faBoundaryMesh::edgeFaces() const
|
Foam::faBoundaryMesh::edgeFaces() const
|
||||||
{
|
{
|
||||||
|
|||||||
@ -132,6 +132,9 @@ public:
|
|||||||
return mesh_;
|
return mesh_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//- Return a list of edgeLabels for each patch
|
||||||
|
UPtrList<const labelUList> edgeLabels() const;
|
||||||
|
|
||||||
//- Return a list of edgeFaces for each patch
|
//- Return a list of edgeFaces for each patch
|
||||||
UPtrList<const labelUList> edgeFaces() const;
|
UPtrList<const labelUList> edgeFaces() const;
|
||||||
|
|
||||||
|
|||||||
@ -337,10 +337,12 @@ Foam::faMesh::faMesh
|
|||||||
*this
|
*this
|
||||||
),
|
),
|
||||||
comm_(Pstream::worldComm),
|
comm_(Pstream::worldComm),
|
||||||
|
curTimeIndex_(time().timeIndex()),
|
||||||
|
|
||||||
patchPtr_(nullptr),
|
patchPtr_(nullptr),
|
||||||
bndConnectPtr_(nullptr),
|
bndConnectPtr_(nullptr),
|
||||||
lduPtr_(nullptr),
|
lduPtr_(nullptr),
|
||||||
curTimeIndex_(time().timeIndex()),
|
|
||||||
SPtr_(nullptr),
|
SPtr_(nullptr),
|
||||||
S0Ptr_(nullptr),
|
S0Ptr_(nullptr),
|
||||||
S00Ptr_(nullptr),
|
S00Ptr_(nullptr),
|
||||||
@ -439,10 +441,12 @@ Foam::faMesh::faMesh
|
|||||||
label(0)
|
label(0)
|
||||||
),
|
),
|
||||||
comm_(Pstream::worldComm),
|
comm_(Pstream::worldComm),
|
||||||
|
curTimeIndex_(time().timeIndex()),
|
||||||
|
|
||||||
patchPtr_(nullptr),
|
patchPtr_(nullptr),
|
||||||
bndConnectPtr_(nullptr),
|
bndConnectPtr_(nullptr),
|
||||||
lduPtr_(nullptr),
|
lduPtr_(nullptr),
|
||||||
curTimeIndex_(time().timeIndex()),
|
|
||||||
SPtr_(nullptr),
|
SPtr_(nullptr),
|
||||||
S0Ptr_(nullptr),
|
S0Ptr_(nullptr),
|
||||||
S00Ptr_(nullptr),
|
S00Ptr_(nullptr),
|
||||||
|
|||||||
@ -209,37 +209,43 @@ class faMesh
|
|||||||
faBoundaryMesh boundary_;
|
faBoundaryMesh boundary_;
|
||||||
|
|
||||||
|
|
||||||
// Primitive mesh data
|
// Primitive mesh data
|
||||||
|
|
||||||
//- Edges, addressing into local point list
|
//- Edges, addressing into local point list
|
||||||
edgeList edges_;
|
edgeList edges_;
|
||||||
|
|
||||||
//- Edge owner
|
//- Edge owner
|
||||||
labelList edgeOwner_;
|
labelList edgeOwner_;
|
||||||
|
|
||||||
//- Edge neighbour
|
//- Edge neighbour
|
||||||
labelList edgeNeighbour_;
|
labelList edgeNeighbour_;
|
||||||
|
|
||||||
|
|
||||||
// Primitive size data
|
// Primitive size data
|
||||||
|
|
||||||
//- Total number of points
|
//- Total number of points
|
||||||
mutable label nPoints_;
|
mutable label nPoints_;
|
||||||
|
|
||||||
//- Total number of edges
|
//- Total number of edges
|
||||||
mutable label nEdges_;
|
mutable label nEdges_;
|
||||||
|
|
||||||
//- Number of internal edges
|
//- Number of internal edges
|
||||||
mutable label nInternalEdges_;
|
mutable label nInternalEdges_;
|
||||||
|
|
||||||
//- Number of faces
|
//- Number of faces
|
||||||
mutable label nFaces_;
|
mutable label nFaces_;
|
||||||
|
|
||||||
|
|
||||||
// Communication support
|
// Communication support, updating
|
||||||
|
|
||||||
//- Communicator used for parallel communication
|
//- Communicator used for parallel communication
|
||||||
label comm_;
|
label comm_;
|
||||||
|
|
||||||
|
//- Current time index for motion
|
||||||
|
// Note. The whole mechanism will be replaced once the
|
||||||
|
// dimensionedField is created and the dimensionedField
|
||||||
|
// will take care of the old-time levels.
|
||||||
|
mutable label curTimeIndex_;
|
||||||
|
|
||||||
|
|
||||||
// Demand-driven data
|
// Demand-driven data
|
||||||
@ -253,11 +259,8 @@ class faMesh
|
|||||||
//- Ldu addressing data
|
//- Ldu addressing data
|
||||||
mutable faMeshLduAddressing* lduPtr_;
|
mutable faMeshLduAddressing* lduPtr_;
|
||||||
|
|
||||||
//- Current time index for motion
|
|
||||||
// Note. The whole mechanism will be replaced once the
|
// Geometric Data
|
||||||
// dimensionedField is created and the dimensionedField
|
|
||||||
// will take care of the old-time levels.
|
|
||||||
mutable label curTimeIndex_;
|
|
||||||
|
|
||||||
//- Face areas
|
//- Face areas
|
||||||
mutable DimensionedField<scalar, areaMesh>* SPtr_;
|
mutable DimensionedField<scalar, areaMesh>* SPtr_;
|
||||||
@ -545,6 +548,22 @@ public:
|
|||||||
|
|
||||||
// Static Functions
|
// Static Functions
|
||||||
|
|
||||||
|
//- Return the current geometry treatment (0: primitive, 1: standard)
|
||||||
|
// A zero level is with restricted neighbour information
|
||||||
|
static int geometryOrder() noexcept
|
||||||
|
{
|
||||||
|
return geometryOrder_;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Set the preferred geometry treatment
|
||||||
|
// \return the previous value
|
||||||
|
static int geometryOrder(const int order) noexcept
|
||||||
|
{
|
||||||
|
int old(geometryOrder_);
|
||||||
|
geometryOrder_ = order;
|
||||||
|
return old;
|
||||||
|
}
|
||||||
|
|
||||||
//- Read construction from polyMesh if all files are available
|
//- Read construction from polyMesh if all files are available
|
||||||
static autoPtr<faMesh> TryNew(const polyMesh& pMesh);
|
static autoPtr<faMesh> TryNew(const polyMesh& pMesh);
|
||||||
|
|
||||||
@ -571,73 +590,79 @@ public:
|
|||||||
bool init(const bool doInit);
|
bool init(const bool doInit);
|
||||||
|
|
||||||
|
|
||||||
// Database
|
// Database
|
||||||
|
|
||||||
//- Return access to polyMesh
|
//- Return access to polyMesh
|
||||||
inline const polyMesh& mesh() const;
|
inline const polyMesh& mesh() const;
|
||||||
|
|
||||||
//- Interface to referenced polyMesh (similar to GeoMesh)
|
//- Interface to referenced polyMesh (similar to GeoMesh)
|
||||||
const polyMesh& operator()() const { return mesh(); }
|
const polyMesh& operator()() const { return mesh(); }
|
||||||
|
|
||||||
//- Return the local mesh directory (dbDir()/meshSubDir)
|
//- Return the local mesh directory (dbDir()/meshSubDir)
|
||||||
fileName meshDir() const;
|
fileName meshDir() const;
|
||||||
|
|
||||||
//- Return reference to time
|
//- Return reference to time
|
||||||
const Time& time() const;
|
const Time& time() const;
|
||||||
|
|
||||||
//- Return the current instance directory for points
|
//- Return the current instance directory for points
|
||||||
// Used in the construction of geometric mesh data dependent
|
// Used in the construction of geometric mesh data dependent
|
||||||
// on points
|
// on points
|
||||||
const fileName& pointsInstance() const;
|
const fileName& pointsInstance() const;
|
||||||
|
|
||||||
//- Return the current instance directory for faces
|
//- Return the current instance directory for faces
|
||||||
const fileName& facesInstance() const;
|
const fileName& facesInstance() const;
|
||||||
|
|
||||||
|
|
||||||
// Communication support
|
// Communication support
|
||||||
|
|
||||||
//- Return communicator used for parallel communication
|
//- Return communicator used for parallel communication
|
||||||
inline label comm() const noexcept;
|
inline label comm() const noexcept;
|
||||||
|
|
||||||
//- Return communicator used for parallel communication
|
//- Return communicator used for parallel communication
|
||||||
inline label& comm() noexcept;
|
inline label& comm() noexcept;
|
||||||
|
|
||||||
|
|
||||||
// Mesh size parameters
|
// Access: Mesh size parameters
|
||||||
|
|
||||||
//- Number of local mesh points
|
//- Number of local mesh points
|
||||||
inline label nPoints() const noexcept;
|
inline label nPoints() const noexcept;
|
||||||
|
|
||||||
//- Number of local mesh edges
|
//- Number of local mesh edges
|
||||||
inline label nEdges() const noexcept;
|
inline label nEdges() const noexcept;
|
||||||
|
|
||||||
//- Number of internal faces
|
//- Number of internal faces
|
||||||
inline label nInternalEdges() const noexcept;
|
inline label nInternalEdges() const noexcept;
|
||||||
|
|
||||||
//- Number of boundary edges (== nEdges - nInternalEdges)
|
//- Number of boundary edges (== nEdges - nInternalEdges)
|
||||||
inline label nBoundaryEdges() const noexcept;
|
inline label nBoundaryEdges() const noexcept;
|
||||||
|
|
||||||
//- Number of patch faces
|
//- Number of patch faces
|
||||||
inline label nFaces() const noexcept;
|
inline label nFaces() const noexcept;
|
||||||
|
|
||||||
|
|
||||||
// Primitive mesh data
|
// Access: Primitive mesh data
|
||||||
|
|
||||||
//- Return local patch points
|
//- Return local points
|
||||||
inline const pointField& points() const;
|
inline const pointField& points() const;
|
||||||
|
|
||||||
//- Return local patch edges with reordered boundary
|
//- Return local edges with reordered boundary
|
||||||
inline const edgeList& edges() const noexcept;
|
inline const edgeList& edges() const noexcept;
|
||||||
|
|
||||||
//- Return local patch faces
|
//- Sub-list of local internal edges
|
||||||
inline const faceList& faces() const;
|
inline const edgeList::subList internalEdges() const;
|
||||||
|
|
||||||
//- Edge owner addressing
|
//- Return local faces
|
||||||
inline const labelList& edgeOwner() const noexcept;
|
inline const faceList& faces() const;
|
||||||
|
|
||||||
//- Edge neighbour addressing
|
//- Edge owner addressing
|
||||||
inline const labelList& edgeNeighbour() const noexcept;
|
inline const labelList& edgeOwner() const noexcept;
|
||||||
|
|
||||||
|
//- Edge neighbour addressing
|
||||||
|
inline const labelList& edgeNeighbour() const noexcept;
|
||||||
|
|
||||||
|
//- True if the internalEdges use an ordering that does not
|
||||||
|
//- correspond 1-to-1 with the patch internalEdges.
|
||||||
|
inline bool hasInternalEdgeLabels() const noexcept;
|
||||||
|
|
||||||
|
|
||||||
// Access
|
// Access
|
||||||
@ -649,7 +674,7 @@ public:
|
|||||||
virtual const objectRegistry& thisDb() const;
|
virtual const objectRegistry& thisDb() const;
|
||||||
|
|
||||||
//- Name function is needed to disambiguate those inherited
|
//- Name function is needed to disambiguate those inherited
|
||||||
// from base classes
|
//- from base classes
|
||||||
const word& name() const
|
const word& name() const
|
||||||
{
|
{
|
||||||
return thisDb().name();
|
return thisDb().name();
|
||||||
@ -688,7 +713,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
//- True if given edge label is internal to the mesh
|
//- True if given edge label is internal to the mesh
|
||||||
bool isInternalEdge(const label edgeIndex) const
|
bool isInternalEdge(const label edgeIndex) const noexcept
|
||||||
{
|
{
|
||||||
return (edgeIndex < nInternalEdges_);
|
return (edgeIndex < nInternalEdges_);
|
||||||
}
|
}
|
||||||
@ -817,6 +842,9 @@ public:
|
|||||||
boolList& correctPatchPointNormals() const;
|
boolList& correctPatchPointNormals() const;
|
||||||
|
|
||||||
|
|
||||||
|
// Storage management
|
||||||
|
|
||||||
|
|
||||||
//- Write mesh
|
//- Write mesh
|
||||||
virtual bool write(const bool valid = true) const;
|
virtual bool write(const bool valid = true) const;
|
||||||
|
|
||||||
|
|||||||
@ -37,6 +37,7 @@ License
|
|||||||
#include "scalarMatrices.H"
|
#include "scalarMatrices.H"
|
||||||
#include "processorFaPatchFields.H"
|
#include "processorFaPatchFields.H"
|
||||||
#include "emptyFaPatchFields.H"
|
#include "emptyFaPatchFields.H"
|
||||||
|
#include "triPointRef.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -102,6 +103,121 @@ static inline vector areaInvDistSqrWeightedNormalDualEdge
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Calculate transform tensor with reference vector (unitAxis1)
|
||||||
|
// and direction vector (axis2).
|
||||||
|
//
|
||||||
|
// This is nearly identical to the meshTools axesRotation
|
||||||
|
// with an E3_E1 transformation with the following exceptions:
|
||||||
|
//
|
||||||
|
// - axis1 (e3 == unitAxis1): is already normalized (unit vector)
|
||||||
|
// - axis2 (e1 == dirn): no difference
|
||||||
|
// - transformation is row-vectors, not column-vectors
|
||||||
|
static inline tensor rotation_e3e1
|
||||||
|
(
|
||||||
|
const vector& unitAxis1,
|
||||||
|
vector dirn
|
||||||
|
)
|
||||||
|
{
|
||||||
|
dirn.removeCollinear(unitAxis1);
|
||||||
|
dirn.normalise();
|
||||||
|
|
||||||
|
// Set row vectors
|
||||||
|
return tensor
|
||||||
|
(
|
||||||
|
dirn,
|
||||||
|
(unitAxis1^dirn),
|
||||||
|
unitAxis1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Simple area-weighted normal calculation for the specified edge vector
|
||||||
|
// and its owner/neighbour face centres (internal edges).
|
||||||
|
//
|
||||||
|
// Uses four triangles since adjacent faces may be non-planar
|
||||||
|
// and/or the edge centre is skewed from the face centres.
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
* * |
|
||||||
|
* /|\ | Triangles (0,1) are on the owner side.
|
||||||
|
* / | \ |
|
||||||
|
* / | \ | Triangles (2,3) are on the neighbour side.
|
||||||
|
* / 1|3 \ |
|
||||||
|
* own *----|----* nbr | Boundary edges are the same, but without a neighbour
|
||||||
|
* \ 0|2 / |
|
||||||
|
* \ | / |
|
||||||
|
* \ | / |
|
||||||
|
* \|/ |
|
||||||
|
* * |
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static inline vector calcEdgeNormalFromFace
|
||||||
|
(
|
||||||
|
const linePointRef& edgeVec,
|
||||||
|
const point& ownCentre,
|
||||||
|
const point& neiCentre
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const scalar magEdge(edgeVec.mag());
|
||||||
|
|
||||||
|
if (magEdge < ROOTVSMALL)
|
||||||
|
{
|
||||||
|
return Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
const vector edgeCtr = edgeVec.centre();
|
||||||
|
|
||||||
|
vector edgeNorm
|
||||||
|
(
|
||||||
|
// owner
|
||||||
|
triPointRef(edgeCtr, ownCentre, edgeVec.first()).areaNormal()
|
||||||
|
+ triPointRef(edgeCtr, edgeVec.last(), ownCentre).areaNormal()
|
||||||
|
// neighbour
|
||||||
|
+ triPointRef(edgeCtr, edgeVec.first(), neiCentre).areaNormal()
|
||||||
|
+ triPointRef(edgeCtr, neiCentre, edgeVec.last()).areaNormal()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Requires a unit-vector (already tested its mag)
|
||||||
|
edgeNorm.removeCollinear(edgeVec.vec()/magEdge);
|
||||||
|
edgeNorm.normalise();
|
||||||
|
|
||||||
|
// Scale with the original edge length
|
||||||
|
return magEdge*edgeNorm;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// As above, but for boundary edgess (no neighbour)
|
||||||
|
static inline vector calcEdgeNormalFromFace
|
||||||
|
(
|
||||||
|
const linePointRef& edgeVec,
|
||||||
|
const point& ownCentre
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const scalar magEdge(edgeVec.mag());
|
||||||
|
|
||||||
|
if (magEdge < ROOTVSMALL)
|
||||||
|
{
|
||||||
|
return Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
const vector edgeCtr = edgeVec.centre();
|
||||||
|
|
||||||
|
vector edgeNorm
|
||||||
|
(
|
||||||
|
// owner
|
||||||
|
triPointRef(edgeCtr, ownCentre, edgeVec.first()).areaNormal()
|
||||||
|
+ triPointRef(edgeCtr, edgeVec.last(), ownCentre).areaNormal()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Requires a unit-vector (already tested its mag)
|
||||||
|
edgeNorm.removeCollinear(edgeVec.vec()/magEdge);
|
||||||
|
edgeNorm.normalise();
|
||||||
|
|
||||||
|
// Scale with the original edge length
|
||||||
|
return magEdge*edgeNorm;
|
||||||
|
}
|
||||||
|
|
||||||
} // End namespace Foam
|
} // End namespace Foam
|
||||||
|
|
||||||
|
|
||||||
@ -189,71 +305,187 @@ void Foam::faMesh::calcLe() const
|
|||||||
|
|
||||||
edgeVectorField& Le = *LePtr_;
|
edgeVectorField& Le = *LePtr_;
|
||||||
|
|
||||||
|
const pointField& localPoints = points();
|
||||||
|
|
||||||
const pointField& pPoints = points();
|
if (faMesh::geometryOrder() < 1)
|
||||||
const edgeList& pEdges = edges();
|
{
|
||||||
|
// Simple (primitive) edge normal calculations.
|
||||||
|
// These are primarly designed to avoid any communication
|
||||||
|
// but are thus necessarily inconsistent across processor boundaries!
|
||||||
|
|
||||||
|
// Reasonable to assume that the volume mesh already has faceCentres
|
||||||
|
// eg, used magSf somewhere.
|
||||||
|
// Can use these instead of triggering our calcAreaCentres().
|
||||||
|
|
||||||
|
WarningInFunction
|
||||||
|
<< "Using geometryOrder < 1 : "
|
||||||
|
"simplified edge area-normals for Le() calculation"
|
||||||
|
<< endl;
|
||||||
|
|
||||||
|
UIndirectList<vector> fCentres(mesh().faceCentres(), faceLabels());
|
||||||
|
|
||||||
|
// Flat addressing
|
||||||
|
vectorField edgeNormals(nEdges_);
|
||||||
|
|
||||||
|
// Internal (edge normals)
|
||||||
|
for (label edgei = 0; edgei < nInternalEdges_; ++edgei)
|
||||||
|
{
|
||||||
|
edgeNormals[edgei] =
|
||||||
|
calcEdgeNormalFromFace
|
||||||
|
(
|
||||||
|
edges_[edgei].line(localPoints),
|
||||||
|
fCentres[owner()[edgei]],
|
||||||
|
fCentres[neighbour()[edgei]]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Boundary (edge normals). Like above, but only has owner
|
||||||
|
for (label edgei = nInternalEdges_; edgei < nEdges_; ++edgei)
|
||||||
|
{
|
||||||
|
edgeNormals[edgei] =
|
||||||
|
calcEdgeNormalFromFace
|
||||||
|
(
|
||||||
|
edges_[edgei].line(localPoints),
|
||||||
|
fCentres[owner()[edgei]]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Now use these edge normals for calculating Le
|
||||||
|
|
||||||
|
// Internal (edge vector)
|
||||||
|
{
|
||||||
|
vectorField& internalFld = Le.ref();
|
||||||
|
for (label edgei = 0; edgei < nInternalEdges_; ++edgei)
|
||||||
|
{
|
||||||
|
vector& leVector = internalFld[edgei];
|
||||||
|
|
||||||
|
vector edgeVec = edges_[edgei].vec(localPoints);
|
||||||
|
const scalar magEdge(mag(edgeVec));
|
||||||
|
|
||||||
|
if (magEdge < ROOTVSMALL)
|
||||||
|
{
|
||||||
|
// Too small
|
||||||
|
leVector = Zero;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const vector edgeCtr = edges_[edgei].centre(localPoints);
|
||||||
|
const vector& edgeNorm = edgeNormals[edgei];
|
||||||
|
const vector& ownCentre = fCentres[owner()[edgei]];
|
||||||
|
|
||||||
|
leVector = magEdge*normalised(edgeVec ^ edgeNorm);
|
||||||
|
leVector *= sign(leVector & (edgeCtr - ownCentre));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Boundary (edge vector)
|
||||||
|
|
||||||
|
forAll(boundary(), patchi)
|
||||||
|
{
|
||||||
|
const labelUList& bndEdgeFaces = boundary()[patchi].edgeFaces();
|
||||||
|
|
||||||
|
const edgeList::subList bndEdges =
|
||||||
|
boundary()[patchi].patchSlice(edges_);
|
||||||
|
|
||||||
|
vectorField& patchLe = Le.boundaryFieldRef()[patchi];
|
||||||
|
|
||||||
|
forAll(patchLe, bndEdgei)
|
||||||
|
{
|
||||||
|
vector& leVector = patchLe[bndEdgei];
|
||||||
|
const label meshEdgei(boundary()[patchi].start() + bndEdgei);
|
||||||
|
|
||||||
|
vector edgeVec = bndEdges[bndEdgei].vec(localPoints);
|
||||||
|
const scalar magEdge(mag(edgeVec));
|
||||||
|
|
||||||
|
if (magEdge < ROOTVSMALL)
|
||||||
|
{
|
||||||
|
// Too small
|
||||||
|
leVector = Zero;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const vector edgeCtr = bndEdges[bndEdgei].centre(localPoints);
|
||||||
|
const vector& edgeNorm = edgeNormals[meshEdgei];
|
||||||
|
const vector& ownCentre = fCentres[bndEdgeFaces[bndEdgei]];
|
||||||
|
|
||||||
|
leVector = magEdge*normalised(edgeVec ^ edgeNorm);
|
||||||
|
leVector *= sign(leVector & (edgeCtr - ownCentre));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Done
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Longer forms.
|
||||||
|
// Using edgeAreaNormals, which uses pointAreaNormals (communication!)
|
||||||
|
|
||||||
const edgeVectorField& eCentres = edgeCentres();
|
const edgeVectorField& eCentres = edgeCentres();
|
||||||
const areaVectorField& fCentres = areaCentres();
|
const areaVectorField& fCentres = areaCentres();
|
||||||
|
|
||||||
const edgeVectorField& edgeNormals = edgeAreaNormals();
|
const edgeVectorField& edgeNormals = edgeAreaNormals();
|
||||||
|
|
||||||
vectorField& leInternal = Le.ref();
|
// Internal (edge vector)
|
||||||
const vectorField& edgeNormalsInternal = edgeNormals.internalField();
|
|
||||||
const vectorField& fCentresInternal = fCentres.internalField();
|
|
||||||
const vectorField& eCentresInternal = eCentres.internalField();
|
|
||||||
const scalarField& magLeInternal = magLe().internalField();
|
|
||||||
|
|
||||||
forAll(leInternal, edgeI)
|
|
||||||
{
|
{
|
||||||
leInternal[edgeI] =
|
vectorField& internalFld = Le.ref();
|
||||||
pEdges[edgeI].vec(pPoints) ^ edgeNormalsInternal[edgeI];
|
for (label edgei = 0; edgei < nInternalEdges_; ++edgei)
|
||||||
|
{
|
||||||
|
vector& leVector = internalFld[edgei];
|
||||||
|
|
||||||
leInternal[edgeI] *=
|
vector edgeVec = edges_[edgei].vec(localPoints);
|
||||||
- sign
|
const scalar magEdge(mag(edgeVec));
|
||||||
(
|
|
||||||
leInternal[edgeI] &
|
|
||||||
(
|
|
||||||
fCentresInternal[owner()[edgeI]]
|
|
||||||
- eCentresInternal[edgeI]
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
leInternal[edgeI] *=
|
if (magEdge < ROOTVSMALL)
|
||||||
magLeInternal[edgeI]/mag(leInternal[edgeI]);
|
{
|
||||||
|
// Too small
|
||||||
|
leVector = Zero;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const vector& edgeCtr = eCentres[edgei];
|
||||||
|
const vector& edgeNorm = edgeNormals[edgei];
|
||||||
|
const vector& ownCentre = fCentres[owner()[edgei]];
|
||||||
|
|
||||||
|
leVector = magEdge*normalised(edgeVec ^ edgeNorm);
|
||||||
|
leVector *= sign(leVector & (edgeCtr - ownCentre));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
forAll(boundary(), patchI)
|
forAll(boundary(), patchi)
|
||||||
{
|
{
|
||||||
const labelUList& bndEdgeFaces = boundary()[patchI].edgeFaces();
|
const labelUList& bndEdgeFaces = boundary()[patchi].edgeFaces();
|
||||||
|
|
||||||
const edgeList::subList bndEdges =
|
const edgeList::subList bndEdges =
|
||||||
boundary()[patchI].patchSlice(pEdges);
|
boundary()[patchi].patchSlice(edges_);
|
||||||
|
|
||||||
const vectorField& bndEdgeNormals =
|
const vectorField& bndEdgeNormals =
|
||||||
edgeNormals.boundaryField()[patchI];
|
edgeNormals.boundaryField()[patchi];
|
||||||
|
|
||||||
vectorField& patchLe = Le.boundaryFieldRef()[patchI];
|
vectorField& patchLe = Le.boundaryFieldRef()[patchi];
|
||||||
const vectorField& patchECentres = eCentres.boundaryField()[patchI];
|
const vectorField& patchECentres = eCentres.boundaryField()[patchi];
|
||||||
|
|
||||||
forAll(patchLe, edgeI)
|
forAll(patchLe, bndEdgei)
|
||||||
{
|
{
|
||||||
patchLe[edgeI] =
|
vector& leVector = patchLe[bndEdgei];
|
||||||
bndEdges[edgeI].vec(pPoints) ^ bndEdgeNormals[edgeI];
|
|
||||||
|
|
||||||
patchLe[edgeI] *=
|
vector edgeVec = bndEdges[bndEdgei].vec(localPoints);
|
||||||
- sign
|
const scalar magEdge(mag(edgeVec));
|
||||||
(
|
|
||||||
patchLe[edgeI]&
|
|
||||||
(
|
|
||||||
fCentresInternal[bndEdgeFaces[edgeI]]
|
|
||||||
- patchECentres[edgeI]
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
patchLe[edgeI] *=
|
if (magEdge < ROOTVSMALL)
|
||||||
magLe().boundaryField()[patchI][edgeI]
|
{
|
||||||
/mag(patchLe[edgeI]);
|
// Too small
|
||||||
|
leVector = Zero;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const vector& edgeCtr = patchECentres[bndEdgei];
|
||||||
|
const vector& edgeNorm = bndEdgeNormals[bndEdgei];
|
||||||
|
const vector& ownCentre = fCentres[bndEdgeFaces[bndEdgei]];
|
||||||
|
|
||||||
|
leVector = magEdge*normalised(edgeVec ^ edgeNorm);
|
||||||
|
leVector *= sign(leVector & (edgeCtr - ownCentre));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -289,23 +521,30 @@ void Foam::faMesh::calcMagLe() const
|
|||||||
|
|
||||||
const pointField& localPoints = points();
|
const pointField& localPoints = points();
|
||||||
|
|
||||||
label edgei = 0;
|
// Internal (edge length)
|
||||||
for (const edge& e : patch().internalEdges())
|
|
||||||
{
|
{
|
||||||
magLe.ref()[edgei] = e.mag(localPoints);
|
auto iter = magLe.primitiveFieldRef().begin();
|
||||||
++edgei;
|
|
||||||
|
for (const edge& e : internalEdges())
|
||||||
|
{
|
||||||
|
*iter = e.mag(localPoints);
|
||||||
|
++iter;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Boundary (edge length)
|
||||||
forAll(boundary(), patchI)
|
|
||||||
{
|
{
|
||||||
const edgeList::subList patchEdges =
|
auto& bfld = magLe.boundaryFieldRef();
|
||||||
boundary()[patchI].patchSlice(edges());
|
|
||||||
|
|
||||||
forAll(patchEdges, edgeI)
|
forAll(boundary(), patchi)
|
||||||
{
|
{
|
||||||
magLe.boundaryFieldRef()[patchI][edgeI] =
|
auto iter = bfld[patchi].begin();
|
||||||
patchEdges[edgeI].mag(localPoints);
|
|
||||||
|
for (const edge& e : boundary()[patchi].patchSlice(edges_))
|
||||||
|
{
|
||||||
|
*iter = e.mag(localPoints);
|
||||||
|
++iter;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -343,21 +582,25 @@ void Foam::faMesh::calcAreaCentres() const
|
|||||||
const faceList& localFaces = faces();
|
const faceList& localFaces = faces();
|
||||||
|
|
||||||
// Internal (face centres)
|
// Internal (face centres)
|
||||||
forAll(localFaces, faceI)
|
// Could also obtain from volume mesh faceCentres()
|
||||||
|
forAll(localFaces, facei)
|
||||||
{
|
{
|
||||||
centres.ref()[faceI] = localFaces[faceI].centre(localPoints);
|
centres.ref()[facei] = localFaces[facei].centre(localPoints);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Boundary (edge centres)
|
// Boundary (edge centres)
|
||||||
forAll(boundary(), patchI)
|
|
||||||
{
|
{
|
||||||
const edgeList::subList patchEdges =
|
auto& bfld = centres.boundaryFieldRef();
|
||||||
boundary()[patchI].patchSlice(edges());
|
|
||||||
|
|
||||||
forAll(patchEdges, edgeI)
|
forAll(boundary(), patchi)
|
||||||
{
|
{
|
||||||
centres.boundaryFieldRef()[patchI][edgeI] =
|
auto iter = bfld[patchi].begin();
|
||||||
patchEdges[edgeI].centre(localPoints);
|
|
||||||
|
for (const edge& e : boundary()[patchi].patchSlice(edges_))
|
||||||
|
{
|
||||||
|
*iter = e.centre(localPoints);
|
||||||
|
++iter;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -389,28 +632,34 @@ void Foam::faMesh::calcEdgeCentres() const
|
|||||||
dimLength
|
dimLength
|
||||||
);
|
);
|
||||||
|
|
||||||
edgeVectorField& edgeCentres = *edgeCentresPtr_;
|
edgeVectorField& centres = *edgeCentresPtr_;
|
||||||
|
|
||||||
const pointField& localPoints = points();
|
const pointField& localPoints = points();
|
||||||
|
|
||||||
// Internal edges
|
// Internal (edge centres)
|
||||||
label edgei = 0;
|
|
||||||
for (const edge& e : patch().internalEdges())
|
|
||||||
{
|
{
|
||||||
edgeCentres.ref()[edgei] = e.centre(localPoints);
|
auto iter = centres.primitiveFieldRef().begin();
|
||||||
++edgei;
|
|
||||||
|
for (const edge& e : internalEdges())
|
||||||
|
{
|
||||||
|
*iter = e.centre(localPoints);
|
||||||
|
++iter;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Boundary edges
|
// Boundary (edge centres)
|
||||||
forAll(boundary(), patchI)
|
|
||||||
{
|
{
|
||||||
const edgeList::subList patchEdges =
|
auto& bfld = centres.boundaryFieldRef();
|
||||||
boundary()[patchI].patchSlice(edges());
|
|
||||||
|
|
||||||
forAll(patchEdges, edgeI)
|
forAll(boundary(), patchi)
|
||||||
{
|
{
|
||||||
edgeCentres.boundaryFieldRef()[patchI][edgeI] =
|
auto iter = bfld[patchi].begin();
|
||||||
patchEdges[edgeI].centre(localPoints);
|
|
||||||
|
for (const edge& e : boundary()[patchi].patchSlice(edges_))
|
||||||
|
{
|
||||||
|
*iter = e.centre(localPoints);
|
||||||
|
++iter;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -446,9 +695,10 @@ void Foam::faMesh::calcS() const
|
|||||||
const pointField& localPoints = points();
|
const pointField& localPoints = points();
|
||||||
const faceList& localFaces = faces();
|
const faceList& localFaces = faces();
|
||||||
|
|
||||||
forAll(S, faceI)
|
// Could also obtain from volume mesh faceAreas()
|
||||||
|
forAll(S, facei)
|
||||||
{
|
{
|
||||||
S[faceI] = localFaces[faceI].mag(localPoints);
|
S[facei] = localFaces[facei].mag(localPoints);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -485,6 +735,7 @@ void Foam::faMesh::calcFaceAreaNormals() const
|
|||||||
const faceList& localFaces = faces();
|
const faceList& localFaces = faces();
|
||||||
|
|
||||||
// Internal (faces)
|
// Internal (faces)
|
||||||
|
// Could also obtain from volume mesh Sf() + normalise
|
||||||
vectorField& nInternal = faceNormals.ref();
|
vectorField& nInternal = faceNormals.ref();
|
||||||
forAll(localFaces, faceI)
|
forAll(localFaces, faceI)
|
||||||
{
|
{
|
||||||
@ -493,8 +744,7 @@ void Foam::faMesh::calcFaceAreaNormals() const
|
|||||||
|
|
||||||
// Boundary - copy from edges
|
// Boundary - copy from edges
|
||||||
|
|
||||||
const edgeVectorField::Boundary& edgeNormalsBoundary =
|
const auto& edgeNormalsBoundary = edgeAreaNormals().boundaryField();
|
||||||
edgeAreaNormals().boundaryField();
|
|
||||||
|
|
||||||
forAll(boundary(), patchI)
|
forAll(boundary(), patchI)
|
||||||
{
|
{
|
||||||
@ -528,46 +778,50 @@ void Foam::faMesh::calcEdgeAreaNormals() const
|
|||||||
*this,
|
*this,
|
||||||
dimless
|
dimless
|
||||||
);
|
);
|
||||||
|
|
||||||
edgeVectorField& edgeAreaNormals = *edgeAreaNormalsPtr_;
|
edgeVectorField& edgeAreaNormals = *edgeAreaNormalsPtr_;
|
||||||
|
|
||||||
|
|
||||||
// Point area normals
|
// Starting from point area normals
|
||||||
const vectorField& pointNormals = pointAreaNormals();
|
const vectorField& pointNormals = pointAreaNormals();
|
||||||
|
|
||||||
|
|
||||||
|
// Internal edges
|
||||||
forAll(edgeAreaNormals.internalField(), edgei)
|
forAll(edgeAreaNormals.internalField(), edgei)
|
||||||
{
|
{
|
||||||
const edge& e = edges()[edgei];
|
const edge& e = edges_[edgei];
|
||||||
const vector edgeVec = e.unitVec(points());
|
const vector edgeVec = e.unitVec(points());
|
||||||
|
|
||||||
vector& n = edgeAreaNormals.ref()[edgei];
|
vector& edgeNorm = edgeAreaNormals.ref()[edgei];
|
||||||
|
|
||||||
n = (pointNormals[e.first()] + pointNormals[e.second()]);
|
// Average of both ends
|
||||||
|
edgeNorm = (pointNormals[e.first()] + pointNormals[e.second()]);
|
||||||
|
|
||||||
n -= edgeVec*(edgeVec & n);
|
edgeNorm.removeCollinear(edgeVec);
|
||||||
|
edgeNorm.normalise();
|
||||||
n.normalise();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Boundary
|
||||||
|
auto& bfld = edgeAreaNormals.boundaryFieldRef();
|
||||||
|
|
||||||
forAll(boundary(), patchi)
|
forAll(boundary(), patchi)
|
||||||
{
|
{
|
||||||
|
auto& pfld = bfld[patchi];
|
||||||
|
|
||||||
const edgeList::subList patchEdges =
|
const edgeList::subList patchEdges =
|
||||||
boundary()[patchi].patchSlice(edges());
|
boundary()[patchi].patchSlice(edges_);
|
||||||
|
|
||||||
vectorField& edgeNorms = edgeAreaNormals.boundaryFieldRef()[patchi];
|
forAll(patchEdges, bndEdgei)
|
||||||
|
|
||||||
forAll(patchEdges, edgei)
|
|
||||||
{
|
{
|
||||||
const edge& e = patchEdges[edgei];
|
const edge& e = patchEdges[bndEdgei];
|
||||||
const vector edgeVec = e.unitVec(points());
|
const vector edgeVec = e.unitVec(points());
|
||||||
|
|
||||||
vector& n = edgeNorms[edgei];
|
vector& edgeNorm = pfld[bndEdgei];
|
||||||
|
|
||||||
n = (pointNormals[e.first()] + pointNormals[e.second()]);
|
// Average of both ends
|
||||||
|
edgeNorm = (pointNormals[e.first()] + pointNormals[e.second()]);
|
||||||
|
|
||||||
n -= edgeVec*(edgeVec & n);
|
edgeNorm.removeCollinear(edgeVec);
|
||||||
|
edgeNorm.normalise();
|
||||||
n.normalise();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -624,9 +878,14 @@ void Foam::faMesh::calcEdgeTransformTensors() const
|
|||||||
<< abort(FatalError);
|
<< abort(FatalError);
|
||||||
}
|
}
|
||||||
|
|
||||||
edgeTransformTensorsPtr_ = new FieldField<Field, tensor>(nEdges());
|
edgeTransformTensorsPtr_ = new FieldField<Field, tensor>(nEdges_);
|
||||||
FieldField<Field, tensor>& edgeTransformTensors =
|
auto& edgeTransformTensors = *edgeTransformTensorsPtr_;
|
||||||
*edgeTransformTensorsPtr_;
|
|
||||||
|
// Initialize all transformation tensors
|
||||||
|
for (label edgei = 0; edgei < nEdges_; ++edgei)
|
||||||
|
{
|
||||||
|
edgeTransformTensors.set(edgei, new Field<tensor>(3, tensor::I));
|
||||||
|
}
|
||||||
|
|
||||||
const areaVectorField& Nf = faceAreaNormals();
|
const areaVectorField& Nf = faceAreaNormals();
|
||||||
const areaVectorField& Cf = areaCentres();
|
const areaVectorField& Cf = areaCentres();
|
||||||
@ -635,193 +894,129 @@ void Foam::faMesh::calcEdgeTransformTensors() const
|
|||||||
const edgeVectorField& Ce = edgeCentres();
|
const edgeVectorField& Ce = edgeCentres();
|
||||||
|
|
||||||
// Internal edges transformation tensors
|
// Internal edges transformation tensors
|
||||||
for (label edgeI=0; edgeI<nInternalEdges(); ++edgeI)
|
for (label edgei = 0; edgei < nInternalEdges_; ++edgei)
|
||||||
{
|
{
|
||||||
edgeTransformTensors.set(edgeI, new Field<tensor>(3, I));
|
const label ownFacei = owner()[edgei];
|
||||||
|
const label neiFacei = neighbour()[edgei];
|
||||||
|
auto& tensors = edgeTransformTensors[edgei];
|
||||||
|
|
||||||
vector E = Ce.internalField()[edgeI];
|
vector edgeCtr = Ce.internalField()[edgei];
|
||||||
|
|
||||||
if (skew())
|
if (skew())
|
||||||
{
|
{
|
||||||
E -= skewCorrectionVectors().internalField()[edgeI];
|
edgeCtr -= skewCorrectionVectors().internalField()[edgei];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Edge transformation tensor
|
// Edge transformation tensor
|
||||||
vector il = E - Cf.internalField()[owner()[edgeI]];
|
tensors[0] =
|
||||||
|
rotation_e3e1
|
||||||
il -= Ne.internalField()[edgeI]
|
|
||||||
*(Ne.internalField()[edgeI]&il);
|
|
||||||
|
|
||||||
il /= mag(il);
|
|
||||||
|
|
||||||
vector kl = Ne.internalField()[edgeI];
|
|
||||||
vector jl = kl^il;
|
|
||||||
|
|
||||||
edgeTransformTensors[edgeI][0] =
|
|
||||||
tensor
|
|
||||||
(
|
(
|
||||||
il.x(), il.y(), il.z(),
|
Ne.internalField()[edgei],
|
||||||
jl.x(), jl.y(), jl.z(),
|
(edgeCtr - Cf.internalField()[ownFacei])
|
||||||
kl.x(), kl.y(), kl.z()
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Owner transformation tensor
|
// Owner transformation tensor
|
||||||
il = E - Cf.internalField()[owner()[edgeI]];
|
tensors[1] =
|
||||||
|
rotation_e3e1
|
||||||
il -= Nf.internalField()[owner()[edgeI]]
|
|
||||||
*(Nf.internalField()[owner()[edgeI]]&il);
|
|
||||||
|
|
||||||
il /= mag(il);
|
|
||||||
|
|
||||||
kl = Nf.internalField()[owner()[edgeI]];
|
|
||||||
jl = kl^il;
|
|
||||||
|
|
||||||
edgeTransformTensors[edgeI][1] =
|
|
||||||
tensor
|
|
||||||
(
|
(
|
||||||
il.x(), il.y(), il.z(),
|
Nf.internalField()[ownFacei],
|
||||||
jl.x(), jl.y(), jl.z(),
|
(edgeCtr - Cf.internalField()[ownFacei])
|
||||||
kl.x(), kl.y(), kl.z()
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Neighbour transformation tensor
|
// Neighbour transformation tensor
|
||||||
il = Cf.internalField()[neighbour()[edgeI]] - E;
|
tensors[2] =
|
||||||
|
rotation_e3e1
|
||||||
il -= Nf.internalField()[neighbour()[edgeI]]
|
|
||||||
*(Nf.internalField()[neighbour()[edgeI]]&il);
|
|
||||||
|
|
||||||
il /= mag(il);
|
|
||||||
|
|
||||||
kl = Nf.internalField()[neighbour()[edgeI]];
|
|
||||||
jl = kl^il;
|
|
||||||
|
|
||||||
edgeTransformTensors[edgeI][2] =
|
|
||||||
tensor
|
|
||||||
(
|
(
|
||||||
il.x(), il.y(), il.z(),
|
Nf.internalField()[neiFacei],
|
||||||
jl.x(), jl.y(), jl.z(),
|
(Cf.internalField()[neiFacei] - edgeCtr)
|
||||||
kl.x(), kl.y(), kl.z()
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Boundary edges transformation tensors
|
// Boundary edges transformation tensors
|
||||||
forAll(boundary(), patchI)
|
forAll(boundary(), patchi)
|
||||||
{
|
{
|
||||||
if (boundary()[patchI].coupled())
|
const labelUList& edgeFaces = boundary()[patchi].edgeFaces();
|
||||||
|
|
||||||
|
if (boundary()[patchi].coupled())
|
||||||
{
|
{
|
||||||
const labelUList& edgeFaces =
|
vectorField nbrCf(Cf.boundaryField()[patchi].patchNeighbourField());
|
||||||
boundary()[patchI].edgeFaces();
|
vectorField nbrNf(Nf.boundaryField()[patchi].patchNeighbourField());
|
||||||
|
|
||||||
vectorField ngbCf(Cf.boundaryField()[patchI].patchNeighbourField());
|
forAll(edgeFaces, bndEdgei)
|
||||||
|
|
||||||
vectorField ngbNf(Nf.boundaryField()[patchI].patchNeighbourField());
|
|
||||||
|
|
||||||
forAll(edgeFaces, edgeI)
|
|
||||||
{
|
{
|
||||||
edgeTransformTensors.set
|
const label ownFacei = edgeFaces[bndEdgei];
|
||||||
(
|
const label meshEdgei(boundary()[patchi].start() + bndEdgei);
|
||||||
boundary()[patchI].start() + edgeI,
|
|
||||||
new Field<tensor>(3, I)
|
|
||||||
);
|
|
||||||
|
|
||||||
vector E = Ce.boundaryField()[patchI][edgeI];
|
auto& tensors = edgeTransformTensors[meshEdgei];
|
||||||
|
|
||||||
|
vector edgeCtr = Ce.boundaryField()[patchi][bndEdgei];
|
||||||
|
|
||||||
if (skew())
|
if (skew())
|
||||||
{
|
{
|
||||||
E -= skewCorrectionVectors()
|
edgeCtr -= skewCorrectionVectors()
|
||||||
.boundaryField()[patchI][edgeI];
|
.boundaryField()[patchi][bndEdgei];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Edge transformation tensor
|
// Edge transformation tensor
|
||||||
vector il = E - Cf.internalField()[edgeFaces[edgeI]];
|
tensors[0] =
|
||||||
|
rotation_e3e1
|
||||||
il -= Ne.boundaryField()[patchI][edgeI]
|
(
|
||||||
*(Ne.boundaryField()[patchI][edgeI]&il);
|
Ne.boundaryField()[patchi][bndEdgei],
|
||||||
|
(edgeCtr - Cf.internalField()[ownFacei])
|
||||||
il /= mag(il);
|
);
|
||||||
|
|
||||||
vector kl = Ne.boundaryField()[patchI][edgeI];
|
|
||||||
vector jl = kl^il;
|
|
||||||
|
|
||||||
edgeTransformTensors[boundary()[patchI].start() + edgeI][0] =
|
|
||||||
tensor(il, jl, kl);
|
|
||||||
|
|
||||||
// Owner transformation tensor
|
// Owner transformation tensor
|
||||||
il = E - Cf.internalField()[edgeFaces[edgeI]];
|
tensors[1] =
|
||||||
|
rotation_e3e1
|
||||||
il -= Nf.internalField()[edgeFaces[edgeI]]
|
(
|
||||||
*(Nf.internalField()[edgeFaces[edgeI]]&il);
|
Nf.internalField()[ownFacei],
|
||||||
|
(edgeCtr - Cf.internalField()[ownFacei])
|
||||||
il /= mag(il);
|
);
|
||||||
|
|
||||||
kl = Nf.internalField()[edgeFaces[edgeI]];
|
|
||||||
jl = kl^il;
|
|
||||||
|
|
||||||
edgeTransformTensors[boundary()[patchI].start() + edgeI][1] =
|
|
||||||
tensor(il, jl, kl);
|
|
||||||
|
|
||||||
// Neighbour transformation tensor
|
// Neighbour transformation tensor
|
||||||
il = ngbCf[edgeI] - E;
|
tensors[2] =
|
||||||
|
rotation_e3e1
|
||||||
il -= ngbNf[edgeI]*(ngbNf[edgeI]&il);
|
(
|
||||||
|
nbrNf[bndEdgei],
|
||||||
il /= mag(il);
|
(nbrCf[bndEdgei] - edgeCtr)
|
||||||
|
);
|
||||||
kl = ngbNf[edgeI];
|
|
||||||
|
|
||||||
jl = kl^il;
|
|
||||||
|
|
||||||
edgeTransformTensors[boundary()[patchI].start() + edgeI][2] =
|
|
||||||
tensor(il, jl, kl);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const labelUList& edgeFaces = boundary()[patchI].edgeFaces();
|
forAll(edgeFaces, bndEdgei)
|
||||||
|
|
||||||
forAll(edgeFaces, edgeI)
|
|
||||||
{
|
{
|
||||||
edgeTransformTensors.set
|
const label ownFacei = edgeFaces[bndEdgei];
|
||||||
(
|
const label meshEdgei(boundary()[patchi].start() + bndEdgei);
|
||||||
boundary()[patchI].start() + edgeI,
|
|
||||||
new Field<tensor>(3, I)
|
|
||||||
);
|
|
||||||
|
|
||||||
vector E = Ce.boundaryField()[patchI][edgeI];
|
auto& tensors = edgeTransformTensors[meshEdgei];
|
||||||
|
|
||||||
|
vector edgeCtr = Ce.boundaryField()[patchi][bndEdgei];
|
||||||
|
|
||||||
if (skew())
|
if (skew())
|
||||||
{
|
{
|
||||||
E -= skewCorrectionVectors()
|
edgeCtr -= skewCorrectionVectors()
|
||||||
.boundaryField()[patchI][edgeI];
|
.boundaryField()[patchi][bndEdgei];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Edge transformation tensor
|
// Edge transformation tensor
|
||||||
vector il = E - Cf.internalField()[edgeFaces[edgeI]];
|
tensors[0] =
|
||||||
|
rotation_e3e1
|
||||||
il -= Ne.boundaryField()[patchI][edgeI]
|
(
|
||||||
*(Ne.boundaryField()[patchI][edgeI]&il);
|
Ne.boundaryField()[patchi][bndEdgei],
|
||||||
|
(edgeCtr - Cf.internalField()[ownFacei])
|
||||||
il /= mag(il);
|
);
|
||||||
|
|
||||||
vector kl = Ne.boundaryField()[patchI][edgeI];
|
|
||||||
vector jl = kl^il;
|
|
||||||
|
|
||||||
edgeTransformTensors[boundary()[patchI].start() + edgeI][0] =
|
|
||||||
tensor(il, jl, kl);
|
|
||||||
|
|
||||||
// Owner transformation tensor
|
// Owner transformation tensor
|
||||||
il = E - Cf.internalField()[edgeFaces[edgeI]];
|
tensors[1] =
|
||||||
|
rotation_e3e1
|
||||||
|
(
|
||||||
|
Nf.internalField()[ownFacei],
|
||||||
|
(edgeCtr - Cf.internalField()[ownFacei])
|
||||||
|
);
|
||||||
|
|
||||||
il -= Nf.internalField()[edgeFaces[edgeI]]
|
// Neighbour transformation tensor
|
||||||
*(Nf.internalField()[edgeFaces[edgeI]]&il);
|
tensors[2] = tensor::I;
|
||||||
|
|
||||||
il /= mag(il);
|
|
||||||
|
|
||||||
kl = Nf.internalField()[edgeFaces[edgeI]];
|
|
||||||
jl = kl^il;
|
|
||||||
|
|
||||||
edgeTransformTensors[boundary()[patchI].start() + edgeI][1] =
|
|
||||||
tensor(il, jl, kl);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -882,7 +1077,7 @@ void Foam::faMesh::calcPointAreaNormals(vectorField& result) const
|
|||||||
DebugInFunction
|
DebugInFunction
|
||||||
<< "Calculating pointAreaNormals : face dual method" << endl;
|
<< "Calculating pointAreaNormals : face dual method" << endl;
|
||||||
|
|
||||||
result.resize(nPoints());
|
result.resize_nocopy(nPoints());
|
||||||
result = Zero;
|
result = Zero;
|
||||||
|
|
||||||
const pointField& points = patch().localPoints();
|
const pointField& points = patch().localPoints();
|
||||||
@ -945,7 +1140,7 @@ void Foam::faMesh::calcPointAreaNormals(vectorField& result) const
|
|||||||
|
|
||||||
for (const label pti : patchPoints)
|
for (const label pti : patchPoints)
|
||||||
{
|
{
|
||||||
result[pti] -= N*(N&result[pti]);
|
result[pti].removeCollinear(N);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Axis point correction
|
// Axis point correction
|
||||||
@ -1124,17 +1319,13 @@ void Foam::faMesh::calcPointAreaNormals(vectorField& result) const
|
|||||||
forAllConstIters(fpNormals, iter)
|
forAllConstIters(fpNormals, iter)
|
||||||
{
|
{
|
||||||
const label pointi = iter.key();
|
const label pointi = iter.key();
|
||||||
vector fpnorm = iter.val();
|
vector fpnorm = normalised(iter.val());
|
||||||
|
|
||||||
fpnorm.normalise();
|
result[pointi].removeCollinear(fpnorm);
|
||||||
result[pointi] -= fpnorm*(fpnorm & result[pointi]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (vector& n : result)
|
result.normalise();
|
||||||
{
|
|
||||||
n.normalise();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1469,7 +1660,7 @@ void Foam::faMesh::calcPointAreaNormalsByQuadricsFit(vectorField& result) const
|
|||||||
const vector& origin = points[curPoint];
|
const vector& origin = points[curPoint];
|
||||||
const vector axis = normalised(result[curPoint]);
|
const vector axis = normalised(result[curPoint]);
|
||||||
vector dir(allPoints[0] - points[curPoint]);
|
vector dir(allPoints[0] - points[curPoint]);
|
||||||
dir -= axis*(axis&dir);
|
dir.removeCollinear(axis);
|
||||||
dir.normalise();
|
dir.normalise();
|
||||||
|
|
||||||
const coordinateSystem cs("cs", origin, axis, dir);
|
const coordinateSystem cs("cs", origin, axis, dir);
|
||||||
@ -1633,7 +1824,7 @@ void Foam::faMesh::calcPointAreaNormalsByQuadricsFit(vectorField& result) const
|
|||||||
const vector& origin = points[curPoint];
|
const vector& origin = points[curPoint];
|
||||||
const vector axis = normalised(result[curPoint]);
|
const vector axis = normalised(result[curPoint]);
|
||||||
vector dir(allPoints[0] - points[curPoint]);
|
vector dir(allPoints[0] - points[curPoint]);
|
||||||
dir -= axis*(axis&dir);
|
dir.removeCollinear(axis);
|
||||||
dir.normalise();
|
dir.normalise();
|
||||||
|
|
||||||
coordinateSystem cs("cs", origin, axis, dir);
|
coordinateSystem cs("cs", origin, axis, dir);
|
||||||
@ -1710,22 +1901,19 @@ Foam::tmp<Foam::edgeScalarField> Foam::faMesh::edgeLengthCorrection() const
|
|||||||
DebugInFunction
|
DebugInFunction
|
||||||
<< "Calculating edge length correction" << endl;
|
<< "Calculating edge length correction" << endl;
|
||||||
|
|
||||||
tmp<edgeScalarField> tcorrection
|
auto tcorrection = tmp<edgeScalarField>::New
|
||||||
(
|
(
|
||||||
new edgeScalarField
|
IOobject
|
||||||
(
|
(
|
||||||
IOobject
|
"edgeLengthCorrection",
|
||||||
(
|
mesh().pointsInstance(),
|
||||||
"edgeLengthCorrection",
|
meshSubDir,
|
||||||
mesh().pointsInstance(),
|
mesh()
|
||||||
meshSubDir,
|
),
|
||||||
mesh()
|
*this,
|
||||||
),
|
dimless
|
||||||
*this,
|
|
||||||
dimless
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
edgeScalarField& correction = tcorrection.ref();
|
auto& correction = tcorrection.ref();
|
||||||
|
|
||||||
const vectorField& pointNormals = pointAreaNormals();
|
const vectorField& pointNormals = pointAreaNormals();
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2016-2017 Wikki Ltd
|
Copyright (C) 2016-2017 Wikki Ltd
|
||||||
Copyright (C) 2021 OpenCFD Ltd.
|
Copyright (C) 2021-2022 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -73,7 +73,7 @@ inline Foam::label Foam::faMesh::nInternalEdges() const noexcept
|
|||||||
|
|
||||||
inline Foam::label Foam::faMesh::nBoundaryEdges() const noexcept
|
inline Foam::label Foam::faMesh::nBoundaryEdges() const noexcept
|
||||||
{
|
{
|
||||||
return nEdges_ - nInternalEdges_;
|
return (nEdges_ - nInternalEdges_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -95,6 +95,12 @@ inline const Foam::edgeList& Foam::faMesh::edges() const noexcept
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::edgeList::subList Foam::faMesh::internalEdges() const
|
||||||
|
{
|
||||||
|
return edgeList::subList(edges_, nInternalEdges_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline const Foam::faceList& Foam::faMesh::faces() const
|
inline const Foam::faceList& Foam::faMesh::faces() const
|
||||||
{
|
{
|
||||||
return patch().localFaces();
|
return patch().localFaces();
|
||||||
@ -139,6 +145,12 @@ inline Foam::uindirectPrimitivePatch& Foam::faMesh::patch()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline bool Foam::faMesh::hasInternalEdgeLabels() const noexcept
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline const Foam::List<Foam::labelPair>&
|
inline const Foam::List<Foam::labelPair>&
|
||||||
Foam::faMesh::boundaryConnections() const
|
Foam::faMesh::boundaryConnections() const
|
||||||
{
|
{
|
||||||
|
|||||||
152
src/finiteArea/faMesh/faMeshSubset/faMeshSubset.C
Normal file
152
src/finiteArea/faMesh/faMeshSubset/faMeshSubset.C
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 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 "faMeshSubset.H"
|
||||||
|
#include "boolList.H"
|
||||||
|
#include "BitOps.H"
|
||||||
|
#include "Pstream.H"
|
||||||
|
#include "emptyFaPatch.H"
|
||||||
|
#include "cyclicFaPatch.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::word Foam::faMeshSubset::exposedPatchName("oldInternalEdges");
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
|
bool Foam::faMeshSubset::checkHasSubMesh() const
|
||||||
|
{
|
||||||
|
if (!subMeshPtr_)
|
||||||
|
{
|
||||||
|
FatalErrorInFunction
|
||||||
|
<< "Mesh is not subsetted!" << nl
|
||||||
|
<< abort(FatalError);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::faMeshSubset::faMeshSubset(const faMesh& baseMesh)
|
||||||
|
:
|
||||||
|
baseMesh_(baseMesh),
|
||||||
|
subMeshPtr_(nullptr),
|
||||||
|
edgeFlipMapPtr_(nullptr),
|
||||||
|
pointMap_(),
|
||||||
|
faceMap_(),
|
||||||
|
cellMap_(),
|
||||||
|
patchMap_()
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::faMeshSubset::faMeshSubset(const faMesh& baseMesh, const Foam::zero)
|
||||||
|
:
|
||||||
|
faMeshSubset(baseMesh)
|
||||||
|
{
|
||||||
|
reset(Foam::zero{});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
void Foam::faMeshSubset::clear()
|
||||||
|
{
|
||||||
|
subMeshPtr_.reset(nullptr);
|
||||||
|
edgeFlipMapPtr_.reset(nullptr);
|
||||||
|
|
||||||
|
pointMap_.clear();
|
||||||
|
faceMap_.clear();
|
||||||
|
cellMap_.clear();
|
||||||
|
patchMap_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::faMeshSubset::reset()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::faMeshSubset::reset(const Foam::zero)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
|
||||||
|
// Create zero-sized subMesh
|
||||||
|
subMeshPtr_.reset
|
||||||
|
(
|
||||||
|
new faMesh
|
||||||
|
(
|
||||||
|
baseMesh_.mesh(), // The polyMesh
|
||||||
|
// IOobject
|
||||||
|
// (
|
||||||
|
// baseMesh_.name(),
|
||||||
|
// baseMesh_.time().timeName(),
|
||||||
|
// baseMesh_.time(),
|
||||||
|
// IOobject::READ_IF_PRESENT, // Read fa* if present
|
||||||
|
// IOobject::NO_WRITE
|
||||||
|
// ),
|
||||||
|
Foam::zero{} // zero-sized
|
||||||
|
)
|
||||||
|
);
|
||||||
|
auto& newSubMesh = subMeshPtr_();
|
||||||
|
|
||||||
|
|
||||||
|
// Clone non-processor patches
|
||||||
|
{
|
||||||
|
const faBoundaryMesh& oldBoundary = baseMesh_.boundary();
|
||||||
|
const faBoundaryMesh& newBoundary = newSubMesh.boundary();
|
||||||
|
|
||||||
|
faPatchList newPatches(oldBoundary.nNonProcessor());
|
||||||
|
|
||||||
|
patchMap_ = identity(newPatches.size());
|
||||||
|
|
||||||
|
forAll(newPatches, patchi)
|
||||||
|
{
|
||||||
|
newPatches.set
|
||||||
|
(
|
||||||
|
patchi,
|
||||||
|
oldBoundary[patchi].clone
|
||||||
|
(
|
||||||
|
newBoundary,
|
||||||
|
labelList(), // edgeLabels
|
||||||
|
patchi,
|
||||||
|
oldBoundary[patchi].ngbPolyPatchIndex()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
newSubMesh.addFaPatches(newPatches);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
222
src/finiteArea/faMesh/faMeshSubset/faMeshSubset.H
Normal file
222
src/finiteArea/faMesh/faMeshSubset/faMeshSubset.H
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 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::faMeshSubset
|
||||||
|
|
||||||
|
Description
|
||||||
|
Holds a reference to the original mesh (the baseMesh)
|
||||||
|
and optionally to a subset of that mesh (the subMesh)
|
||||||
|
with mapping lists for points, faces, and cells.
|
||||||
|
|
||||||
|
Caution
|
||||||
|
Currently not really functional for subsetting beyond handling
|
||||||
|
a simple zero-sized mesh.
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
faMeshSubset.C
|
||||||
|
faMeshSubsetI.H
|
||||||
|
faMeshSubsetTemplates.C
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef Foam_faMeshSubset_H
|
||||||
|
#define Foam_faMeshSubset_H
|
||||||
|
|
||||||
|
#include "areaFaMesh.H"
|
||||||
|
#include "edgeFaMesh.H"
|
||||||
|
#include "GeometricField.H"
|
||||||
|
#include "bitSet.H"
|
||||||
|
#include "HashSet.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
// Forward Declarations
|
||||||
|
class mapDistributePolyMesh;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class faMeshSubset Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class faMeshSubset
|
||||||
|
{
|
||||||
|
// Private Data
|
||||||
|
|
||||||
|
//- The base mesh to subset from
|
||||||
|
const faMesh& baseMesh_;
|
||||||
|
|
||||||
|
//- Demand-driven subset mesh (pointer)
|
||||||
|
autoPtr<faMesh> subMeshPtr_;
|
||||||
|
|
||||||
|
//- Optional edge mapping array with flip encoded (-1/+1)
|
||||||
|
mutable autoPtr<labelList> edgeFlipMapPtr_;
|
||||||
|
|
||||||
|
//- Point mapping array
|
||||||
|
labelList pointMap_;
|
||||||
|
|
||||||
|
//- Face mapping array
|
||||||
|
labelList faceMap_;
|
||||||
|
|
||||||
|
//- Cell mapping array
|
||||||
|
labelList cellMap_;
|
||||||
|
|
||||||
|
//- Patch mapping array
|
||||||
|
labelList patchMap_;
|
||||||
|
|
||||||
|
|
||||||
|
// Private Member Functions
|
||||||
|
|
||||||
|
//- Calculate face flip map
|
||||||
|
void calcEdgeFlipMap() const;
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// Protected Member Functions
|
||||||
|
|
||||||
|
//- FatalError if subset has not been performed
|
||||||
|
bool checkHasSubMesh() const;
|
||||||
|
|
||||||
|
//- No copy construct
|
||||||
|
faMeshSubset(const faMeshSubset&) = delete;
|
||||||
|
|
||||||
|
//- No copy assignment
|
||||||
|
void operator=(const faMeshSubset&) = delete;
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Static Data Members
|
||||||
|
|
||||||
|
//- Name for exposed internal edges (default: oldInternalEdges)
|
||||||
|
static word exposedPatchName;
|
||||||
|
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
//- Construct using the entire mesh (no subset)
|
||||||
|
explicit faMeshSubset(const faMesh& baseMesh);
|
||||||
|
|
||||||
|
//- Construct a zero-sized subset mesh, non-processor patches only
|
||||||
|
faMeshSubset(const faMesh& baseMesh, const Foam::zero);
|
||||||
|
|
||||||
|
|
||||||
|
// Member Functions
|
||||||
|
|
||||||
|
// Access
|
||||||
|
|
||||||
|
//- Original mesh
|
||||||
|
inline const faMesh& baseMesh() const noexcept;
|
||||||
|
|
||||||
|
//- Return baseMesh or subMesh, depending on the current state.
|
||||||
|
inline const faMesh& mesh() const noexcept;
|
||||||
|
|
||||||
|
//- Have subMesh?
|
||||||
|
inline bool hasSubMesh() const noexcept;
|
||||||
|
|
||||||
|
//- Return reference to subset mesh
|
||||||
|
inline const faMesh& subMesh() const;
|
||||||
|
|
||||||
|
//- Return reference to subset mesh
|
||||||
|
inline faMesh& subMesh();
|
||||||
|
|
||||||
|
//- Return point map
|
||||||
|
inline const labelList& pointMap() const;
|
||||||
|
|
||||||
|
//- Return face map
|
||||||
|
inline const labelList& faceMap() const;
|
||||||
|
|
||||||
|
//- Return edge map with sign to encode flipped edges
|
||||||
|
inline const labelList& edgeFlipMap() const;
|
||||||
|
|
||||||
|
//- Return cell map
|
||||||
|
inline const labelList& cellMap() const;
|
||||||
|
|
||||||
|
//- Return patch map
|
||||||
|
inline const labelList& patchMap() const;
|
||||||
|
|
||||||
|
|
||||||
|
// Edit
|
||||||
|
|
||||||
|
//- Reset subMesh and all maps
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
//- Reset subMesh and all maps. Same as clear()
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
//- Reset to a zero-sized subset mesh, non-processor patches only
|
||||||
|
void reset(const Foam::zero);
|
||||||
|
|
||||||
|
|
||||||
|
// Field Mapping (static functions)
|
||||||
|
|
||||||
|
//- Map area field.
|
||||||
|
// Optionally allow unmapped faces not to produce a warning
|
||||||
|
template<class Type>
|
||||||
|
static tmp<GeometricField<Type, faPatchField, areaMesh>>
|
||||||
|
interpolate
|
||||||
|
(
|
||||||
|
const GeometricField<Type, faPatchField, areaMesh>&,
|
||||||
|
const faMesh& sMesh,
|
||||||
|
const bool allowUnmapped = false
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// Field Mapping
|
||||||
|
|
||||||
|
//- Map area field.
|
||||||
|
// Optionally allow unmapped faces not to produce a warning
|
||||||
|
template<class Type>
|
||||||
|
tmp<GeometricField<Type, faPatchField, areaMesh>>
|
||||||
|
interpolate
|
||||||
|
(
|
||||||
|
const GeometricField<Type, faPatchField, areaMesh>&,
|
||||||
|
const bool allowUnmapped = false
|
||||||
|
) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#include "faMeshSubsetI.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#ifdef NoRepository
|
||||||
|
#include "faMeshSubsetTemplates.C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
107
src/finiteArea/faMesh/faMeshSubset/faMeshSubsetI.H
Normal file
107
src/finiteArea/faMesh/faMeshSubset/faMeshSubsetI.H
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 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/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
inline const Foam::faMesh& Foam::faMeshSubset::baseMesh() const noexcept
|
||||||
|
{
|
||||||
|
return baseMesh_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::faMesh& Foam::faMeshSubset::mesh() const noexcept
|
||||||
|
{
|
||||||
|
return subMeshPtr_ ? *subMeshPtr_ : baseMesh_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline bool Foam::faMeshSubset::hasSubMesh() const noexcept
|
||||||
|
{
|
||||||
|
return bool(subMeshPtr_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::faMesh& Foam::faMeshSubset::subMesh() const
|
||||||
|
{
|
||||||
|
checkHasSubMesh();
|
||||||
|
|
||||||
|
return *subMeshPtr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline Foam::faMesh& Foam::faMeshSubset::subMesh()
|
||||||
|
{
|
||||||
|
checkHasSubMesh();
|
||||||
|
|
||||||
|
return *subMeshPtr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::labelList& Foam::faMeshSubset::pointMap() const
|
||||||
|
{
|
||||||
|
checkHasSubMesh();
|
||||||
|
|
||||||
|
return pointMap_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::labelList& Foam::faMeshSubset::faceMap() const
|
||||||
|
{
|
||||||
|
checkHasSubMesh();
|
||||||
|
|
||||||
|
return faceMap_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::labelList& Foam::faMeshSubset::edgeFlipMap() const
|
||||||
|
{
|
||||||
|
if (!edgeFlipMapPtr_)
|
||||||
|
{
|
||||||
|
// calcEdgeFlipMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
return *edgeFlipMapPtr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::labelList& Foam::faMeshSubset::cellMap() const
|
||||||
|
{
|
||||||
|
checkHasSubMesh();
|
||||||
|
|
||||||
|
return cellMap_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::labelList& Foam::faMeshSubset::patchMap() const
|
||||||
|
{
|
||||||
|
checkHasSubMesh();
|
||||||
|
|
||||||
|
return patchMap_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
169
src/finiteArea/faMesh/faMeshSubset/faMeshSubsetTemplates.C
Normal file
169
src/finiteArea/faMesh/faMeshSubset/faMeshSubsetTemplates.C
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 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 "faMeshSubset.H"
|
||||||
|
#include "areaFaMesh.H"
|
||||||
|
#include "edgeFaMesh.H"
|
||||||
|
#include "areaFields.H"
|
||||||
|
#include "edgeFields.H"
|
||||||
|
#include "emptyFaPatchFields.H"
|
||||||
|
#include "directFaPatchFieldMapper.H"
|
||||||
|
#include "flipOp.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
template<class Type>
|
||||||
|
Foam::tmp
|
||||||
|
<
|
||||||
|
Foam::GeometricField<Type, Foam::faPatchField, Foam::areaMesh>
|
||||||
|
>
|
||||||
|
Foam::faMeshSubset::interpolate
|
||||||
|
(
|
||||||
|
const GeometricField<Type, faPatchField, areaMesh>& vf,
|
||||||
|
const faMesh& sMesh,
|
||||||
|
const bool allowUnmapped
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// 1. Create the complete field with dummy patch fields
|
||||||
|
PtrList<faPatchField<Type>> patchFields(sMesh.boundary().size());
|
||||||
|
|
||||||
|
forAll(patchFields, patchi)
|
||||||
|
{
|
||||||
|
patchFields.set
|
||||||
|
(
|
||||||
|
patchi,
|
||||||
|
faPatchField<Type>::New
|
||||||
|
(
|
||||||
|
calculatedFaPatchField<Type>::typeName,
|
||||||
|
sMesh.boundary()[patchi],
|
||||||
|
DimensionedField<Type, areaMesh>::null()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto tresult = tmp<GeometricField<Type, faPatchField, areaMesh>>::New
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"subset"+vf.name(),
|
||||||
|
sMesh.time().timeName(),
|
||||||
|
sMesh.thisDb(),
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
),
|
||||||
|
sMesh,
|
||||||
|
vf.dimensions(),
|
||||||
|
Field<Type>(),
|
||||||
|
// Field<Type>(vf.primitiveField(), cellMap),
|
||||||
|
patchFields
|
||||||
|
);
|
||||||
|
auto& result = tresult.ref();
|
||||||
|
result.oriented() = vf.oriented();
|
||||||
|
|
||||||
|
|
||||||
|
// 2. Change the faPatchFields to the correct type using a mapper
|
||||||
|
// constructor (with reference to the now correct internal field)
|
||||||
|
|
||||||
|
auto& bf = result.boundaryFieldRef();
|
||||||
|
|
||||||
|
forAll(bf, patchi)
|
||||||
|
{
|
||||||
|
// Construct addressing
|
||||||
|
const faPatch& subPatch = sMesh.boundary()[patchi];
|
||||||
|
|
||||||
|
labelList directAddressing;
|
||||||
|
directFaPatchFieldMapper mapper(directAddressing);
|
||||||
|
|
||||||
|
// allowUnmapped : special mode for if we do not want to be
|
||||||
|
// warned for unmapped faces (e.g. from faMeshDistribute).
|
||||||
|
const bool hasUnmapped = mapper.hasUnmapped();
|
||||||
|
if (allowUnmapped)
|
||||||
|
{
|
||||||
|
mapper.hasUnmapped() = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bf.set
|
||||||
|
(
|
||||||
|
patchi,
|
||||||
|
faPatchField<Type>::New
|
||||||
|
(
|
||||||
|
vf.boundaryField()[patchi],
|
||||||
|
subPatch,
|
||||||
|
result(),
|
||||||
|
mapper
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (allowUnmapped && hasUnmapped)
|
||||||
|
{
|
||||||
|
// Set unmapped values to zeroGradient. This is the default
|
||||||
|
// action for unmapped faPatchFields. Note that this bypasses
|
||||||
|
// any special logic for handling unmapped faPatchFields but
|
||||||
|
// since this is only used inside faMeshDistribute ...
|
||||||
|
|
||||||
|
tmp<Field<Type>> tfld(bf[patchi].patchInternalField());
|
||||||
|
const Field<Type>& fld = tfld();
|
||||||
|
|
||||||
|
Field<Type> value(bf[patchi]);
|
||||||
|
forAll(directAddressing, i)
|
||||||
|
{
|
||||||
|
if (directAddressing[i] == -1)
|
||||||
|
{
|
||||||
|
value[i] = fld[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bf[patchi].faPatchField<Type>::operator=(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tresult;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
template<class Type>
|
||||||
|
Foam::tmp
|
||||||
|
<
|
||||||
|
Foam::GeometricField<Type, Foam::faPatchField, Foam::areaMesh>
|
||||||
|
>
|
||||||
|
Foam::faMeshSubset::interpolate
|
||||||
|
(
|
||||||
|
const GeometricField<Type, faPatchField, areaMesh>& vf,
|
||||||
|
const bool allowUnmapped
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
if (subMeshPtr_)
|
||||||
|
{
|
||||||
|
return interpolate(vf, *subMeshPtr_);
|
||||||
|
}
|
||||||
|
|
||||||
|
return vf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
470
src/finiteArea/faMesh/faMeshTools/faMeshTools.C
Normal file
470
src/finiteArea/faMesh/faMeshTools/faMeshTools.C
Normal file
@ -0,0 +1,470 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 2012-2016 OpenFOAM Foundation
|
||||||
|
Copyright (C) 2015-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 "faMeshTools.H"
|
||||||
|
#include "faBoundaryMeshEntries.H"
|
||||||
|
#include "areaFields.H"
|
||||||
|
#include "edgeFields.H"
|
||||||
|
#include "polyMesh.H"
|
||||||
|
#include "processorFaPatch.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
void Foam::faMeshTools::unregisterMesh(const faMesh& mesh)
|
||||||
|
{
|
||||||
|
auto& obr = const_cast<objectRegistry&>(mesh.thisDb());
|
||||||
|
|
||||||
|
// Checkout by name (casting ambiguity)
|
||||||
|
obr.checkOut(faMesh::typeName);
|
||||||
|
obr.checkOut("faBoundaryMesh");
|
||||||
|
obr.checkOut("faSchemes");
|
||||||
|
obr.checkOut("faSolution");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::faMeshTools::forceDemandDriven(faMesh& mesh)
|
||||||
|
{
|
||||||
|
(void)mesh.globalData();
|
||||||
|
|
||||||
|
(void)mesh.Le();
|
||||||
|
(void)mesh.magLe();
|
||||||
|
(void)mesh.areaCentres();
|
||||||
|
(void)mesh.edgeCentres();
|
||||||
|
|
||||||
|
(void)mesh.faceAreaNormals();
|
||||||
|
(void)mesh.edgeAreaNormals();
|
||||||
|
(void)mesh.pointAreaNormals();
|
||||||
|
(void)mesh.faceCurvatures();
|
||||||
|
(void)mesh.edgeTransformTensors();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::autoPtr<Foam::faMesh> Foam::faMeshTools::newMesh
|
||||||
|
(
|
||||||
|
const IOobject& io,
|
||||||
|
const polyMesh& pMesh,
|
||||||
|
const bool masterOnlyReading,
|
||||||
|
const bool verbose
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Region name
|
||||||
|
// ~~~~~~~~~~~
|
||||||
|
|
||||||
|
const fileName meshSubDir
|
||||||
|
(
|
||||||
|
(pMesh.name() == polyMesh::defaultRegion ? word::null : pMesh.name())
|
||||||
|
/ faMesh::meshSubDir
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
fileName facesInstance;
|
||||||
|
|
||||||
|
// Patch types
|
||||||
|
// ~~~~~~~~~~~
|
||||||
|
// Read and scatter master patches (without reading master mesh!)
|
||||||
|
|
||||||
|
PtrList<entry> patchEntries;
|
||||||
|
if (Pstream::master())
|
||||||
|
{
|
||||||
|
const bool oldParRun = Pstream::parRun(false);
|
||||||
|
|
||||||
|
facesInstance = io.time().findInstance
|
||||||
|
(
|
||||||
|
meshSubDir,
|
||||||
|
"faceLabels",
|
||||||
|
IOobject::MUST_READ
|
||||||
|
);
|
||||||
|
|
||||||
|
patchEntries = faBoundaryMeshEntries
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"faBoundary",
|
||||||
|
facesInstance,
|
||||||
|
meshSubDir,
|
||||||
|
io.db(),
|
||||||
|
IOobject::MUST_READ,
|
||||||
|
IOobject::NO_WRITE,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
Pstream::parRun(oldParRun);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Broadcast information to all
|
||||||
|
Pstream::broadcasts
|
||||||
|
(
|
||||||
|
UPstream::worldComm,
|
||||||
|
patchEntries,
|
||||||
|
facesInstance
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// Dummy meshes
|
||||||
|
// ~~~~~~~~~~~~
|
||||||
|
|
||||||
|
// Set up to read-if-present. Note: does not search for mesh so set
|
||||||
|
// instance explicitly
|
||||||
|
|
||||||
|
IOobject meshIO(io);
|
||||||
|
meshIO.instance() = facesInstance;
|
||||||
|
meshIO.readOpt(IOobject::READ_IF_PRESENT);
|
||||||
|
|
||||||
|
// For mesh components (faceLabels, ...)
|
||||||
|
IOobject cmptIO(meshIO, "faceLabels", meshSubDir);
|
||||||
|
cmptIO.readOpt(IOobject::MUST_READ);
|
||||||
|
cmptIO.writeOpt(IOobject::NO_WRITE);
|
||||||
|
cmptIO.registerObject(false);
|
||||||
|
|
||||||
|
|
||||||
|
// Check who has a mesh
|
||||||
|
|
||||||
|
const fileName meshDir = io.time().path()/facesInstance/meshSubDir;
|
||||||
|
bool haveMesh = isDir(meshDir);
|
||||||
|
if (masterOnlyReading && !Pstream::master())
|
||||||
|
{
|
||||||
|
haveMesh = false;
|
||||||
|
meshIO.readOpt(IOobject::NO_READ);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!haveMesh)
|
||||||
|
{
|
||||||
|
cmptIO.readOpt(IOobject::NO_READ);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Read mesh
|
||||||
|
// ~~~~~~~~~
|
||||||
|
// Now all processors use supplied points,faces etc
|
||||||
|
// Note: solution, schemes are also using the supplied IOobject so
|
||||||
|
// on slave will be NO_READ, on master READ_IF_PRESENT. This will
|
||||||
|
// conflict with e.g. timeStampMaster reading so switch off.
|
||||||
|
|
||||||
|
const auto oldCheckType = IOobject::fileModificationChecking;
|
||||||
|
IOobject::fileModificationChecking = IOobject::timeStamp;
|
||||||
|
|
||||||
|
|
||||||
|
// faceLabels
|
||||||
|
cmptIO.rename("faceLabels");
|
||||||
|
labelIOList faceLabels(cmptIO);
|
||||||
|
|
||||||
|
|
||||||
|
auto meshPtr = autoPtr<faMesh>::New
|
||||||
|
(
|
||||||
|
pMesh,
|
||||||
|
std::move(faceLabels),
|
||||||
|
meshIO
|
||||||
|
);
|
||||||
|
auto& mesh = *meshPtr;
|
||||||
|
|
||||||
|
IOobject::fileModificationChecking = oldCheckType;
|
||||||
|
|
||||||
|
|
||||||
|
// Some processors without patches? - add patches
|
||||||
|
|
||||||
|
if (returnReduce(mesh.boundary().empty(), orOp<bool>()))
|
||||||
|
{
|
||||||
|
// Use patchEntries, which were read on master and broadcast
|
||||||
|
|
||||||
|
faPatchList patches(patchEntries.size());
|
||||||
|
label nPatches = 0;
|
||||||
|
|
||||||
|
const bool isEmptyMesh = (mesh.faceLabels().empty());
|
||||||
|
|
||||||
|
forAll(patchEntries, patchi)
|
||||||
|
{
|
||||||
|
const entry& e = patchEntries[patchi];
|
||||||
|
const word type(e.dict().get<word>("type"));
|
||||||
|
const word& name = e.keyword();
|
||||||
|
|
||||||
|
if
|
||||||
|
(
|
||||||
|
type == processorFaPatch::typeName
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Stop at the first processor patch.
|
||||||
|
// - logic will not work with inter-mixed proc-patches anyhow
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dictionary patchDict(e.dict());
|
||||||
|
|
||||||
|
if (isEmptyMesh)
|
||||||
|
{
|
||||||
|
patchDict.set("edgeLabels", labelList());
|
||||||
|
}
|
||||||
|
|
||||||
|
patches.set
|
||||||
|
(
|
||||||
|
patchi,
|
||||||
|
faPatch::New
|
||||||
|
(
|
||||||
|
name,
|
||||||
|
patchDict,
|
||||||
|
nPatches++,
|
||||||
|
mesh.boundary()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
patches.resize(nPatches);
|
||||||
|
mesh.addFaPatches(patches, false); // No parallel comms
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recreate basic geometry, globalMeshData etc.
|
||||||
|
mesh.init(false);
|
||||||
|
(void)mesh.globalData();
|
||||||
|
|
||||||
|
return meshPtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::autoPtr<Foam::faMesh> Foam::faMeshTools::loadOrCreateMesh
|
||||||
|
(
|
||||||
|
const IOobject& io,
|
||||||
|
const polyMesh& pMesh,
|
||||||
|
const bool decompose,
|
||||||
|
const bool verbose
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Region name
|
||||||
|
// ~~~~~~~~~~~
|
||||||
|
|
||||||
|
const fileName meshSubDir
|
||||||
|
(
|
||||||
|
(pMesh.name() == polyMesh::defaultRegion ? word::null : pMesh.name())
|
||||||
|
/ faMesh::meshSubDir
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// Patch types
|
||||||
|
// ~~~~~~~~~~~
|
||||||
|
// Read and scatter master patches (without reading master mesh!)
|
||||||
|
|
||||||
|
PtrList<entry> patchEntries;
|
||||||
|
if (Pstream::master())
|
||||||
|
{
|
||||||
|
const bool oldParRun = Pstream::parRun(false);
|
||||||
|
|
||||||
|
patchEntries = faBoundaryMeshEntries
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"faBoundary",
|
||||||
|
io.instance(),
|
||||||
|
meshSubDir,
|
||||||
|
io.db(),
|
||||||
|
IOobject::MUST_READ,
|
||||||
|
IOobject::NO_WRITE,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
Pstream::parRun(oldParRun);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Broadcast: send patches to all
|
||||||
|
Pstream::broadcast(patchEntries); // == worldComm;
|
||||||
|
|
||||||
|
/// Info<< patchEntries << nl;
|
||||||
|
|
||||||
|
// Dummy meshes
|
||||||
|
// ~~~~~~~~~~~~
|
||||||
|
|
||||||
|
// Check who has or needs a mesh.
|
||||||
|
// For 'decompose', only need mesh on master.
|
||||||
|
// Otherwise check for presence of the "faceLabels" file
|
||||||
|
|
||||||
|
bool haveMesh =
|
||||||
|
(
|
||||||
|
decompose
|
||||||
|
? Pstream::master()
|
||||||
|
: fileHandler().isFile
|
||||||
|
(
|
||||||
|
fileHandler().filePath
|
||||||
|
(
|
||||||
|
io.time().path()/io.instance()/meshSubDir/"faceLabels"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
if (!haveMesh)
|
||||||
|
{
|
||||||
|
const bool oldParRun = Pstream::parRun(false);
|
||||||
|
|
||||||
|
// Create dummy mesh - on procs that don't already have a mesh
|
||||||
|
faMesh dummyMesh
|
||||||
|
(
|
||||||
|
pMesh,
|
||||||
|
labelList(),
|
||||||
|
IOobject(io, IOobject::NO_READ, IOobject::AUTO_WRITE)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Add patches
|
||||||
|
faPatchList patches(patchEntries.size());
|
||||||
|
label nPatches = 0;
|
||||||
|
|
||||||
|
forAll(patchEntries, patchi)
|
||||||
|
{
|
||||||
|
const entry& e = patchEntries[patchi];
|
||||||
|
const word type(e.dict().get<word>("type"));
|
||||||
|
const word& name = e.keyword();
|
||||||
|
|
||||||
|
if
|
||||||
|
(
|
||||||
|
type == processorFaPatch::typeName
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Stop at the first processor patch.
|
||||||
|
// - logic will not work with inter-mixed proc-patches anyhow
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dictionary patchDict(e.dict());
|
||||||
|
patchDict.set("edgeLabels", labelList());
|
||||||
|
|
||||||
|
patches.set
|
||||||
|
(
|
||||||
|
patchi,
|
||||||
|
faPatch::New
|
||||||
|
(
|
||||||
|
name,
|
||||||
|
patchDict,
|
||||||
|
nPatches++,
|
||||||
|
dummyMesh.boundary()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
patches.resize(nPatches);
|
||||||
|
dummyMesh.addFaPatches(patches, false); // No parallel comms
|
||||||
|
|
||||||
|
// Bad hack, but the underlying polyMesh is NO_WRITE
|
||||||
|
// so it does not create the faMesh subDir for us...
|
||||||
|
Foam::mkDir(dummyMesh.boundary().path());
|
||||||
|
|
||||||
|
//Pout<< "Writing dummy mesh to " << dummyMesh.boundary().path()
|
||||||
|
// << endl;
|
||||||
|
dummyMesh.write();
|
||||||
|
|
||||||
|
Pstream::parRun(oldParRun); // Restore parallel state
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read mesh
|
||||||
|
// ~~~~~~~~~
|
||||||
|
// Now all processors have a (possibly zero size) mesh so read in
|
||||||
|
// parallel
|
||||||
|
|
||||||
|
/// Pout<< "Reading area mesh from " << io.objectRelPath() << endl;
|
||||||
|
auto meshPtr = autoPtr<faMesh>::New(pMesh, false);
|
||||||
|
faMesh& mesh = *meshPtr;
|
||||||
|
|
||||||
|
// Sync patches
|
||||||
|
// ~~~~~~~~~~~~
|
||||||
|
|
||||||
|
if (!Pstream::master() && haveMesh)
|
||||||
|
{
|
||||||
|
// Check master names against mine
|
||||||
|
|
||||||
|
const faBoundaryMesh& patches = mesh.boundary();
|
||||||
|
|
||||||
|
forAll(patchEntries, patchi)
|
||||||
|
{
|
||||||
|
const entry& e = patchEntries[patchi];
|
||||||
|
const word type(e.dict().get<word>("type"));
|
||||||
|
const word& name = e.keyword();
|
||||||
|
|
||||||
|
if
|
||||||
|
(
|
||||||
|
type == processorFaPatch::typeName
|
||||||
|
)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (patchi >= patches.size())
|
||||||
|
{
|
||||||
|
FatalErrorInFunction
|
||||||
|
<< "Non-processor patches not synchronised."
|
||||||
|
<< endl
|
||||||
|
<< "Processor " << Pstream::myProcNo()
|
||||||
|
<< " has only " << patches.size()
|
||||||
|
<< " patches, master has "
|
||||||
|
<< patchi
|
||||||
|
<< exit(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
if
|
||||||
|
(
|
||||||
|
type != patches[patchi].type()
|
||||||
|
|| name != patches[patchi].name()
|
||||||
|
)
|
||||||
|
{
|
||||||
|
FatalErrorInFunction
|
||||||
|
<< "Non-processor patches not synchronised."
|
||||||
|
<< endl
|
||||||
|
<< "Master patch " << patchi
|
||||||
|
<< " name:" << type
|
||||||
|
<< " type:" << type << endl
|
||||||
|
<< "Processor " << Pstream::myProcNo()
|
||||||
|
<< " patch " << patchi
|
||||||
|
<< " has name:" << patches[patchi].name()
|
||||||
|
<< " type:" << patches[patchi].type()
|
||||||
|
<< exit(FatalError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Recreate basic geometry, globalMeshData etc.
|
||||||
|
mesh.init(false);
|
||||||
|
(void)mesh.globalData();
|
||||||
|
|
||||||
|
/// #if 0
|
||||||
|
/// faMeshTools::forceDemandDriven(mesh);
|
||||||
|
/// faMeshTools::unregisterMesh(mesh);
|
||||||
|
/// #endif
|
||||||
|
|
||||||
|
// Do some checks.
|
||||||
|
|
||||||
|
// Check if the boundary definition is unique
|
||||||
|
// and processor patches are correct
|
||||||
|
mesh.boundary().checkDefinition(verbose);
|
||||||
|
mesh.boundary().checkParallelSync(verbose);
|
||||||
|
|
||||||
|
return meshPtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
154
src/finiteArea/faMesh/faMeshTools/faMeshTools.H
Normal file
154
src/finiteArea/faMesh/faMeshTools/faMeshTools.H
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 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::faMeshTools
|
||||||
|
|
||||||
|
Description
|
||||||
|
A collection of tools for operating on an faMesh.
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
faMeshTools.C
|
||||||
|
faMeshToolsProcAddr.C
|
||||||
|
faMeshToolsTemplates.C
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef Foam_faMeshTools_H
|
||||||
|
#define Foam_faMeshTools_H
|
||||||
|
|
||||||
|
#include "faMesh.H"
|
||||||
|
#include "areaFieldsFwd.H"
|
||||||
|
#include "edgeFieldsFwd.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
// Forward Declarations
|
||||||
|
class mapDistributePolyMesh;
|
||||||
|
class writeHandler;
|
||||||
|
class polyMesh;
|
||||||
|
class IOobject;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class faMeshTools Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class faMeshTools
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
//- Unregister the faMesh from its associated polyMesh
|
||||||
|
//- to prevent triggering on polyMesh changes etc.
|
||||||
|
static void unregisterMesh(const faMesh& mesh);
|
||||||
|
|
||||||
|
//- Force creation of everything that might vaguely be used by patches.
|
||||||
|
// This is fairly horrible.
|
||||||
|
static void forceDemandDriven(faMesh& mesh);
|
||||||
|
|
||||||
|
|
||||||
|
//- Read mesh or create dummy mesh (0 faces, >0 patches).
|
||||||
|
// Works in two modes according to masterOnlyReading:
|
||||||
|
// true : create a dummy mesh for all procs
|
||||||
|
// false: checks locally for mesh directories and only creates dummy mesh
|
||||||
|
// if not present
|
||||||
|
static autoPtr<faMesh> newMesh
|
||||||
|
(
|
||||||
|
const IOobject& io,
|
||||||
|
const polyMesh& pMesh,
|
||||||
|
const bool masterOnlyReading,
|
||||||
|
const bool verbose = false
|
||||||
|
);
|
||||||
|
|
||||||
|
// Read mesh if available. Otherwise create empty mesh with same non-proc
|
||||||
|
// patches as proc0 mesh. Requires:
|
||||||
|
// - all processors to have all patches (and in same order).
|
||||||
|
// - io.instance() set to facesInstance
|
||||||
|
static autoPtr<faMesh> loadOrCreateMesh
|
||||||
|
(
|
||||||
|
const IOobject& io,
|
||||||
|
const polyMesh& pMesh,
|
||||||
|
const bool decompose,
|
||||||
|
const bool verbose = false
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
//- Read decompose/reconstruct addressing
|
||||||
|
static mapDistributePolyMesh readProcAddressing
|
||||||
|
(
|
||||||
|
const faMesh& mesh,
|
||||||
|
const autoPtr<faMesh>& baseMeshPtr
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Write decompose/reconstruct addressing
|
||||||
|
//
|
||||||
|
// \param mesh
|
||||||
|
// \param faDistMap
|
||||||
|
// \param decompose running in decompose vs reconstruct mode
|
||||||
|
// \param writeHandler file handler
|
||||||
|
// \param procMesh (optional) processor mesh in reconstruct mode
|
||||||
|
//
|
||||||
|
// \note Since the faMesh holds a reference to a polyMesh,
|
||||||
|
// in reconstruct mode it will refer to the base mesh, but
|
||||||
|
// we need a means to proc addressing into the processor locations.
|
||||||
|
// This is the purpose of the additional procMesh reference
|
||||||
|
static void writeProcAddressing
|
||||||
|
(
|
||||||
|
const faMesh& mesh,
|
||||||
|
const mapDistributePolyMesh& faDistMap,
|
||||||
|
const bool decompose,
|
||||||
|
autoPtr<fileOperation>&& writeHandler,
|
||||||
|
const faMesh* procMesh = nullptr
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
//- Flatten an edge field into linear addressing
|
||||||
|
// Optionally use primitive patch edge ordering
|
||||||
|
template<class Type>
|
||||||
|
static tmp<Field<Type>> flattenEdgeField
|
||||||
|
(
|
||||||
|
const GeometricField<Type, faePatchField, edgeMesh>& fld,
|
||||||
|
const bool primitiveOrdering = false
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#ifdef NoRepository
|
||||||
|
#include "faMeshToolsTemplates.C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
468
src/finiteArea/faMesh/faMeshTools/faMeshToolsProcAddr.C
Normal file
468
src/finiteArea/faMesh/faMeshTools/faMeshToolsProcAddr.C
Normal file
@ -0,0 +1,468 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 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 "faMeshTools.H"
|
||||||
|
#include "BitOps.H"
|
||||||
|
#include "fileOperation.H"
|
||||||
|
#include "areaFields.H"
|
||||||
|
#include "edgeFields.H"
|
||||||
|
#include "IOmapDistributePolyMesh.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
// Create a reconstruct map.
|
||||||
|
|
||||||
|
static mapDistributePolyMesh createReconstructMap
|
||||||
|
(
|
||||||
|
const faMesh& mesh,
|
||||||
|
const autoPtr<faMesh>& baseMeshPtr,
|
||||||
|
const labelUList& faceProcAddr,
|
||||||
|
const labelUList& edgeProcAddr,
|
||||||
|
const labelUList& pointProcAddr,
|
||||||
|
const labelUList& boundaryProcAddr
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const label nOldPoints = mesh.nPoints();
|
||||||
|
const label nOldFaces = mesh.nFaces();
|
||||||
|
const label nOldEdges = mesh.nEdges();
|
||||||
|
|
||||||
|
///Pout<< "old sizes"
|
||||||
|
/// << " points:" << nOldPoints
|
||||||
|
/// << " faces:" << nOldFaces
|
||||||
|
/// << " edges:" << nOldEdges << nl;
|
||||||
|
|
||||||
|
const faBoundaryMesh& oldBndMesh = mesh.boundary();
|
||||||
|
labelList oldPatchStarts(oldBndMesh.patchStarts());
|
||||||
|
|
||||||
|
// Patches: purge -1 entries
|
||||||
|
labelList patchProcAddr
|
||||||
|
(
|
||||||
|
IndirectList<label>::subset_if
|
||||||
|
(
|
||||||
|
boundaryProcAddr,
|
||||||
|
labelRange::ge0()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
labelListList faceSubMap(Pstream::nProcs());
|
||||||
|
faceSubMap[Pstream::masterNo()] = identity(nOldFaces);
|
||||||
|
|
||||||
|
labelListList edgeSubMap(Pstream::nProcs());
|
||||||
|
edgeSubMap[Pstream::masterNo()] = identity(nOldEdges);
|
||||||
|
|
||||||
|
labelListList pointSubMap(Pstream::nProcs());
|
||||||
|
pointSubMap[Pstream::masterNo()] = identity(nOldPoints);
|
||||||
|
|
||||||
|
labelListList patchSubMap(Pstream::nProcs());
|
||||||
|
patchSubMap[Pstream::masterNo()] = patchProcAddr;
|
||||||
|
|
||||||
|
|
||||||
|
// Gather addressing on the master
|
||||||
|
labelListList faceAddressing(Pstream::nProcs());
|
||||||
|
faceAddressing[Pstream::myProcNo()] = faceProcAddr;
|
||||||
|
Pstream::gatherList(faceAddressing);
|
||||||
|
|
||||||
|
labelListList edgeAddressing(Pstream::nProcs());
|
||||||
|
edgeAddressing[Pstream::myProcNo()] = edgeProcAddr;
|
||||||
|
Pstream::gatherList(edgeAddressing);
|
||||||
|
|
||||||
|
labelListList pointAddressing(Pstream::nProcs());
|
||||||
|
pointAddressing[Pstream::myProcNo()] = pointProcAddr;
|
||||||
|
Pstream::gatherList(pointAddressing);
|
||||||
|
|
||||||
|
labelListList patchAddressing(Pstream::nProcs());
|
||||||
|
patchAddressing[Pstream::myProcNo()] = patchProcAddr;
|
||||||
|
Pstream::gatherList(patchAddressing);
|
||||||
|
|
||||||
|
|
||||||
|
// NB: can only have a reconstruct on master!
|
||||||
|
if (Pstream::master() && baseMeshPtr && baseMeshPtr->nFaces())
|
||||||
|
{
|
||||||
|
const faMesh& baseMesh = *baseMeshPtr;
|
||||||
|
|
||||||
|
const label nNewPoints = baseMesh.nPoints();
|
||||||
|
const label nNewFaces = baseMesh.nFaces();
|
||||||
|
const label nNewEdges = baseMesh.nEdges();
|
||||||
|
const label nNewPatches = baseMesh.boundary().size();
|
||||||
|
|
||||||
|
/// Pout<< "new sizes"
|
||||||
|
/// << " points:" << nNewPoints
|
||||||
|
/// << " faces:" << nNewFaces
|
||||||
|
/// << " edges:" << nNewEdges << nl;
|
||||||
|
|
||||||
|
mapDistribute faFaceMap
|
||||||
|
(
|
||||||
|
nNewFaces,
|
||||||
|
std::move(faceSubMap),
|
||||||
|
std::move(faceAddressing),
|
||||||
|
false, // subHasFlip
|
||||||
|
false // constructHasFlip
|
||||||
|
);
|
||||||
|
|
||||||
|
mapDistribute faEdgeMap
|
||||||
|
(
|
||||||
|
nNewEdges,
|
||||||
|
std::move(edgeSubMap),
|
||||||
|
std::move(edgeAddressing),
|
||||||
|
false, // subHasFlip
|
||||||
|
false // constructHasFlip
|
||||||
|
);
|
||||||
|
|
||||||
|
mapDistribute faPointMap
|
||||||
|
(
|
||||||
|
nNewPoints,
|
||||||
|
std::move(pointSubMap),
|
||||||
|
std::move(pointAddressing)
|
||||||
|
);
|
||||||
|
|
||||||
|
mapDistribute faPatchMap
|
||||||
|
(
|
||||||
|
nNewPatches,
|
||||||
|
std::move(patchSubMap),
|
||||||
|
std::move(patchAddressing)
|
||||||
|
);
|
||||||
|
|
||||||
|
return mapDistributePolyMesh
|
||||||
|
(
|
||||||
|
// Mesh before changes
|
||||||
|
nOldPoints,
|
||||||
|
nOldEdges, // area: nOldEdges (volume: nOldFaces)
|
||||||
|
nOldFaces, // area: nOldFaces (volume: nOldCells)
|
||||||
|
|
||||||
|
std::move(oldPatchStarts),
|
||||||
|
labelList(), // oldPatchNMeshPoints [unused]
|
||||||
|
|
||||||
|
mapDistribute(std::move(faPointMap)),
|
||||||
|
mapDistribute(std::move(faEdgeMap)), // edgeMap (volume: faceMap)
|
||||||
|
mapDistribute(std::move(faFaceMap)), // faceMap (volume: cellMap)
|
||||||
|
mapDistribute(std::move(faPatchMap))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mapDistribute faFaceMap
|
||||||
|
(
|
||||||
|
0, // nNewFaces
|
||||||
|
std::move(faceSubMap),
|
||||||
|
labelListList(Pstream::nProcs()), // constructMap
|
||||||
|
false, // subHasFlip
|
||||||
|
false // constructHasFlip
|
||||||
|
);
|
||||||
|
|
||||||
|
mapDistribute faEdgeMap
|
||||||
|
(
|
||||||
|
0, // nNewEdges
|
||||||
|
std::move(edgeSubMap),
|
||||||
|
labelListList(Pstream::nProcs()), // constructMap
|
||||||
|
false, // subHasFlip
|
||||||
|
false // constructHasFlip
|
||||||
|
);
|
||||||
|
|
||||||
|
mapDistribute faPointMap
|
||||||
|
(
|
||||||
|
0, // nNewPoints
|
||||||
|
std::move(pointSubMap),
|
||||||
|
labelListList(Pstream::nProcs()) // constructMap
|
||||||
|
);
|
||||||
|
|
||||||
|
mapDistribute faPatchMap
|
||||||
|
(
|
||||||
|
0, // nNewPatches
|
||||||
|
std::move(patchSubMap),
|
||||||
|
labelListList(Pstream::nProcs()) // constructMap
|
||||||
|
);
|
||||||
|
|
||||||
|
return mapDistributePolyMesh
|
||||||
|
(
|
||||||
|
// Mesh before changes
|
||||||
|
nOldPoints,
|
||||||
|
nOldEdges, // area: nOldEdges (volume: nOldFaces)
|
||||||
|
nOldFaces, // area: nOldFaces (volume: nOldCells)
|
||||||
|
|
||||||
|
std::move(oldPatchStarts),
|
||||||
|
labelList(), // oldPatchNMeshPoints [unused]
|
||||||
|
|
||||||
|
mapDistribute(std::move(faPointMap)),
|
||||||
|
mapDistribute(std::move(faEdgeMap)), // edgeMap (volume: faceMap)
|
||||||
|
mapDistribute(std::move(faFaceMap)), // faceMap (volume: cellMap)
|
||||||
|
mapDistribute(std::move(faPatchMap))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::mapDistributePolyMesh
|
||||||
|
Foam::faMeshTools::readProcAddressing
|
||||||
|
(
|
||||||
|
const faMesh& mesh,
|
||||||
|
const autoPtr<faMesh>& baseMeshPtr
|
||||||
|
)
|
||||||
|
{
|
||||||
|
IOobject ioAddr
|
||||||
|
(
|
||||||
|
"procAddressing",
|
||||||
|
mesh.facesInstance(),
|
||||||
|
faMesh::meshSubDir,
|
||||||
|
mesh.thisDb(),
|
||||||
|
IOobject::READ_IF_PRESENT,
|
||||||
|
IOobject::NO_WRITE,
|
||||||
|
false // no register
|
||||||
|
);
|
||||||
|
|
||||||
|
//if (ioAddr.typeHeaderOk<labelIOList>(true))
|
||||||
|
//{
|
||||||
|
// Pout<< "Reading addressing from " << io.name() << " at "
|
||||||
|
// << mesh.facesInstance() << nl << endl;
|
||||||
|
// distMap.reset(new IOmapDistributePolyMesh(io));
|
||||||
|
//}
|
||||||
|
//else
|
||||||
|
|
||||||
|
{
|
||||||
|
Info<< "Reading (face|edge|face|point|boundary)ProcAddressing from "
|
||||||
|
<< mesh.facesInstance().c_str() << '/'
|
||||||
|
<< faMesh::meshSubDir << nl << endl;
|
||||||
|
|
||||||
|
ioAddr.rename("faceProcAddressing");
|
||||||
|
labelIOList faceProcAddressing(ioAddr, Zero);
|
||||||
|
|
||||||
|
ioAddr.rename("edgeProcAddressing");
|
||||||
|
labelIOList edgeProcAddressing(ioAddr, Zero);
|
||||||
|
|
||||||
|
ioAddr.rename("pointProcAddressing");
|
||||||
|
labelIOList pointProcAddressing(ioAddr, Zero);
|
||||||
|
|
||||||
|
ioAddr.rename("boundaryProcAddressing");
|
||||||
|
labelIOList boundaryProcAddressing(ioAddr, Zero);
|
||||||
|
|
||||||
|
if
|
||||||
|
(
|
||||||
|
mesh.nFaces() != faceProcAddressing.size()
|
||||||
|
|| mesh.nEdges() != edgeProcAddressing.size()
|
||||||
|
|| mesh.nPoints() != pointProcAddressing.size()
|
||||||
|
|| mesh.boundary().size() != boundaryProcAddressing.size()
|
||||||
|
)
|
||||||
|
{
|
||||||
|
FatalErrorInFunction
|
||||||
|
<< "Read addressing inconsistent with mesh sizes" << nl
|
||||||
|
<< "faces:" << mesh.nFaces()
|
||||||
|
<< " addressing:" << faceProcAddressing.objectRelPath()
|
||||||
|
<< " size:" << faceProcAddressing.size() << nl
|
||||||
|
<< "edges:" << mesh.nEdges()
|
||||||
|
<< " addressing:" << edgeProcAddressing.objectRelPath()
|
||||||
|
<< " size:" << edgeProcAddressing.size() << nl
|
||||||
|
<< "points:" << mesh.nPoints()
|
||||||
|
<< " addressing:" << pointProcAddressing.objectRelPath()
|
||||||
|
<< " size:" << pointProcAddressing.size()
|
||||||
|
<< "patches:" << mesh.boundary().size()
|
||||||
|
<< " addressing:" << boundaryProcAddressing.objectRelPath()
|
||||||
|
<< " size:" << boundaryProcAddressing.size()
|
||||||
|
<< exit(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
return createReconstructMap
|
||||||
|
(
|
||||||
|
mesh,
|
||||||
|
baseMeshPtr,
|
||||||
|
faceProcAddressing,
|
||||||
|
edgeProcAddressing,
|
||||||
|
pointProcAddressing,
|
||||||
|
boundaryProcAddressing
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::faMeshTools::writeProcAddressing
|
||||||
|
(
|
||||||
|
const faMesh& mesh,
|
||||||
|
const mapDistributePolyMesh& map,
|
||||||
|
const bool decompose,
|
||||||
|
autoPtr<fileOperation>&& writeHandler,
|
||||||
|
const faMesh* procMesh
|
||||||
|
)
|
||||||
|
{
|
||||||
|
Info<< "Writing ("
|
||||||
|
<< (decompose ? "decompose" : "reconstruct")
|
||||||
|
<< ") procAddressing files to "
|
||||||
|
<< mesh.facesInstance().c_str() << '/'
|
||||||
|
<< faMesh::meshSubDir << endl;
|
||||||
|
|
||||||
|
IOobject ioAddr
|
||||||
|
(
|
||||||
|
"procAddressing",
|
||||||
|
mesh.facesInstance(),
|
||||||
|
faMesh::meshSubDir,
|
||||||
|
(procMesh && !decompose ? procMesh->thisDb() : mesh.thisDb()),
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE,
|
||||||
|
false // no register
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// faceProcAddressing (faMesh)
|
||||||
|
ioAddr.rename("faceProcAddressing");
|
||||||
|
labelIOList faceMap(ioAddr, Zero);
|
||||||
|
|
||||||
|
// edgeProcAddressing (faMesh)
|
||||||
|
ioAddr.rename("edgeProcAddressing");
|
||||||
|
labelIOList edgeMap(ioAddr, Zero);
|
||||||
|
|
||||||
|
// pointProcAddressing (faMesh)
|
||||||
|
ioAddr.rename("pointProcAddressing");
|
||||||
|
labelIOList pointMap(ioAddr, Zero);
|
||||||
|
|
||||||
|
// boundaryProcAddressing (faMesh)
|
||||||
|
ioAddr.rename("boundaryProcAddressing");
|
||||||
|
labelIOList patchMap(ioAddr, Zero);
|
||||||
|
|
||||||
|
if (decompose)
|
||||||
|
{
|
||||||
|
// Decompose
|
||||||
|
// - forward map: [undecomposed] -> [decomposed]
|
||||||
|
|
||||||
|
// area:faces (volume:cells)
|
||||||
|
faceMap = identity(map.nOldCells());
|
||||||
|
map.cellMap().distribute(faceMap);
|
||||||
|
|
||||||
|
// area:edges (volume:faces)
|
||||||
|
edgeMap = identity(map.nOldFaces());
|
||||||
|
map.faceMap().distribute(edgeMap);
|
||||||
|
|
||||||
|
pointMap = identity(map.nOldPoints());
|
||||||
|
map.distributePointData(pointMap);
|
||||||
|
|
||||||
|
patchMap = identity(map.patchMap().constructSize());
|
||||||
|
map.patchMap().mapDistributeBase::distribute
|
||||||
|
(
|
||||||
|
Pstream::commsTypes::nonBlocking,
|
||||||
|
label(-1), // nullValue for new patches...
|
||||||
|
patchMap,
|
||||||
|
flipOp() // negate op
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else // reconstruct
|
||||||
|
{
|
||||||
|
// Reconstruct
|
||||||
|
// - reverse map: [undecomposed] <- [decomposed]
|
||||||
|
|
||||||
|
// area:faces (volume:cells)
|
||||||
|
faceMap = identity(mesh.nFaces());
|
||||||
|
map.cellMap().reverseDistribute(map.nOldCells(), faceMap);
|
||||||
|
|
||||||
|
// area:edges (volume:faces)
|
||||||
|
edgeMap = identity(mesh.patch().nEdges());
|
||||||
|
map.faceMap().reverseDistribute(map.nOldFaces(), edgeMap);
|
||||||
|
|
||||||
|
pointMap = identity(mesh.nPoints());
|
||||||
|
map.pointMap().reverseDistribute(map.nOldPoints(), pointMap);
|
||||||
|
|
||||||
|
patchMap = identity(mesh.boundary().size());
|
||||||
|
map.patchMap().mapDistributeBase::reverseDistribute
|
||||||
|
(
|
||||||
|
Pstream::commsTypes::nonBlocking,
|
||||||
|
map.oldPatchSizes().size(),
|
||||||
|
label(-1), // nullValue for unmapped patches...
|
||||||
|
patchMap
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
autoPtr<fileOperation> defaultHandler;
|
||||||
|
if (writeHandler)
|
||||||
|
{
|
||||||
|
defaultHandler = fileHandler(std::move(writeHandler));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// If we want procAddressing, need to manually write it ourselves
|
||||||
|
// since it was not registered anywhere
|
||||||
|
|
||||||
|
IOmapDistributePolyMeshRef procAddrMap
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"procAddressing",
|
||||||
|
mesh.facesInstance(),
|
||||||
|
faMesh::meshSubDir,
|
||||||
|
mesh.thisDb(),
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE,
|
||||||
|
false // no register
|
||||||
|
),
|
||||||
|
map
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
if (decompose)
|
||||||
|
{
|
||||||
|
// Write into proc directories
|
||||||
|
procAddrMap.write();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Reconstruct: "procAddressing" only meaningful for rank 0
|
||||||
|
// and written into base (serial) location (if at all).
|
||||||
|
|
||||||
|
if (Pstream::master())
|
||||||
|
{
|
||||||
|
const bool oldParRun = Pstream::parRun(false);
|
||||||
|
procAddrMap.write();
|
||||||
|
Pstream::parRun(oldParRun);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const bool faceOk = faceMap.write();
|
||||||
|
const bool edgeOk = edgeMap.write();
|
||||||
|
const bool pointOk = pointMap.write();
|
||||||
|
const bool patchOk = patchMap.write();
|
||||||
|
|
||||||
|
if (defaultHandler)
|
||||||
|
{
|
||||||
|
writeHandler = fileHandler(std::move(defaultHandler));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!edgeOk || !faceOk || !pointOk || !patchOk)
|
||||||
|
{
|
||||||
|
WarningInFunction
|
||||||
|
<< "Failed to write some of "
|
||||||
|
<< faceMap.objectRelPath() << ", "
|
||||||
|
<< edgeMap.objectRelPath() << ", "
|
||||||
|
<< pointMap.objectRelPath() << ", "
|
||||||
|
<< patchMap.objectRelPath() << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
80
src/finiteArea/faMesh/faMeshTools/faMeshToolsTemplates.C
Normal file
80
src/finiteArea/faMesh/faMeshTools/faMeshToolsTemplates.C
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 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 "edgeFields.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
template<class Type>
|
||||||
|
Foam::tmp<Foam::Field<Type>> Foam::faMeshTools::flattenEdgeField
|
||||||
|
(
|
||||||
|
const GeometricField<Type, faePatchField, edgeMesh>& fld,
|
||||||
|
const bool primitiveOrdering
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const faMesh& mesh = fld.mesh();
|
||||||
|
|
||||||
|
auto tresult = tmp<Field<Type>>::New(mesh.nEdges(), Zero);
|
||||||
|
auto& result = tresult.ref();
|
||||||
|
|
||||||
|
// Internal field
|
||||||
|
result.slice(0, fld.size()) = fld;
|
||||||
|
|
||||||
|
if (primitiveOrdering)
|
||||||
|
{
|
||||||
|
// Boundary field in primitive patch order
|
||||||
|
|
||||||
|
forAll(fld.boundaryField(), patchi)
|
||||||
|
{
|
||||||
|
UIndirectList<Type>
|
||||||
|
(
|
||||||
|
result,
|
||||||
|
mesh.boundary()[patchi].edgeLabels()
|
||||||
|
) = fld.boundaryField()[patchi];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Boundary field in sub-list (slice) order
|
||||||
|
|
||||||
|
label start = fld.size();
|
||||||
|
|
||||||
|
forAll(fld.boundaryField(), patchi)
|
||||||
|
{
|
||||||
|
const label len = mesh.boundary()[patchi].size();
|
||||||
|
|
||||||
|
result.slice(start, len) = fld.boundaryField()[patchi];
|
||||||
|
|
||||||
|
start += len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tresult;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -37,8 +37,6 @@ License
|
|||||||
|
|
||||||
void Foam::faMesh::updateMesh(const mapPolyMesh& mpm)
|
void Foam::faMesh::updateMesh(const mapPolyMesh& mpm)
|
||||||
{
|
{
|
||||||
DebugInFunction << "Updating mesh" << endl;
|
|
||||||
|
|
||||||
// if (!mpm.morphing())
|
// if (!mpm.morphing())
|
||||||
// {
|
// {
|
||||||
// // No topo change
|
// // No topo change
|
||||||
@ -48,18 +46,14 @@ void Foam::faMesh::updateMesh(const mapPolyMesh& mpm)
|
|||||||
// Create fa mesh mapper, using the old mesh
|
// Create fa mesh mapper, using the old mesh
|
||||||
const faMeshMapper mapper(*this, mpm);
|
const faMeshMapper mapper(*this, mpm);
|
||||||
|
|
||||||
|
|
||||||
// Rebuild mesh
|
// Rebuild mesh
|
||||||
|
// ~~~~~~~~~~~~
|
||||||
// Cast away const for interface reasons. HJ, 12/Aug/2011
|
|
||||||
faMesh& m = const_cast<faMesh&>(*this);
|
|
||||||
|
|
||||||
|
|
||||||
// Clear existing mesh data
|
// Clear existing mesh data
|
||||||
clearOut();
|
clearOut();
|
||||||
|
|
||||||
// Set new labels
|
// Set new labels
|
||||||
m.faceLabels_ = mapper.areaMap().newFaceLabels();
|
faceLabels_ = mapper.areaMap().newFaceLabels();
|
||||||
|
|
||||||
const uindirectPrimitivePatch& bp = patch();
|
const uindirectPrimitivePatch& bp = patch();
|
||||||
|
|
||||||
@ -121,12 +115,12 @@ void Foam::faMesh::updateMesh(const mapPolyMesh& mpm)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set new edges for all patches
|
// Set new edges for all patches
|
||||||
forAll(m.boundary_, patchI)
|
forAll(boundary_, patchI)
|
||||||
{
|
{
|
||||||
m.boundary_[patchI].resetEdges(patchEdges[patchI]);
|
boundary_[patchI].resetEdges(patchEdges[patchI]);
|
||||||
}
|
}
|
||||||
|
|
||||||
m.setPrimitiveMeshData();
|
setPrimitiveMeshData();
|
||||||
|
|
||||||
// Create global mesh data
|
// Create global mesh data
|
||||||
if (Pstream::parRun())
|
if (Pstream::parRun())
|
||||||
@ -135,10 +129,10 @@ void Foam::faMesh::updateMesh(const mapPolyMesh& mpm)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Calculate topology for the patches (processor-processor comms etc.)
|
// Calculate topology for the patches (processor-processor comms etc.)
|
||||||
m.boundary_.updateMesh();
|
boundary_.updateMesh();
|
||||||
|
|
||||||
// Calculate the geometry for the patches (transformation tensors etc.)
|
// Calculate the geometry for the patches (transformation tensors etc.)
|
||||||
m.boundary_.calcGeometry();
|
boundary_.calcGeometry();
|
||||||
|
|
||||||
|
|
||||||
// Map fields
|
// Map fields
|
||||||
@ -156,7 +150,7 @@ void Foam::faMesh::updateMesh(const mapPolyMesh& mpm)
|
|||||||
|
|
||||||
void Foam::faMesh::mapFields(const faMeshMapper& mapper) const
|
void Foam::faMesh::mapFields(const faMeshMapper& mapper) const
|
||||||
{
|
{
|
||||||
// Map all the areaFields in the objectRegistry
|
// Map areaFields in the objectRegistry
|
||||||
MapGeometricFields<scalar, faPatchField, faMeshMapper, areaMesh>(mapper);
|
MapGeometricFields<scalar, faPatchField, faMeshMapper, areaMesh>(mapper);
|
||||||
MapGeometricFields<vector, faPatchField, faMeshMapper, areaMesh>(mapper);
|
MapGeometricFields<vector, faPatchField, faMeshMapper, areaMesh>(mapper);
|
||||||
MapGeometricFields<sphericalTensor, faPatchField, faMeshMapper, areaMesh>
|
MapGeometricFields<sphericalTensor, faPatchField, faMeshMapper, areaMesh>
|
||||||
@ -165,7 +159,7 @@ void Foam::faMesh::mapFields(const faMeshMapper& mapper) const
|
|||||||
(mapper);
|
(mapper);
|
||||||
MapGeometricFields<tensor, faPatchField, faMeshMapper, areaMesh>(mapper);
|
MapGeometricFields<tensor, faPatchField, faMeshMapper, areaMesh>(mapper);
|
||||||
|
|
||||||
// Map all the edgeFields in the objectRegistry
|
// Map edgeFields in the objectRegistry
|
||||||
MapGeometricFields<scalar, faePatchField, faMeshMapper, edgeMesh>(mapper);
|
MapGeometricFields<scalar, faePatchField, faMeshMapper, edgeMesh>(mapper);
|
||||||
MapGeometricFields<vector, faePatchField, faMeshMapper, edgeMesh>(mapper);
|
MapGeometricFields<vector, faePatchField, faMeshMapper, edgeMesh>(mapper);
|
||||||
MapGeometricFields<sphericalTensor, faePatchField, faMeshMapper, edgeMesh>
|
MapGeometricFields<sphericalTensor, faePatchField, faMeshMapper, edgeMesh>
|
||||||
@ -227,7 +221,6 @@ void Foam::faMesh::mapOldAreas(const faMeshMapper& mapper) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user