reconstructPar: Reconstruct the mesh

The reconstructPar utility now reconstructs the mesh if and when it is
necessary to do so. The reconstructParMesh utility is therefore no
longer necessary and has been removed.

It was necessary/advantagous to consolidate these utilities into one
because in the case of mesh changes it becomes increasingly less clear
which of the separate utilities is responsible for reconstructing data
that is neither clearly physical field nor mesh topology; e.g., moving
points, sets, refinement data, and so on.
This commit is contained in:
Will Bainbridge
2022-06-07 08:36:12 +01:00
parent b48abc78f5
commit c3ab704513
19 changed files with 1222 additions and 1346 deletions

View File

@ -164,36 +164,12 @@ void decomposeUniform
void writeDecomposition(const domainDecomposition& meshes)
{
const labelList& procIds = meshes.cellToProc();
// Write the decomposition as labelList for use with 'manual'
// decomposition method.
labelIOList cellDecomposition
(
IOobject
(
"cellDecomposition",
meshes.completeMesh().facesInstance(),
meshes.completeMesh(),
IOobject::NO_READ,
IOobject::NO_WRITE,
false
),
procIds
);
cellDecomposition.write();
Info<< nl << "Wrote decomposition to "
<< cellDecomposition.relativeObjectPath()
<< " for use in manual decomposition." << endl;
// Write as volScalarField for postprocessing.
volScalarField::Internal cellDist
volScalarField::Internal cellProc
(
IOobject
(
"cellDist",
"cellProc",
meshes.completeMesh().time().timeName(),
meshes.completeMesh(),
IOobject::NO_READ,
@ -201,14 +177,14 @@ void writeDecomposition(const domainDecomposition& meshes)
),
meshes.completeMesh(),
dimless,
scalarField(scalarList(procIds))
scalarField(scalarList(meshes.cellProc()))
);
cellDist.write();
cellProc.write();
Info<< nl << "Wrote decomposition as volScalarField to "
<< cellDist.name() << " for use in postprocessing."
<< endl;
Info<< "Wrote decomposition as volScalarField to "
<< cellProc.name() << " for use in postprocessing."
<< nl << endl;
}
@ -281,8 +257,7 @@ int main(int argc, char *argv[])
if (decomposeGeomOnly)
{
Info<< "Skipping decomposing fields"
<< nl << endl;
Info<< "Skipping decomposing fields" << nl << endl;
if (decomposeFieldsOnly || copyZero)
{
@ -304,65 +279,71 @@ int main(int argc, char *argv[])
const wordList regionNames =
selectRegionNames(args, runTimes.completeTime());
// Handle existing decomposition directories
// Remove existing processor directories if requested
if (forceOverwrite)
{
// Determine the processor count from the directories
label nProcs = fileHandler().nProcs(runTimes.completeTime().path());
if (forceOverwrite)
if (region)
{
if (region)
FatalErrorInFunction
<< "Cannot force the decomposition of a single region"
<< exit(FatalError);
}
const label nProcs0 =
fileHandler().nProcs(runTimes.completeTime().path());
Info<< "Removing " << nProcs0
<< " existing processor directories" << endl;
// Remove existing processor directories
const fileNameList dirs
(
fileHandler().readDir
(
runTimes.completeTime().path(),
fileType::directory
)
);
forAllReverse(dirs, diri)
{
const fileName& d = dirs[diri];
// Starts with 'processors'
if (d.find("processors") == 0)
{
FatalErrorInFunction
<< "Cannot force the decomposition of a single region"
<< exit(FatalError);
if (fileHandler().exists(d))
{
fileHandler().rmDir(d);
}
}
Info<< "Removing " << nProcs
<< " existing processor directories" << endl;
// Remove existing processors directory
fileNameList dirs
(
fileHandler().readDir
(
runTimes.completeTime().path(),
fileType::directory
)
);
forAllReverse(dirs, diri)
// Starts with 'processor'
if (d.find("processor") == 0)
{
const fileName& d = dirs[diri];
// Starts with 'processors'
if (d.find("processors") == 0)
// Check that integer after processor
fileName num(d.substr(9));
label proci = -1;
if (Foam::read(num.c_str(), proci))
{
if (fileHandler().exists(d))
{
fileHandler().rmDir(d);
}
}
// Starts with 'processor'
if (d.find("processor") == 0)
{
// Check that integer after processor
fileName num(d.substr(9));
label proci = -1;
if (Foam::read(num.c_str(), proci))
{
if (fileHandler().exists(d))
{
fileHandler().rmDir(d);
}
}
}
}
}
else if (nProcs && !region && !decomposeFieldsOnly)
}
// Check the specified number of processes is consistent with any existing
// processor directories
{
const label nProcs0 =
fileHandler().nProcs(runTimes.completeTime().path());
if (nProcs0 && nProcs0 != runTimes.nProcs())
{
FatalErrorInFunction
<< "Case is already decomposed with " << nProcs
<< "Case is already decomposed with " << nProcs0
<< " domains, use the -force option or manually" << nl
<< "remove processor directories before decomposing. e.g.,"
<< nl
@ -413,25 +394,14 @@ int main(int argc, char *argv[])
// Create meshes
Info<< "Create mesh" << endl;
domainDecomposition meshes(runTimes, regionName);
meshes.readComplete();
// Read or generate a decomposition as necessary
if (decomposeFieldsOnly)
if (!decomposeFieldsOnly || !copyZero)
{
meshes.readProcs();
if (!copyZero)
if (meshes.readDecompose(decomposeSets) && writeCellDist)
{
meshes.readAddressing();
meshes.readUpdate();
writeDecomposition(meshes);
fileHandler().flush();
}
}
else
{
meshes.decompose();
meshes.writeProcs(decomposeSets);
if (writeCellDist) writeDecomposition(meshes);
fileHandler().flush();
}
// Field maps. These are preserved if decomposing multiple times.
PtrList<fvFieldDecomposer> fieldDecomposerList
@ -448,10 +418,10 @@ int main(int argc, char *argv[])
);
// Loop over all times
forAll(times, timeI)
forAll(times, timei)
{
// Set the time
runTimes.setTime(times[timeI], timeI);
runTimes.setTime(times[timei], timei);
Info<< "Time = " << runTimes.completeTime().userTimeName() << endl;
@ -459,7 +429,7 @@ int main(int argc, char *argv[])
fvMesh::readUpdateState state = fvMesh::UNCHANGED;
if (!decomposeFieldsOnly || !copyZero)
{
state = meshes.readUpdate();
state = meshes.readUpdateDecompose();
}
// Write the mesh out, if necessary
@ -467,18 +437,20 @@ int main(int argc, char *argv[])
{
// Nothing to do
}
else if (state == fvMesh::POINTS_MOVED)
{
meshes.writeProcs(false);
}
else if
(
state == fvMesh::TOPO_CHANGE
|| state == fvMesh::TOPO_PATCH_CHANGE
)
else if (state != fvMesh::UNCHANGED)
{
meshes.writeProcs(decomposeSets);
if (writeCellDist) writeDecomposition(meshes);
}
// Write the decomposition, if necessary
if
(
writeCellDist
&& meshes.completeMesh().facesInstance()
== runTimes.completeTime().timeName()
)
{
writeDecomposition(meshes);
fileHandler().flush();
}
@ -510,10 +482,9 @@ int main(int argc, char *argv[])
runTimes.completeTime().timePath();
fileName prevProcTimePath;
for (label proci = 0; proci < meshes.nProcs(); proci++)
for (label proci = 0; proci < runTimes.nProcs(); proci++)
{
const Time& procRunTime =
meshes.procMeshes()[proci].time();
const Time& procRunTime = runTimes.procTimes()[proci];
if (fileHandler().isDir(completeTimePath))
{

View File

@ -48,7 +48,6 @@ SourceFiles
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class fvFieldReconstructor Declaration
\*---------------------------------------------------------------------------*/

View File

@ -169,6 +169,8 @@ void Foam::pointFieldReconstructor::reconstructFields
Info<< " " << fieldIter()->name() << endl;
reconstructField<Type>(*fieldIter())().write();
nReconstructed_++;
}
}

View File

@ -45,25 +45,56 @@ Description
namespace Foam
{
bool haveAllTimes
(
const HashSet<word>& masterTimeDirSet,
const instantList& timeDirs
)
bool haveAllTimes
(
const HashSet<word>& masterTimeDirSet,
const instantList& timeDirs
)
{
// Loop over all times
forAll(timeDirs, timei)
{
// Loop over all times
forAll(timeDirs, timei)
if (!masterTimeDirSet.found(timeDirs[timei].name()))
{
if (!masterTimeDirSet.found(timeDirs[timei].name()))
{
return false;
}
return false;
}
return true;
}
return true;
}
void writeDecomposition(const domainDecomposition& meshes)
{
// Write as volScalarField for postprocessing.
volScalarField::Internal cellProc
(
IOobject
(
"cellProc",
meshes.completeMesh().time().timeName(),
meshes.completeMesh(),
IOobject::NO_READ,
IOobject::AUTO_WRITE
),
meshes.completeMesh(),
dimless,
scalarField(scalarList(meshes.cellProc()))
);
cellProc.write();
Info<< "Wrote decomposition as volScalarField to "
<< cellProc.name() << " for use in postprocessing."
<< nl << endl;
}
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
int main(int argc, char *argv[])
{
argList::addNote
@ -77,6 +108,12 @@ int main(int argc, char *argv[])
argList::noParallel();
#include "addRegionOption.H"
#include "addAllRegionsOption.H"
argList::addBoolOption
(
"cellDist",
"write cell distribution as a labelList - for use with 'manual' "
"decomposition method or as a volScalarField for post-processing."
);
argList::addOption
(
"fields",
@ -115,6 +152,8 @@ int main(int argc, char *argv[])
#include "setRootCase.H"
const bool writeCellDist = args.optionFound("cellDist");
HashSet<word> selectedFields;
if (args.optionFound("fields"))
{
@ -225,25 +264,12 @@ int main(int argc, char *argv[])
const word& regionDir = Foam::regionDir(regionName);
// Create meshes
Info<< "\n\nReconstructing fields for mesh " << regionName
<< nl << endl;
Info<< "\n\nReconstructing mesh " << regionName << nl << endl;
domainDecomposition meshes(runTimes, regionName);
meshes.readComplete();
meshes.readProcs();
meshes.readAddressing();
meshes.readUpdate();
// Write the complete mesh if at the constant instant. Otherwise
// mesh-associated things (sets, hexRef8, ...) will not be written by
// domainDecomposition because there is no change of mesh to trigger
// them to write.
if
(
runTimes.completeTime().timeName()
== runTimes.completeTime().constant()
)
if (meshes.readReconstruct(!noReconstructSets) && writeCellDist)
{
meshes.writeComplete(!noReconstructSets);
writeDecomposition(meshes);
fileHandler().flush();
}
// Loop over all times
@ -263,20 +289,27 @@ int main(int argc, char *argv[])
<< nl << endl;
// Update the meshes
const fvMesh::readUpdateState state = meshes.readUpdate();
if (state == fvMesh::POINTS_MOVED)
{
meshes.writeComplete(false);
}
if
(
state == fvMesh::TOPO_CHANGE
|| state == fvMesh::TOPO_PATCH_CHANGE
)
const fvMesh::readUpdateState state =
meshes.readUpdateReconstruct();
// Write the mesh out, if necessary
if (state != fvMesh::UNCHANGED)
{
meshes.writeComplete(!noReconstructSets);
}
// Write the decomposition, if necessary
if
(
writeCellDist
&& meshes.completeMesh().facesInstance()
== runTimes.completeTime().timeName()
)
{
writeDecomposition(meshes);
fileHandler().flush();
}
// Get list of objects from processor0 database
IOobjectList objects
(

View File

@ -1,3 +0,0 @@
reconstructParMesh.C
EXE = $(FOAM_APPBIN)/reconstructParMesh

View File

@ -1,10 +0,0 @@
EXE_INC = \
-I$(LIB_SRC)/dynamicMesh/lnInclude \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/regionModels/regionModel/lnInclude
EXE_LIBS = \
-ldynamicMesh \
-lmeshTools \
-lregionModels

View File

@ -1,693 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
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/>.
Application
reconstructParMesh
Description
Reconstructs a mesh.
Writes point/face/cell procAddressing so afterwards reconstructPar can be
used to reconstruct fields.
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "timeSelector.H"
#include "IOobjectList.H"
#include "labelIOList.H"
#include "processorPolyPatch.H"
#include "mapAddedPolyMesh.H"
#include "polyMeshAdder.H"
#include "faceCoupleInfo.H"
#include "fvMeshAdder.H"
#include "polyTopoChange.H"
#include "extrapolatedCalculatedFvPatchFields.H"
#include "regionProperties.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
autoPtr<faceCoupleInfo> determineCoupledFaces
(
const label masterMeshProcStart,
const label masterMeshProcEnd,
const polyMesh& masterMesh,
const label meshToAddProcStart,
const label meshToAddProcEnd,
const polyMesh& meshToAdd
)
{
const polyBoundaryMesh& masterPatches = masterMesh.boundaryMesh();
const polyBoundaryMesh& addPatches = meshToAdd.boundaryMesh();
DynamicList<label> masterFaces
(
masterMesh.nFaces() - masterMesh.nInternalFaces()
);
DynamicList<label> addFaces
(
meshToAdd.nFaces() - meshToAdd.nInternalFaces()
);
for
(
label masterProci = masterMeshProcStart;
masterProci < masterMeshProcEnd;
masterProci++
)
{
for
(
label addProci = meshToAddProcStart;
addProci < meshToAddProcEnd;
addProci++
)
{
const word masterToAddName
(
"procBoundary" + name(masterProci) + "to" + name(addProci)
);
const word addToMasterName
(
"procBoundary" + name(addProci) + "to" + name(masterProci)
);
const label masterToAddID =
masterPatches.findPatchID(masterToAddName);
const label addToMasterID =
addPatches.findPatchID(addToMasterName);
if (masterToAddID != -1 && addToMasterID != -1)
{
const polyPatch& masterPp = masterPatches[masterToAddID];
forAll(masterPp, i)
{
masterFaces.append(masterPp.start() + i);
}
const polyPatch& addPp = addPatches[addToMasterID];
forAll(addPp, i)
{
addFaces.append(addPp.start() + i);
}
}
if ((masterToAddID != -1) != (addToMasterID != -1))
{
const label foundProci =
masterToAddID != -1 ? masterProci : addProci;
const word& foundName =
masterToAddID != -1 ? masterToAddName : addToMasterName;
const label missingProci =
masterToAddID != -1 ? addProci : masterProci;
const word& missingName =
masterToAddID != -1 ? addToMasterName : masterToAddName;
FatalErrorInFunction
<< "Patch " << foundName << " found on processor "
<< foundProci << " but corresponding patch "
<< missingName << " missing on processor "
<< missingProci << exit(FatalError);
}
}
}
masterFaces.shrink();
addFaces.shrink();
return autoPtr<faceCoupleInfo>
(
new faceCoupleInfo
(
masterMesh,
masterFaces,
meshToAdd,
addFaces
)
);
}
void writeCellDistribution
(
Time& runTime,
const fvMesh& masterMesh,
const labelListList& cellProcAddressing
)
{
// Write the decomposition as labelList for use with 'manual'
// decomposition method.
labelIOList cellDecomposition
(
IOobject
(
"cellDecomposition",
masterMesh.facesInstance(),
masterMesh,
IOobject::NO_READ,
IOobject::NO_WRITE,
false
),
masterMesh.nCells()
);
forAll(cellProcAddressing, proci)
{
const labelList& pCells = cellProcAddressing[proci];
UIndirectList<label>(cellDecomposition, pCells) = proci;
}
cellDecomposition.write();
Info<< nl << "Wrote decomposition to "
<< cellDecomposition.relativeObjectPath()
<< " for use in manual decomposition." << endl;
// Write as volScalarField for postprocessing. Change time to 0
// if was 'constant'
{
const scalar oldTime = runTime.value();
const label oldIndex = runTime.timeIndex();
if (runTime.timeName() == runTime.constant() && oldIndex == 0)
{
runTime.setTime(0, oldIndex+1);
}
volScalarField cellDist
(
IOobject
(
"cellDist",
runTime.timeName(),
masterMesh,
IOobject::NO_READ,
IOobject::AUTO_WRITE
),
masterMesh,
dimensionedScalar(dimless, 0),
extrapolatedCalculatedFvPatchScalarField::typeName
);
forAll(cellDecomposition, celli)
{
cellDist[celli] = cellDecomposition[celli];
}
cellDist.correctBoundaryConditions();
cellDist.write();
Info<< nl << "Wrote decomposition as volScalarField to "
<< cellDist.name() << " for use in postprocessing."
<< endl;
// Restore time
runTime.setTime(oldTime, oldIndex);
}
}
int main(int argc, char *argv[])
{
argList::addNote("reconstruct a mesh");
timeSelector::addOptions(true, true);
argList::noParallel();
argList::addBoolOption
(
"cellDist",
"write cell distribution as a labelList - for use with 'manual' "
"decomposition method or as a volScalarField for post-processing."
);
#include "addRegionOption.H"
#include "addAllRegionsOption.H"
#include "setRootCase.H"
#include "createTime.H"
const wordList regionNames(selectRegionNames(args, runTime));
if (regionNames.size() > 1)
{
Info<< "Operating on regions " << regionNames[0];
for (label regioni = 1; regioni < regionNames.size() - 1; ++ regioni)
{
Info<< ", " << regionNames[regioni];
}
Info<< " and " << regionNames.last() << nl << endl;
}
else if (regionNames[0] != polyMesh::defaultRegion)
{
Info<< "Operating on region " << regionNames[0] << nl << endl;
}
label nProcs = fileHandler().nProcs(args.path());
Info<< "Found " << nProcs << " processor directories" << nl << endl;
// Read all time databases
PtrList<Time> databases(nProcs);
forAll(databases, proci)
{
Info<< "Reading database "
<< args.caseName()/fileName(word("processor") + name(proci))
<< endl;
databases.set
(
proci,
new Time
(
Time::controlDictName,
args.rootPath(),
args.caseName()/fileName(word("processor") + name(proci))
)
);
}
// Use the times list from the master processor
// and select a subset based on the command-line options
instantList timeDirs = timeSelector::select
(
databases[0].times(),
args
);
// Loop over all times
forAll(timeDirs, timeI)
{
// Set time for global database
runTime.setTime(timeDirs[timeI], timeI);
Info<< "Time = " << runTime.userTimeName() << nl << endl;
// Set time for all databases
forAll(databases, proci)
{
databases[proci].setTime(timeDirs[timeI], timeI);
}
forAll(regionNames, regioni)
{
const word& regionName = regionNames[regioni];
const word regionDir =
regionName == polyMesh::defaultRegion
? word::null
: regionName;
IOobject facesIO
(
"faces",
databases[0].timeName(),
regionDir/polyMesh::meshSubDir,
databases[0],
IOobject::NO_READ,
IOobject::NO_WRITE
);
// Problem: faceCompactIOList recognises both 'faceList' and
// 'faceCompactList' so we cannot check the type
if (!facesIO.headerOk())
{
Info<< "No mesh." << nl << endl;
continue;
}
// Addressing from processor to reconstructed case
labelListList cellProcAddressing(nProcs);
labelListList faceProcAddressing(nProcs);
labelListList pointProcAddressing(nProcs);
// Internal faces on the final reconstructed mesh
label masterInternalFaces;
// Owner addressing on the final reconstructed mesh
labelList masterOwner;
{
// Construct empty mesh.
PtrList<fvMesh> masterMesh(nProcs);
// Read all the meshes
for (label proci=0; proci<nProcs; proci++)
{
masterMesh.set
(
proci,
new fvMesh
(
IOobject
(
regionName,
runTime.timeName(),
runTime,
IOobject::NO_READ
),
pointField(),
faceList(),
cellList()
)
);
fvMesh meshToAdd
(
IOobject
(
regionName,
databases[proci].timeName(),
databases[proci]
),
false
);
// Initialise its addressing
cellProcAddressing[proci] = identity(meshToAdd.nCells());
faceProcAddressing[proci] = identity(meshToAdd.nFaces());
pointProcAddressing[proci] = identity(meshToAdd.nPoints());
// Find shared points/faces
autoPtr<faceCoupleInfo> couples = determineCoupledFaces
(
proci,
proci,
masterMesh[proci],
proci,
proci,
meshToAdd
);
// Add elements to mesh
autoPtr<mapAddedPolyMesh> map = fvMeshAdder::add
(
masterMesh[proci],
meshToAdd,
couples
);
// Added processor
inplaceRenumber
(
map().addedCellMap(),
cellProcAddressing[proci]
);
inplaceRenumber
(
map().addedFaceMap(),
faceProcAddressing[proci]
);
inplaceRenumber
(
map().addedPointMap(),
pointProcAddressing[proci]
);
}
// Merge the meshes
for (label step=2; step<nProcs*2; step*=2)
{
for (label proci=0; proci<nProcs; proci+=step)
{
label next = proci + step/2;
if(next >= nProcs)
{
continue;
}
Info<< "Merging mesh " << proci << " with " << next
<< endl;
// Find shared points/faces
autoPtr<faceCoupleInfo> couples = determineCoupledFaces
(
proci,
next,
masterMesh[proci],
next,
proci+step,
masterMesh[next]
);
// Add elements to mesh
autoPtr<mapAddedPolyMesh> map = fvMeshAdder::add
(
masterMesh[proci],
masterMesh[next],
couples
);
// Processors that were already in masterMesh
for (label mergedI=proci; mergedI<next; mergedI++)
{
inplaceRenumber
(
map().oldCellMap(),
cellProcAddressing[mergedI]
);
inplaceRenumber
(
map().oldFaceMap(),
faceProcAddressing[mergedI]
);
inplaceRenumber
(
map().oldPointMap(),
pointProcAddressing[mergedI]
);
}
// Added processor
for
(
label addedI=next;
addedI<min(proci+step, nProcs);
addedI++
)
{
inplaceRenumber
(
map().addedCellMap(),
cellProcAddressing[addedI]
);
inplaceRenumber
(
map().addedFaceMap(),
faceProcAddressing[addedI]
);
inplaceRenumber
(
map().addedPointMap(),
pointProcAddressing[addedI]
);
}
masterMesh.set(next, nullptr);
}
}
for (label proci=0; proci<nProcs; proci++)
{
Info<< "Reading mesh to add from "
<< databases[proci].caseName()
<< " for time = " << databases[proci].timeName()
<< nl << nl << endl;
}
// Save some properties on the reconstructed mesh
masterInternalFaces = masterMesh[0].nInternalFaces();
masterOwner = masterMesh[0].faceOwner();
Info<< "\nWriting merged mesh to "
<< runTime.path()/runTime.timeName()
<< nl << endl;
if (!masterMesh[0].write())
{
FatalErrorInFunction
<< "Failed writing polyMesh."
<< exit(FatalError);
}
if (args.optionFound("cellDist"))
{
writeCellDistribution
(
runTime,
masterMesh[0],
cellProcAddressing
);
}
}
// Write the addressing
Info<< "Reconstructing the addressing from the processor meshes"
<< " to the newly reconstructed mesh" << nl << endl;
forAll(databases, proci)
{
Info<< "Reading processor " << proci << " mesh from "
<< databases[proci].caseName() << endl;
polyMesh procMesh
(
IOobject
(
regionName,
databases[proci].timeName(),
databases[proci]
)
);
// From processor point to reconstructed mesh point
Info<< "Writing pointProcAddressing to "
<< databases[proci].caseName()
/procMesh.facesInstance()
/polyMesh::meshSubDir
<< endl;
labelIOList
(
IOobject
(
"pointProcAddressing",
procMesh.facesInstance(),
polyMesh::meshSubDir,
procMesh,
IOobject::NO_READ,
IOobject::NO_WRITE,
false // Do not register
),
pointProcAddressing[proci]
).write();
// From processor face to reconstructed mesh face
Info<< "Writing faceProcAddressing to "
<< databases[proci].caseName()
/procMesh.facesInstance()
/polyMesh::meshSubDir
<< endl;
labelIOList faceProcAddr
(
IOobject
(
"faceProcAddressing",
procMesh.facesInstance(),
polyMesh::meshSubDir,
procMesh,
IOobject::NO_READ,
IOobject::NO_WRITE,
false // Do not register
),
faceProcAddressing[proci]
);
// Now add turning index to faceProcAddressing.
// See reconstructPar for meaning of turning index.
forAll(faceProcAddr, procFacei)
{
const label masterFacei = faceProcAddr[procFacei];
if
(
!procMesh.isInternalFace(procFacei)
&& masterFacei < masterInternalFaces
)
{
// proc face is now external but used to be internal
// face. Check if we have owner or neighbour.
label procOwn = procMesh.faceOwner()[procFacei];
label masterOwn = masterOwner[masterFacei];
if (cellProcAddressing[proci][procOwn] == masterOwn)
{
// No turning. Offset by 1.
faceProcAddr[procFacei]++;
}
else
{
// Turned face.
faceProcAddr[procFacei] =
-1 - faceProcAddr[procFacei];
}
}
else
{
// No turning. Offset by 1.
faceProcAddr[procFacei]++;
}
}
faceProcAddr.write();
// From processor cell to reconstructed mesh cell
Info<< "Writing cellProcAddressing to "
<< databases[proci].caseName()
/procMesh.facesInstance()
/polyMesh::meshSubDir
<< endl;
labelIOList
(
IOobject
(
"cellProcAddressing",
procMesh.facesInstance(),
polyMesh::meshSubDir,
procMesh,
IOobject::NO_READ,
IOobject::NO_WRITE,
false // Do not register
),
cellProcAddressing[proci]
).write();
Info<< endl;
}
}
}
Info<< "End.\n" << endl;
return 0;
}
// ************************************************************************* //