mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: combine loadOrCreateMesh from redistributePar into fvMeshTools.
- similar functionality as newMesh etc. Relocated to finiteVolume since there are no dynamicMesh dependencies. - use simpler procAddressing (with updated mapDistributeBase). separated from redistributePar
This commit is contained in:
@ -27,377 +27,62 @@ License
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "loadOrCreateMesh.H"
|
||||
#include "processorPolyPatch.H"
|
||||
#include "processorCyclicPolyPatch.H"
|
||||
#include "Time.H"
|
||||
#include "polyBoundaryMeshEntries.H"
|
||||
#include "IOobjectList.H"
|
||||
#include "pointSet.H"
|
||||
#include "faceSet.H"
|
||||
#include "cellSet.H"
|
||||
#include "basicFvGeometryScheme.H"
|
||||
#include "Pstream.H"
|
||||
#include "OSspecific.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
|
||||
|
||||
// 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
|
||||
Foam::autoPtr<Foam::fvMesh> Foam::loadOrCreateMesh
|
||||
Foam::boolList Foam::haveMeshFile
|
||||
(
|
||||
const bool decompose,
|
||||
const IOobject& io
|
||||
const Time& runTime,
|
||||
const fileName& meshPath,
|
||||
const word& meshFile,
|
||||
const bool verbose
|
||||
)
|
||||
{
|
||||
// Region name
|
||||
// ~~~~~~~~~~~
|
||||
|
||||
fileName meshSubDir;
|
||||
|
||||
if (io.name() == polyMesh::defaultRegion)
|
||||
{
|
||||
meshSubDir = polyMesh::meshSubDir;
|
||||
}
|
||||
else
|
||||
{
|
||||
meshSubDir = io.name()/polyMesh::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 = polyBoundaryMeshEntries
|
||||
boolList haveFileOnProc
|
||||
(
|
||||
UPstream::listGatherValues<bool>
|
||||
(
|
||||
IOobject
|
||||
fileHandler().isFile
|
||||
(
|
||||
"boundary",
|
||||
io.instance(), //facesInstance,
|
||||
meshSubDir,
|
||||
io.db(),
|
||||
IOobject::MUST_READ,
|
||||
IOobject::NO_WRITE,
|
||||
false
|
||||
)
|
||||
);
|
||||
|
||||
Pstream::parRun(oldParRun);
|
||||
}
|
||||
|
||||
// Broadcast: send patches to all
|
||||
Pstream::scatter(patchEntries); // == worldComm;
|
||||
|
||||
|
||||
// Dummy meshes
|
||||
// ~~~~~~~~~~~~
|
||||
|
||||
// Check who has a mesh
|
||||
bool haveMesh;
|
||||
if (decompose)
|
||||
{
|
||||
// Mesh needs to be present on the master only
|
||||
haveMesh = Pstream::master();
|
||||
}
|
||||
else
|
||||
{
|
||||
const fileName facesFile
|
||||
(
|
||||
io.time().path()
|
||||
/io.instance() //facesInstance
|
||||
/meshSubDir
|
||||
/"faces"
|
||||
);
|
||||
|
||||
// Check presence of the searched-for faces file
|
||||
haveMesh = fileHandler().isFile(fileHandler().filePath(facesFile));
|
||||
}
|
||||
|
||||
if (!haveMesh)
|
||||
{
|
||||
const bool oldParRun = Pstream::parRun(false);
|
||||
|
||||
|
||||
// Create dummy mesh. Only used on procs that don't have mesh.
|
||||
IOobject noReadIO(io);
|
||||
noReadIO.readOpt(IOobject::NO_READ);
|
||||
noReadIO.writeOpt(IOobject::AUTO_WRITE);
|
||||
fvMesh dummyMesh(noReadIO, Zero, false);
|
||||
|
||||
// Add patches
|
||||
List<polyPatch*> 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 != processorPolyPatch::typeName
|
||||
&& type != processorCyclicPolyPatch::typeName
|
||||
)
|
||||
{
|
||||
dictionary patchDict(e.dict());
|
||||
patchDict.set("nFaces", 0);
|
||||
patchDict.set("startFace", 0);
|
||||
|
||||
patches[patchi] = polyPatch::New
|
||||
fileHandler().filePath
|
||||
(
|
||||
name,
|
||||
patchDict,
|
||||
nPatches++,
|
||||
dummyMesh.boundaryMesh()
|
||||
).ptr();
|
||||
}
|
||||
}
|
||||
patches.setSize(nPatches);
|
||||
dummyMesh.addFvPatches(patches, false); // no parallel comms
|
||||
|
||||
|
||||
// Add some dummy zones so upon reading it does not read them
|
||||
// from the undecomposed case. Should be done as extra argument to
|
||||
// regIOobject::readStream?
|
||||
List<pointZone*> pz
|
||||
(
|
||||
1,
|
||||
new pointZone
|
||||
(
|
||||
"dummyPointZone",
|
||||
0,
|
||||
dummyMesh.pointZones()
|
||||
runTime.path()/meshPath/meshFile
|
||||
)
|
||||
)
|
||||
);
|
||||
List<faceZone*> fz
|
||||
(
|
||||
1,
|
||||
new faceZone
|
||||
(
|
||||
"dummyFaceZone",
|
||||
0,
|
||||
dummyMesh.faceZones()
|
||||
)
|
||||
);
|
||||
List<cellZone*> cz
|
||||
(
|
||||
1,
|
||||
new cellZone
|
||||
(
|
||||
"dummyCellZone",
|
||||
0,
|
||||
dummyMesh.cellZones()
|
||||
)
|
||||
);
|
||||
dummyMesh.addZones(pz, fz, cz);
|
||||
dummyMesh.pointZones().clear();
|
||||
dummyMesh.faceZones().clear();
|
||||
dummyMesh.cellZones().clear();
|
||||
//Pout<< "Writing dummy mesh to " << dummyMesh.polyMesh::objectPath()
|
||||
// << 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 mesh from " << io.objectPath() << endl;
|
||||
auto meshPtr = autoPtr<fvMesh>::New(io);
|
||||
fvMesh& mesh = *meshPtr;
|
||||
|
||||
// Make sure to use a non-parallel geometry calculation method
|
||||
if (verbose)
|
||||
{
|
||||
tmp<fvGeometryScheme> basicGeometry
|
||||
(
|
||||
fvGeometryScheme::New
|
||||
(
|
||||
mesh,
|
||||
dictionary(),
|
||||
basicFvGeometryScheme::typeName
|
||||
)
|
||||
);
|
||||
mesh.geometry(basicGeometry);
|
||||
Info<< "Per processor availability of \""
|
||||
<< meshFile << "\" file in " << meshPath << nl
|
||||
<< " " << flatOutput(haveFileOnProc) << nl << endl;
|
||||
}
|
||||
|
||||
Pstream::broadcast(haveFileOnProc);
|
||||
return haveFileOnProc;
|
||||
}
|
||||
|
||||
// Sync patches
|
||||
// ~~~~~~~~~~~~
|
||||
|
||||
if (!Pstream::master() && haveMesh)
|
||||
void Foam::removeProcAddressing(const polyMesh& mesh)
|
||||
{
|
||||
IOobject ioAddr
|
||||
(
|
||||
"procAddressing",
|
||||
mesh.facesInstance(),
|
||||
polyMesh::meshSubDir,
|
||||
mesh.thisDb()
|
||||
);
|
||||
|
||||
for (const auto prefix : {"boundary", "cell", "face", "point"})
|
||||
{
|
||||
// Check master names against mine
|
||||
ioAddr.rename(prefix + word("ProcAddressing"));
|
||||
|
||||
const polyBoundaryMesh& patches = mesh.boundaryMesh();
|
||||
|
||||
forAll(patchEntries, patchi)
|
||||
{
|
||||
const entry& e = patchEntries[patchi];
|
||||
const word type(e.dict().get<word>("type"));
|
||||
const word& name = e.keyword();
|
||||
|
||||
if
|
||||
(
|
||||
type == processorPolyPatch::typeName
|
||||
|| type == processorCyclicPolyPatch::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);
|
||||
}
|
||||
}
|
||||
const fileName procFile(ioAddr.objectPath());
|
||||
Foam::rm(procFile);
|
||||
}
|
||||
|
||||
|
||||
// Determine zones
|
||||
// ~~~~~~~~~~~~~~~
|
||||
|
||||
wordList pointZoneNames(mesh.pointZones().names());
|
||||
Pstream::scatter(pointZoneNames);
|
||||
wordList faceZoneNames(mesh.faceZones().names());
|
||||
Pstream::scatter(faceZoneNames);
|
||||
wordList cellZoneNames(mesh.cellZones().names());
|
||||
Pstream::scatter(cellZoneNames);
|
||||
|
||||
if (!haveMesh)
|
||||
{
|
||||
// Add the zones. Make sure to remove the old dummy ones first
|
||||
mesh.pointZones().clear();
|
||||
mesh.faceZones().clear();
|
||||
mesh.cellZones().clear();
|
||||
|
||||
List<pointZone*> pz(pointZoneNames.size());
|
||||
forAll(pointZoneNames, i)
|
||||
{
|
||||
pz[i] = new pointZone
|
||||
(
|
||||
pointZoneNames[i],
|
||||
i,
|
||||
mesh.pointZones()
|
||||
);
|
||||
}
|
||||
List<faceZone*> fz(faceZoneNames.size());
|
||||
forAll(faceZoneNames, i)
|
||||
{
|
||||
fz[i] = new faceZone
|
||||
(
|
||||
faceZoneNames[i],
|
||||
i,
|
||||
mesh.faceZones()
|
||||
);
|
||||
}
|
||||
List<cellZone*> cz(cellZoneNames.size());
|
||||
forAll(cellZoneNames, i)
|
||||
{
|
||||
cz[i] = new cellZone
|
||||
(
|
||||
cellZoneNames[i],
|
||||
i,
|
||||
mesh.cellZones()
|
||||
);
|
||||
}
|
||||
mesh.addZones(pz, fz, cz);
|
||||
}
|
||||
|
||||
|
||||
// Determine sets
|
||||
// ~~~~~~~~~~~~~~
|
||||
|
||||
wordList pointSetNames;
|
||||
wordList faceSetNames;
|
||||
wordList cellSetNames;
|
||||
if (Pstream::master())
|
||||
{
|
||||
// Read sets
|
||||
const bool oldParRun = Pstream::parRun(false);
|
||||
IOobjectList objects(mesh, mesh.facesInstance(), "polyMesh/sets");
|
||||
Pstream::parRun(oldParRun);
|
||||
|
||||
pointSetNames = objects.sortedNames(pointSet::typeName);
|
||||
faceSetNames = objects.sortedNames(faceSet::typeName);
|
||||
cellSetNames = objects.sortedNames(cellSet::typeName);
|
||||
}
|
||||
Pstream::scatter(pointSetNames);
|
||||
Pstream::scatter(faceSetNames);
|
||||
Pstream::scatter(cellSetNames);
|
||||
|
||||
if (!haveMesh)
|
||||
{
|
||||
for (const word& setName : pointSetNames)
|
||||
{
|
||||
pointSet(mesh, setName, 0).write();
|
||||
}
|
||||
for (const word& setName : faceSetNames)
|
||||
{
|
||||
faceSet(mesh, setName, 0).write();
|
||||
}
|
||||
for (const word& setName : cellSetNames)
|
||||
{
|
||||
cellSet(mesh, setName, 0).write();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Force recreation of globalMeshData.
|
||||
mesh.globalData();
|
||||
|
||||
|
||||
// Do some checks.
|
||||
|
||||
// Check if the boundary definition is unique
|
||||
mesh.boundaryMesh().checkDefinition(true);
|
||||
// Check if the boundary processor patches are correct
|
||||
mesh.boundaryMesh().checkParallelSync(true);
|
||||
// Check names of zones are equal
|
||||
mesh.cellZones().checkDefinition(true);
|
||||
mesh.cellZones().checkParallelSync(true);
|
||||
mesh.faceZones().checkDefinition(true);
|
||||
mesh.faceZones().checkParallelSync(true);
|
||||
mesh.pointZones().checkDefinition(true);
|
||||
mesh.pointZones().checkParallelSync(true);
|
||||
|
||||
return meshPtr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2012 OpenFOAM Foundation
|
||||
Copyright (C) 2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -27,29 +28,35 @@ InNamespace
|
||||
Foam
|
||||
|
||||
Description
|
||||
Load or create (0 size) a mesh. Used in distributing meshes to a
|
||||
larger number of processors
|
||||
Miscellaneous file handling for meshes.
|
||||
|
||||
SourceFiles
|
||||
loadOrCreateMesh.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef loadOrCreateMesh_H
|
||||
#define loadOrCreateMesh_H
|
||||
#ifndef Foam_loadOrCreateMesh_H
|
||||
#define Foam_loadOrCreateMesh_H
|
||||
|
||||
#include "fvMesh.H"
|
||||
#include "fvMeshTools.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
//- Load (if it exists) or create zero cell mesh given an IOobject:
|
||||
// name : regionName
|
||||
// instance : exact directory where to find mesh (i.e. does not
|
||||
// do a findInstance
|
||||
autoPtr<fvMesh> loadOrCreateMesh(const bool decompose, const IOobject& io);
|
||||
//- Check for availability of specified mesh file (default: "faces")
|
||||
boolList haveMeshFile
|
||||
(
|
||||
const Time& runTime,
|
||||
const fileName& meshPath,
|
||||
const word& meshFile = "faces",
|
||||
const bool verbose = true
|
||||
);
|
||||
|
||||
|
||||
//- Remove procAddressing
|
||||
void removeProcAddressing(const polyMesh& mesh);
|
||||
|
||||
//- Remove empty directory. Return true if removed.
|
||||
bool removeEmptyDir(const fileName& path);
|
||||
|
||||
@ -92,7 +92,6 @@ Usage
|
||||
#include "zeroGradientFvPatchFields.H"
|
||||
#include "topoSet.H"
|
||||
#include "regionProperties.H"
|
||||
#include "basicFvGeometryScheme.H"
|
||||
|
||||
#include "parFvFieldReconstructor.H"
|
||||
#include "parLagrangianRedistributor.H"
|
||||
@ -257,49 +256,6 @@ void copyUniform
|
||||
}
|
||||
|
||||
|
||||
boolList haveFacesFile(const fileName& meshPath)
|
||||
{
|
||||
const fileName facesPath(meshPath/"faces");
|
||||
Info<< "Checking for mesh in " << facesPath << nl << endl;
|
||||
boolList haveMesh
|
||||
(
|
||||
UPstream::listGatherValues<bool>
|
||||
(
|
||||
fileHandler().isFile(fileHandler().filePath(facesPath))
|
||||
)
|
||||
);
|
||||
Info<< "Per processor mesh availability:" << nl
|
||||
<< " " << flatOutput(haveMesh) << nl << endl;
|
||||
|
||||
Pstream::broadcast(haveMesh);
|
||||
return haveMesh;
|
||||
}
|
||||
|
||||
|
||||
void setBasicGeometry(fvMesh& mesh)
|
||||
{
|
||||
// Set the fvGeometryScheme to basic since it does not require
|
||||
// any parallel communication to construct the geometry. During
|
||||
// redistributePar one might temporarily end up with processors
|
||||
// with zero procBoundaries. Normally procBoundaries trigger geometry
|
||||
// calculation (e.g. send over cellCentres) so on the processors without
|
||||
// procBoundaries this will not happen. The call to the geometry calculation
|
||||
// is not synchronised and this might lead to a hang for geometry schemes
|
||||
// that do require synchronisation
|
||||
|
||||
tmp<fvGeometryScheme> basicGeometry
|
||||
(
|
||||
fvGeometryScheme::New
|
||||
(
|
||||
mesh,
|
||||
dictionary(),
|
||||
basicFvGeometryScheme::typeName
|
||||
)
|
||||
);
|
||||
mesh.geometry(basicGeometry);
|
||||
}
|
||||
|
||||
|
||||
void printMeshData(const polyMesh& mesh)
|
||||
{
|
||||
// Collect all data on master
|
||||
@ -557,213 +513,6 @@ void determineDecomposition
|
||||
}
|
||||
|
||||
|
||||
// Write addressing if decomposing (1 to many) or reconstructing (many to 1)
|
||||
void writeProcAddressing
|
||||
(
|
||||
autoPtr<fileOperation>&& writeHandler,
|
||||
const fvMesh& mesh,
|
||||
const mapDistributePolyMesh& map,
|
||||
const bool decompose
|
||||
)
|
||||
{
|
||||
Info<< "Writing procAddressing files to " << mesh.facesInstance()
|
||||
<< endl;
|
||||
|
||||
labelIOList cellMap
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"cellProcAddressing",
|
||||
mesh.facesInstance(),
|
||||
polyMesh::meshSubDir,
|
||||
mesh,
|
||||
IOobject::NO_READ
|
||||
),
|
||||
0
|
||||
);
|
||||
|
||||
labelIOList faceMap
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"faceProcAddressing",
|
||||
mesh.facesInstance(),
|
||||
polyMesh::meshSubDir,
|
||||
mesh,
|
||||
IOobject::NO_READ
|
||||
),
|
||||
0
|
||||
);
|
||||
|
||||
labelIOList pointMap
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"pointProcAddressing",
|
||||
mesh.facesInstance(),
|
||||
polyMesh::meshSubDir,
|
||||
mesh,
|
||||
IOobject::NO_READ
|
||||
),
|
||||
0
|
||||
);
|
||||
|
||||
labelIOList patchMap
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"boundaryProcAddressing",
|
||||
mesh.facesInstance(),
|
||||
polyMesh::meshSubDir,
|
||||
mesh,
|
||||
IOobject::NO_READ
|
||||
),
|
||||
0
|
||||
);
|
||||
|
||||
// Decomposing: see how cells moved from undecomposed case
|
||||
if (decompose)
|
||||
{
|
||||
cellMap = identity(map.nOldCells());
|
||||
map.distributeCellData(cellMap);
|
||||
|
||||
faceMap = identity(map.nOldFaces());
|
||||
{
|
||||
const mapDistribute& faceDistMap = map.faceMap();
|
||||
|
||||
if (faceDistMap.subHasFlip() || faceDistMap.constructHasFlip())
|
||||
{
|
||||
// Offset by 1
|
||||
faceMap = faceMap + 1;
|
||||
}
|
||||
// Apply face flips
|
||||
mapDistributeBase::distribute
|
||||
(
|
||||
Pstream::commsTypes::nonBlocking,
|
||||
List<labelPair>(),
|
||||
faceDistMap.constructSize(),
|
||||
faceDistMap.subMap(),
|
||||
faceDistMap.subHasFlip(),
|
||||
faceDistMap.constructMap(),
|
||||
faceDistMap.constructHasFlip(),
|
||||
faceMap,
|
||||
flipLabelOp()
|
||||
);
|
||||
}
|
||||
|
||||
pointMap = identity(map.nOldPoints());
|
||||
map.distributePointData(pointMap);
|
||||
|
||||
patchMap = identity(map.oldPatchSizes().size());
|
||||
const mapDistribute& patchDistMap = map.patchMap();
|
||||
// Use explicit distribute since we need to provide a null value
|
||||
// (for new patches) and this is the only call that allow us to
|
||||
// provide one ...
|
||||
mapDistributeBase::distribute
|
||||
(
|
||||
Pstream::commsTypes::nonBlocking,
|
||||
List<labelPair>(),
|
||||
patchDistMap.constructSize(),
|
||||
patchDistMap.subMap(),
|
||||
patchDistMap.subHasFlip(),
|
||||
patchDistMap.constructMap(),
|
||||
patchDistMap.constructHasFlip(),
|
||||
patchMap,
|
||||
label(-1),
|
||||
eqOp<label>(),
|
||||
flipOp(),
|
||||
UPstream::msgType()
|
||||
);
|
||||
}
|
||||
else // reconstruct
|
||||
{
|
||||
cellMap = identity(mesh.nCells());
|
||||
map.cellMap().reverseDistribute(map.nOldCells(), cellMap);
|
||||
|
||||
faceMap = identity(mesh.nFaces());
|
||||
{
|
||||
const mapDistribute& faceDistMap = map.faceMap();
|
||||
|
||||
if (faceDistMap.subHasFlip() || faceDistMap.constructHasFlip())
|
||||
{
|
||||
// Offset by 1
|
||||
faceMap = faceMap + 1;
|
||||
}
|
||||
|
||||
mapDistributeBase::distribute
|
||||
(
|
||||
Pstream::commsTypes::nonBlocking,
|
||||
List<labelPair>(),
|
||||
map.nOldFaces(),
|
||||
faceDistMap.constructMap(),
|
||||
faceDistMap.constructHasFlip(),
|
||||
faceDistMap.subMap(),
|
||||
faceDistMap.subHasFlip(),
|
||||
faceMap,
|
||||
flipLabelOp()
|
||||
);
|
||||
}
|
||||
|
||||
pointMap = identity(mesh.nPoints());
|
||||
map.pointMap().reverseDistribute(map.nOldPoints(), pointMap);
|
||||
|
||||
const mapDistribute& patchDistMap = map.patchMap();
|
||||
patchMap = identity(mesh.boundaryMesh().size());
|
||||
patchDistMap.reverseDistribute
|
||||
(
|
||||
map.oldPatchSizes().size(),
|
||||
label(-1),
|
||||
patchMap
|
||||
);
|
||||
}
|
||||
|
||||
autoPtr<fileOperation> defaultHandler;
|
||||
if (writeHandler)
|
||||
{
|
||||
defaultHandler = fileHandler(std::move(writeHandler));
|
||||
}
|
||||
|
||||
const bool cellOk = cellMap.write();
|
||||
const bool faceOk = faceMap.write();
|
||||
const bool pointOk = pointMap.write();
|
||||
const bool patchOk = patchMap.write();
|
||||
|
||||
if (defaultHandler)
|
||||
{
|
||||
writeHandler = fileHandler(std::move(defaultHandler));
|
||||
}
|
||||
|
||||
if (!cellOk || !faceOk || !pointOk || !patchOk)
|
||||
{
|
||||
WarningInFunction
|
||||
<< "Failed to write " << cellMap.objectPath()
|
||||
<< ", " << faceMap.objectPath()
|
||||
<< ", " << pointMap.objectPath()
|
||||
<< ", " << patchMap.objectPath()
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Remove addressing
|
||||
void removeProcAddressing(const polyMesh& mesh)
|
||||
{
|
||||
for (const auto prefix : {"boundary", "cell", "face", "point"})
|
||||
{
|
||||
IOobject io
|
||||
(
|
||||
prefix + word("ProcAddressing"),
|
||||
mesh.facesInstance(),
|
||||
polyMesh::meshSubDir,
|
||||
mesh
|
||||
);
|
||||
|
||||
const fileName procFile(io.objectPath());
|
||||
rm(procFile);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Generic mesh-based field reading
|
||||
template<class GeoField>
|
||||
void readField
|
||||
@ -1391,7 +1140,13 @@ autoPtr<mapDistributePolyMesh> redistributeAndWrite
|
||||
{
|
||||
// Decompose (1 -> N) or reconstruct (N -> 1)
|
||||
// so {boundary,cell,face,point}ProcAddressing have meaning
|
||||
writeProcAddressing(std::move(writeHandler), mesh, map, decompose);
|
||||
fvMeshTools::writeProcAddressing
|
||||
(
|
||||
mesh,
|
||||
map,
|
||||
decompose,
|
||||
std::move(writeHandler)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1531,322 +1286,6 @@ autoPtr<mapDistributePolyMesh> redistributeAndWrite
|
||||
//
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
autoPtr<mapDistributePolyMesh> createReconstructMap
|
||||
(
|
||||
const autoPtr<fvMesh>& baseMeshPtr,
|
||||
const fvMesh& mesh,
|
||||
const labelList& cellProcAddressing,
|
||||
const labelList& faceProcAddressing,
|
||||
const labelList& pointProcAddressing,
|
||||
const labelList& boundaryProcAddressing
|
||||
)
|
||||
{
|
||||
// Send addressing to master
|
||||
labelListList cellAddressing(Pstream::nProcs());
|
||||
cellAddressing[Pstream::myProcNo()] = cellProcAddressing;
|
||||
Pstream::gatherList(cellAddressing);
|
||||
|
||||
labelListList faceAddressing(Pstream::nProcs());
|
||||
faceAddressing[Pstream::myProcNo()] = faceProcAddressing;
|
||||
Pstream::gatherList(faceAddressing);
|
||||
|
||||
labelListList pointAddressing(Pstream::nProcs());
|
||||
pointAddressing[Pstream::myProcNo()] = pointProcAddressing;
|
||||
Pstream::gatherList(pointAddressing);
|
||||
|
||||
labelListList boundaryAddressing(Pstream::nProcs());
|
||||
{
|
||||
// Remove -1 entries
|
||||
DynamicList<label> patchProcAddressing(boundaryProcAddressing.size());
|
||||
forAll(boundaryProcAddressing, i)
|
||||
{
|
||||
if (boundaryProcAddressing[i] != -1)
|
||||
{
|
||||
patchProcAddressing.append(boundaryProcAddressing[i]);
|
||||
}
|
||||
}
|
||||
boundaryAddressing[Pstream::myProcNo()] = patchProcAddressing;
|
||||
Pstream::gatherList(boundaryAddressing);
|
||||
}
|
||||
|
||||
|
||||
autoPtr<mapDistributePolyMesh> mapPtr;
|
||||
|
||||
if (baseMeshPtr && baseMeshPtr->nCells())
|
||||
{
|
||||
const fvMesh& baseMesh = *baseMeshPtr;
|
||||
|
||||
labelListList cellSubMap(Pstream::nProcs());
|
||||
cellSubMap[Pstream::masterNo()] = identity(mesh.nCells());
|
||||
|
||||
mapDistribute cellMap
|
||||
(
|
||||
baseMesh.nCells(),
|
||||
std::move(cellSubMap),
|
||||
std::move(cellAddressing)
|
||||
);
|
||||
|
||||
labelListList faceSubMap(Pstream::nProcs());
|
||||
faceSubMap[Pstream::masterNo()] = identity(mesh.nFaces());
|
||||
|
||||
mapDistribute faceMap
|
||||
(
|
||||
baseMesh.nFaces(),
|
||||
std::move(faceSubMap),
|
||||
std::move(faceAddressing),
|
||||
false, //subHasFlip
|
||||
true //constructHasFlip
|
||||
);
|
||||
|
||||
labelListList pointSubMap(Pstream::nProcs());
|
||||
pointSubMap[Pstream::masterNo()] = identity(mesh.nPoints());
|
||||
|
||||
mapDistribute pointMap
|
||||
(
|
||||
baseMesh.nPoints(),
|
||||
std::move(pointSubMap),
|
||||
std::move(pointAddressing)
|
||||
);
|
||||
|
||||
labelListList patchSubMap(Pstream::nProcs());
|
||||
// Send (filtered) patches to master
|
||||
patchSubMap[Pstream::masterNo()] =
|
||||
boundaryAddressing[Pstream::myProcNo()];
|
||||
|
||||
mapDistribute patchMap
|
||||
(
|
||||
baseMesh.boundaryMesh().size(),
|
||||
std::move(patchSubMap),
|
||||
std::move(boundaryAddressing)
|
||||
);
|
||||
|
||||
const label nOldPoints = mesh.nPoints();
|
||||
const label nOldFaces = mesh.nFaces();
|
||||
const label nOldCells = mesh.nCells();
|
||||
|
||||
const polyBoundaryMesh& pbm = mesh.boundaryMesh();
|
||||
labelList oldPatchStarts(pbm.size());
|
||||
labelList oldPatchNMeshPoints(pbm.size());
|
||||
forAll(pbm, patchI)
|
||||
{
|
||||
oldPatchStarts[patchI] = pbm[patchI].start();
|
||||
oldPatchNMeshPoints[patchI] = pbm[patchI].nPoints();
|
||||
}
|
||||
|
||||
mapPtr.reset
|
||||
(
|
||||
new mapDistributePolyMesh
|
||||
(
|
||||
nOldPoints,
|
||||
nOldFaces,
|
||||
nOldCells,
|
||||
std::move(oldPatchStarts),
|
||||
std::move(oldPatchNMeshPoints),
|
||||
std::move(pointMap),
|
||||
std::move(faceMap),
|
||||
std::move(cellMap),
|
||||
std::move(patchMap)
|
||||
)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
labelListList cellSubMap(Pstream::nProcs());
|
||||
cellSubMap[Pstream::masterNo()] = identity(mesh.nCells());
|
||||
labelListList cellConstructMap(Pstream::nProcs());
|
||||
|
||||
mapDistribute cellMap
|
||||
(
|
||||
0,
|
||||
std::move(cellSubMap),
|
||||
std::move(cellConstructMap)
|
||||
);
|
||||
|
||||
labelListList faceSubMap(Pstream::nProcs());
|
||||
faceSubMap[Pstream::masterNo()] = identity(mesh.nFaces());
|
||||
labelListList faceConstructMap(Pstream::nProcs());
|
||||
|
||||
mapDistribute faceMap
|
||||
(
|
||||
0,
|
||||
std::move(faceSubMap),
|
||||
std::move(faceConstructMap),
|
||||
false, //subHasFlip
|
||||
true //constructHasFlip
|
||||
);
|
||||
|
||||
labelListList pointSubMap(Pstream::nProcs());
|
||||
pointSubMap[Pstream::masterNo()] = identity(mesh.nPoints());
|
||||
labelListList pointConstructMap(Pstream::nProcs());
|
||||
|
||||
mapDistribute pointMap
|
||||
(
|
||||
0,
|
||||
std::move(pointSubMap),
|
||||
std::move(pointConstructMap)
|
||||
);
|
||||
|
||||
labelListList patchSubMap(Pstream::nProcs());
|
||||
// Send (filtered) patches to master
|
||||
patchSubMap[Pstream::masterNo()] =
|
||||
boundaryAddressing[Pstream::myProcNo()];
|
||||
labelListList patchConstructMap(Pstream::nProcs());
|
||||
|
||||
mapDistribute patchMap
|
||||
(
|
||||
0,
|
||||
std::move(patchSubMap),
|
||||
std::move(patchConstructMap)
|
||||
);
|
||||
|
||||
const label nOldPoints = mesh.nPoints();
|
||||
const label nOldFaces = mesh.nFaces();
|
||||
const label nOldCells = mesh.nCells();
|
||||
|
||||
const polyBoundaryMesh& pbm = mesh.boundaryMesh();
|
||||
labelList oldPatchStarts(pbm.size());
|
||||
labelList oldPatchNMeshPoints(pbm.size());
|
||||
forAll(pbm, patchI)
|
||||
{
|
||||
oldPatchStarts[patchI] = pbm[patchI].start();
|
||||
oldPatchNMeshPoints[patchI] = pbm[patchI].nPoints();
|
||||
}
|
||||
|
||||
mapPtr.reset
|
||||
(
|
||||
new mapDistributePolyMesh
|
||||
(
|
||||
nOldPoints,
|
||||
nOldFaces,
|
||||
nOldCells,
|
||||
std::move(oldPatchStarts),
|
||||
std::move(oldPatchNMeshPoints),
|
||||
std::move(pointMap),
|
||||
std::move(faceMap),
|
||||
std::move(cellMap),
|
||||
std::move(patchMap)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return mapPtr;
|
||||
}
|
||||
|
||||
|
||||
void readProcAddressing
|
||||
(
|
||||
const fvMesh& mesh,
|
||||
const autoPtr<fvMesh>& baseMeshPtr,
|
||||
autoPtr<mapDistributePolyMesh>& distMap
|
||||
)
|
||||
{
|
||||
//IOobject io
|
||||
//(
|
||||
// "procAddressing",
|
||||
// mesh.facesInstance(),
|
||||
// polyMesh::meshSubDir,
|
||||
// mesh,
|
||||
// IOobject::MUST_READ
|
||||
//);
|
||||
//if (io.typeHeaderOk<labelIOList>(true))
|
||||
//{
|
||||
// Pout<< "Reading addressing from " << io.name() << " at "
|
||||
// << mesh.facesInstance() << nl << endl;
|
||||
// distMap.reset(new IOmapDistributePolyMesh(io));
|
||||
//}
|
||||
//else
|
||||
{
|
||||
Info<< "Reading addressing from procXXXAddressing at "
|
||||
<< mesh.facesInstance() << nl << endl;
|
||||
labelIOList cellProcAddressing
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"cellProcAddressing",
|
||||
mesh.facesInstance(),
|
||||
polyMesh::meshSubDir,
|
||||
mesh,
|
||||
IOobject::READ_IF_PRESENT
|
||||
),
|
||||
labelList()
|
||||
);
|
||||
labelIOList faceProcAddressing
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"faceProcAddressing",
|
||||
mesh.facesInstance(),
|
||||
polyMesh::meshSubDir,
|
||||
mesh,
|
||||
IOobject::READ_IF_PRESENT
|
||||
),
|
||||
labelList()
|
||||
);
|
||||
labelIOList pointProcAddressing
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"pointProcAddressing",
|
||||
mesh.facesInstance(),
|
||||
polyMesh::meshSubDir,
|
||||
mesh,
|
||||
IOobject::READ_IF_PRESENT
|
||||
),
|
||||
labelList()
|
||||
);
|
||||
labelIOList boundaryProcAddressing
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"boundaryProcAddressing",
|
||||
mesh.facesInstance(),
|
||||
polyMesh::meshSubDir,
|
||||
mesh,
|
||||
IOobject::READ_IF_PRESENT
|
||||
),
|
||||
labelList()
|
||||
);
|
||||
|
||||
|
||||
if
|
||||
(
|
||||
mesh.nCells() != cellProcAddressing.size()
|
||||
|| mesh.nPoints() != pointProcAddressing.size()
|
||||
|| mesh.nFaces() != faceProcAddressing.size()
|
||||
|| mesh.boundaryMesh().size() != boundaryProcAddressing.size()
|
||||
)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Read addressing inconsistent with mesh sizes" << nl
|
||||
<< "cells:" << mesh.nCells()
|
||||
<< " addressing:" << cellProcAddressing.objectPath()
|
||||
<< " size:" << cellProcAddressing.size() << nl
|
||||
<< "faces:" << mesh.nFaces()
|
||||
<< " addressing:" << faceProcAddressing.objectPath()
|
||||
<< " size:" << faceProcAddressing.size() << nl
|
||||
<< "points:" << mesh.nPoints()
|
||||
<< " addressing:" << pointProcAddressing.objectPath()
|
||||
<< " size:" << pointProcAddressing.size()
|
||||
<< "patches:" << mesh.boundaryMesh().size()
|
||||
<< " addressing:" << boundaryProcAddressing.objectPath()
|
||||
<< " size:" << boundaryProcAddressing.size()
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
distMap.clear();
|
||||
distMap = createReconstructMap
|
||||
(
|
||||
baseMeshPtr,
|
||||
mesh,
|
||||
cellProcAddressing,
|
||||
faceProcAddressing,
|
||||
pointProcAddressing,
|
||||
boundaryProcAddressing
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void reconstructMeshFields
|
||||
(
|
||||
const parFvFieldReconstructor& fvReconstructor,
|
||||
@ -2745,9 +2184,11 @@ int main(int argc, char *argv[])
|
||||
// Check who has a mesh (by checking for 'faces' file)
|
||||
const boolList haveMesh
|
||||
(
|
||||
haveFacesFile
|
||||
haveMeshFile
|
||||
(
|
||||
runTime.path()/facesInstance/meshSubDir
|
||||
runTime,
|
||||
facesInstance/meshSubDir,
|
||||
"faces"
|
||||
)
|
||||
);
|
||||
|
||||
@ -2840,22 +2281,22 @@ int main(int argc, char *argv[])
|
||||
)
|
||||
{
|
||||
Info<< "loading mesh from " << facesInstance << endl;
|
||||
autoPtr<fvMesh> meshPtr = loadOrCreateMesh
|
||||
autoPtr<fvMesh> meshPtr = fvMeshTools::loadOrCreateMesh
|
||||
(
|
||||
decompose,
|
||||
IOobject
|
||||
(
|
||||
regionName,
|
||||
facesInstance,
|
||||
runTime,
|
||||
Foam::IOobject::MUST_READ
|
||||
)
|
||||
),
|
||||
decompose
|
||||
);
|
||||
fvMesh& mesh = meshPtr();
|
||||
|
||||
// Use basic geometry calculation to avoid synchronisation
|
||||
// problems. See comment in routine
|
||||
setBasicGeometry(mesh);
|
||||
fvMeshTools::setBasicGeometry(mesh);
|
||||
|
||||
|
||||
// Determine decomposition
|
||||
@ -2919,20 +2360,20 @@ int main(int argc, char *argv[])
|
||||
true // read on master only
|
||||
);
|
||||
|
||||
setBasicGeometry(baseMeshPtr());
|
||||
fvMeshTools::setBasicGeometry(baseMeshPtr());
|
||||
|
||||
|
||||
Info<< "Reading local, decomposed mesh" << endl;
|
||||
autoPtr<fvMesh> meshPtr = loadOrCreateMesh
|
||||
autoPtr<fvMesh> meshPtr = fvMeshTools::loadOrCreateMesh
|
||||
(
|
||||
decompose,
|
||||
IOobject
|
||||
(
|
||||
regionName,
|
||||
baseMeshPtr().facesInstance(),
|
||||
runTime,
|
||||
Foam::IOobject::MUST_READ
|
||||
)
|
||||
),
|
||||
decompose
|
||||
);
|
||||
fvMesh& mesh = meshPtr();
|
||||
|
||||
@ -2949,7 +2390,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
// Read addressing back to base mesh
|
||||
autoPtr<mapDistributePolyMesh> distMap;
|
||||
readProcAddressing(mesh, baseMeshPtr, distMap);
|
||||
distMap = fvMeshTools::readProcAddressing(mesh, baseMeshPtr);
|
||||
|
||||
// Construct field mapper
|
||||
autoPtr<parFvFieldReconstructor> fvReconstructorPtr
|
||||
@ -3032,8 +2473,9 @@ int main(int argc, char *argv[])
|
||||
);
|
||||
}
|
||||
|
||||
// Re-read procXXXaddressing
|
||||
readProcAddressing(mesh, baseMeshPtr, distMap);
|
||||
// Re-read procaddressing
|
||||
distMap =
|
||||
fvMeshTools::readProcAddressing(mesh, baseMeshPtr);
|
||||
|
||||
// Reset field mapper
|
||||
fvReconstructorPtr.reset
|
||||
@ -3188,9 +2630,16 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
Pstream::scatter(masterInstDir);
|
||||
|
||||
// Check who has a mesh
|
||||
const fileName meshPath(runTime.path()/masterInstDir/meshSubDir);
|
||||
const boolList haveMesh(haveFacesFile(meshPath));
|
||||
// Check who has a polyMesh
|
||||
const boolList haveMesh
|
||||
(
|
||||
haveMeshFile
|
||||
(
|
||||
runTime,
|
||||
masterInstDir/meshSubDir,
|
||||
"faces"
|
||||
)
|
||||
);
|
||||
|
||||
// Collect objectPath of polyMesh for the current file handler. This
|
||||
// is where the mesh would be written if it didn't exist already.
|
||||
@ -3222,17 +2671,16 @@ int main(int argc, char *argv[])
|
||||
runTime.processorCase(false);
|
||||
}
|
||||
|
||||
autoPtr<fvMesh> meshPtr = loadOrCreateMesh
|
||||
autoPtr<fvMesh> meshPtr = fvMeshTools::loadOrCreateMesh
|
||||
(
|
||||
decompose,
|
||||
//haveMesh[Pstream::myProcNo()],
|
||||
IOobject
|
||||
(
|
||||
regionName,
|
||||
masterInstDir,
|
||||
runTime,
|
||||
Foam::IOobject::MUST_READ
|
||||
)
|
||||
),
|
||||
decompose
|
||||
);
|
||||
fvMesh& mesh = meshPtr();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user