83 static const scalar defaultMergeTol = 1
e-7;
93 const label masterMeshProcStart,
94 const label masterMeshProcEnd,
96 const label meshToAddProcStart,
97 const label meshToAddProcEnd,
99 const scalar mergeDist
102 if (fullMatch || masterMesh.
nCells() == 0)
127 forAll(masterPatches, patchi)
129 const polyPatch& pp = masterPatches[patchi];
131 if (isA<processorPolyPatch>(pp))
135 label proci=meshToAddProcStart;
136 proci<meshToAddProcEnd;
140 const string toProcString(
"to" +
name(proci));
142 pp.
name().rfind(toProcString)
143 == (pp.
name().size()-toProcString.size())
146 label meshFacei = pp.
start();
149 masterFaces.append(meshFacei++);
157 masterFaces.shrink();
171 forAll(addPatches, patchi)
173 const polyPatch& pp = addPatches[patchi];
175 if (isA<processorPolyPatch>(pp))
177 bool isConnected =
false;
181 label mergedProci=masterMeshProcStart;
182 !isConnected && (mergedProci < masterMeshProcEnd);
188 label proci = meshToAddProcStart;
189 proci < meshToAddProcEnd;
193 const word fromProcString
198 if (pp.
name() == fromProcString)
208 label meshFacei = pp.
start();
211 addFaces.append(meshFacei++);
236 const scalar mergeDist,
252 Info<<
"mergeSharedPoints : detected " << pointToMaster.size()
253 <<
" points that are to be merged." <<
endl;
274 forAll(pointProcAddressing, proci)
276 labelList& constructMap = pointProcAddressing[proci];
280 label oldPointi = constructMap[i];
283 label
newPointi = map().reversePointMap()[oldPointi];
296 <<
"Problem. oldPointi:" << oldPointi
314 for (
const Time& procDb : databases)
325 if (pointsInstance != procDb.timeName())
328 <<
"Your time was specified as " << procDb.timeName()
329 <<
" but there is no polyMesh/points in that time." <<
nl 330 <<
"(points file at " << pointsInstance <<
')' <<
nl 331 <<
"Please rerun with the correct time specified" 332 <<
" (through the -constant, -time or -latestTime " 333 <<
"(at your option)." 337 Info<<
"Reading points from " 339 <<
" for time = " << procDb.timeName()
367 void writeDistribution
390 forAll(cellProcAddressing, proci)
392 const labelList& pCells = cellProcAddressing[proci];
396 cellDecomposition.write();
398 Info<<
nl <<
"Wrote decomposition to " 399 << cellDecomposition.objectRelPath()
400 <<
" for use in manual decomposition." <<
endl;
425 zeroGradientFvPatchScalarField::typeName
428 forAll(cellDecomposition, celli)
430 cellDist[celli] = cellDecomposition[celli];
433 cellDist.correctBoundaryConditions();
436 Info<<
nl <<
"Wrote decomposition to " 437 << cellDist.objectRelPath()
438 <<
" (volScalarField) for visualization." 461 Info<<
nl <<
"Writing merged mesh to " 467 <<
"Failed writing polyMesh." 476 const label masterInternalFaces,
505 Info<<
"Writing addressing : " << outputDir <<
nl;
509 Info<<
" pointProcAddressing" <<
endl;
510 ioAddr.
rename(
"pointProcAddressing");
514 Info<<
" faceProcAddressing" <<
endl;
515 ioAddr.
rename(
"faceProcAddressing");
516 labelIOList faceProcAddr(ioAddr, faceProcAddressing);
520 forAll(faceProcAddr, procFacei)
522 const label masterFacei = faceProcAddr[procFacei];
526 !procMesh.isInternalFace(procFacei)
527 && masterFacei < masterInternalFaces
533 label procOwn = procMesh.faceOwner()[procFacei];
534 label masterOwn = masterOwner[masterFacei];
536 if (cellProcAddressing[procOwn] == masterOwn)
539 faceProcAddr[procFacei]++;
544 faceProcAddr[procFacei] = -1 - faceProcAddr[procFacei];
550 faceProcAddr[procFacei]++;
554 faceProcAddr.write();
558 Info<<
" cellProcAddressing" <<
endl;
559 ioAddr.
rename(
"cellProcAddressing");
564 Info<<
" boundaryProcAddressing" <<
endl;
565 ioAddr.
rename(
"boundaryProcAddressing");
575 "Merge individual processor meshes back into one master mesh.\n" 576 "Use if the original master mesh has been deleted or the processor meshes\n" 577 "have been modified (topology change).\n" 578 "This tool will write the resulting mesh to a new time step and construct\n" 579 "xxxxProcAddressing files in the processor meshes so reconstructPar can be\n" 580 "used to regenerate the fields on the master mesh.\n\n" 581 "Not well tested & use at your own risk!\n\n";
585 int main(
int argc,
char *argv[])
589 "Reconstruct a mesh using geometric/topological information only" 602 "Create procAddressing only without overwriting the mesh" 608 "The merge distance relative to the bounding box size (default 1e-7)" 613 "Do (slower) geometric matching on all boundary faces" 618 "Do matching on processor faces only" 623 "Write cell distribution as a labelList - for use with 'manual' " 624 "decomposition method or as a volScalarField for post-processing." 634 const bool fullMatch =
args.
found(
"fullMatch");
635 const bool procMatch =
args.
found(
"procMatch");
636 const bool writeCellDist =
args.
found(
"cellDist");
638 const bool writeAddrOnly =
args.
found(
"addressing-only");
640 const scalar mergeTol =
645 Info<<
"Use geometric matching on all boundary faces." <<
nl <<
endl;
649 Info<<
"Use geometric matching on correct procBoundaries only." <<
nl 650 <<
"This assumes a correct decomposition." <<
endl;
654 Info<<
"Merge assuming correct, fully matched procBoundaries." <<
nl 658 if (fullMatch || procMatch)
660 const scalar writeTol =
663 Info<<
"Merge tolerance : " << mergeTol <<
nl 664 <<
"Write tolerance : " << writeTol <<
endl;
669 && mergeTol < writeTol
673 <<
"Your current settings specify ASCII writing with " 675 <<
"Your merging tolerance (" << mergeTol <<
")" 676 <<
" is finer than this." <<
endl 677 <<
"Please change your writeFormat to binary" 678 <<
" or increase the writePrecision" <<
endl 679 <<
"or adjust the merge tolerance (-mergeTol)." 693 <<
"No regions specified or detected." 713 <<
"No processor* directories found" 720 Info<<
"Found " << nProcs <<
" processor directories" <<
endl;
723 Info<<
" Reading database " 746 databases[0].times(),
759 databases[proci].setTime(timeDirs[timei], timei);
765 label nMeshChanged = 0;
789 hasRegionMesh[regioni] =
true;
808 if (!hasRegionMesh[regioni])
828 label masterInternalFaces;
840 const scalar mergeDist = mergeTol*bb.
mag();
842 Info<<
"Overall mesh bounding box : " << bb <<
nl 843 <<
"Relative tolerance : " << mergeTol <<
nl 844 <<
"Absolute matching distance : " << mergeDist <<
nl 851 for (label proci=0; proci<nProcs; proci++)
883 boundProcAddressing[proci] =
908 renumber(map().addedCellMap(), cellProcAddressing[proci]);
909 renumber(map().addedFaceMap(), faceProcAddressing[proci]);
910 renumber(map().addedPointMap(), pointProcAddressing[proci]);
911 renumber(map().addedPatchMap(), boundProcAddressing[proci]);
913 for (label step=2; step<nProcs*2; step*=2)
915 for (label proci=0; proci<nProcs; proci+=step)
917 label next = proci + step/2;
923 Info<<
"Merging mesh " << proci <<
" with " 948 for (label mergedI=proci; mergedI<next; mergedI++)
953 cellProcAddressing[mergedI]
959 faceProcAddressing[mergedI]
965 pointProcAddressing[mergedI]
972 boundProcAddressing[mergedI]
980 addedI<
min(proci+step, nProcs);
986 map().addedCellMap(),
987 cellProcAddressing[addedI]
992 map().addedFaceMap(),
993 faceProcAddressing[addedI]
998 map().addedPointMap(),
999 pointProcAddressing[addedI]
1004 map().addedPatchMap(),
1005 boundProcAddressing[addedI]
1009 masterMesh.
set(next,
nullptr);
1013 for (label proci=0; proci<nProcs; proci++)
1015 Info<<
"Reading mesh to add from " 1016 << databases[proci].caseName()
1017 <<
" for time = " << databases[proci].timeName()
1023 mergeSharedPoints(mergeDist,masterMesh[0],pointProcAddressing);
1027 masterOwner = masterMesh[0].
faceOwner();
1033 <<
"Disabled writing of merged mesh (-addressing-only)" 1039 writeMesh(masterMesh[0], cellProcAddressing);
1055 for (label proci=0; proci<nProcs; proci++)
1111 const labelList& procFaces = localBoundaryFace[proci];
1112 remoteFaceStart[proci].
setSize(procFaces.
size(), 0);
1127 patchMap[proci].
setSize(nGlobalPatches);
1139 const labelList oldFaceOwner(fvMeshes[0].faceOwner());
1152 boundProcAddressing,
1165 const auto& pp = pbm[patchi];
1166 if (!isA<processorPolyPatch>(pp) || pp.size())
1168 oldToNew[patchi] = newi++;
1171 const label nNonProcPatches = newi;
1176 if (oldToNew[patchi] == -1)
1178 oldToNew[patchi] = newi++;
1189 masterMeshPtr.
cref(fvMeshes[0]);
1193 const fvMesh& masterMesh = masterMeshPtr();
1213 <<
"Disabled writing of merged mesh (-addressing-only)" 1218 Time& masterTime =
const_cast<Time&
>(masterMesh.
time());
1225 writeMesh(masterMesh, cellProcAddressing);
1235 masterTime.
caseName() = oldCaseName;
1243 Info<<
"Reconstructing addressing from processor meshes" 1244 <<
" to the newly reconstructed mesh" <<
nl <<
endl;
1248 Info<<
"Processor " << proci <<
nl 1249 <<
"Read processor mesh: " 1264 masterInternalFaces,
1267 cellProcAddressing[proci],
1268 faceProcAddressing[proci],
1269 pointProcAddressing[proci],
1270 boundProcAddressing[proci]
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
const Type & value() const noexcept
Return const reference to value.
static void addNote(const string ¬e)
Add extra notes for the usage information.
void size(const label n)
Older name for setAddressableSize.
fileName path() const
Return path.
Info<< "Creating field kinetic energy K\"<< endl;volScalarField K("K", 0.5 *magSqr(U));if(U.nOldTimes()){ volVectorField *Uold=&U.oldTime();volScalarField *Kold=&K.oldTime();*Kold==0.5 *magSqr(*Uold);while(Uold->nOldTimes()) { Uold=&Uold-> oldTime()
A class for handling file names.
errorManipArg< error, int > exit(error &err, const int errNo=1)
const fileName & facesInstance() const
Return the current instance directory for faces.
label nPoints() const noexcept
Number of mesh points.
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
const word & regionName() const
The mesh region name or word::null if polyMesh::defaultRegion.
virtual bool write(const bool valid=true) const
Write mesh using IO settings from time.
IntListType renumber(const labelUList &oldToNew, const IntListType &input)
Renumber the values (not the indices) of a list.
const fileName & caseName() const noexcept
Return case name.
constexpr char nl
The newline '\n' character (0x0a)
bool empty() const noexcept
True if the UList is empty (ie, size() is zero)
static word meshSubDir
Return the mesh sub-directory name (usually "polyMesh")
static word newName(const label myProcNo, const label neighbProcNo)
Return the name of a processorPolyPatch.
Ostream & endl(Ostream &os)
Add newline and flush stream.
fileName relativePath(const fileName &input, const bool caseTag=false) const
Return the input relative to the globalPath by stripping off a leading value of the globalPath...
static unsigned int defaultPrecision() noexcept
Return the default precision.
static void addBoolOption(const word &optName, const string &usage="", bool advanced=false)
Add a bool option to validOptions with usage information.
static void noParallel()
Remove the parallel options.
autoPtr< fileOperation > fileHandler(std::nullptr_t)
Delete current file handler.
A bounding box defined in terms of min/max extrema points.
Ignore writing from objectRegistry::writeObject()
const dimensionSet dimless
Dimensionless.
T getOrDefault(const word &optName, const T &deflt) const
Get a value from the named option if present, or return default.
const Time & time() const
Return the top-level database.
const T & cref() const
Return const reference to the object or to the contents of a (non-null) managed pointer.
label nFaces() const noexcept
Number of mesh faces.
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
A class for managing references or pointers (no reference counting)
instantList select(const instantList ×) const
Select a list of Time values that are within the ranges.
bool processorCase() const noexcept
Return true if this is a processor case.
bool allowFunctionObjects() const
The controlDict 'functions' entry is allowed to be used.
#define forAll(list, i)
Loop across all elements in list.
void write(vtk::formatter &fmt, const Type &val, const label n=1)
Component-wise write of a value (N times)
Foam::word regionName(Foam::polyMesh::defaultRegion)
bool allowLibs() const
The controlDict 'libs' entry is allowed to be used. (eg, has not been disabled by the -no-libs option...
void add(const boundBox &bb)
Extend to include the second box.
static void removeFiles(const polyMesh &)
Helper: remove all sets files from mesh instance.
bool returnReduceAnd(const bool value, const label comm=UPstream::worldComm)
Perform logical (and) MPI Allreduce on a copy. Uses UPstream::reduceAnd.
const dimensionedScalar e
Elementary charge.
void setSize(const label n)
Alias for resize()
virtual void updateMesh(const mapPolyMesh &mpm)
Update mesh corresponding to the given map.
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
labelList identity(const label len, label start=0)
Return an identity map of the given length with (map[i] == i)
static void mergePoints(const polyMesh &, const Map< label > &pointToMaster, polyTopoChange &meshMod)
Helper: Merge points.
A class for handling words, derived from Foam::string.
const Time & time() const noexcept
Return time registry.
static word defaultRegion
Return the default region name.
scalar mag() const
The magnitude/length of the bounding box diagonal.
label size() const noexcept
The number of elements in the list.
Foam::PtrList< Foam::fvMesh > meshes(regionNames.size())
static autoPtr< mapAddedPolyMesh > add(fvMesh &mesh0, const fvMesh &mesh1, const faceCoupleInfo &coupleInfo, const bool validBoundary=true, const bool fullyMapped=false)
Inplace add mesh to fvMesh. Maps all stored fields. Returns map.
virtual const labelList & faceOwner() const
Return face owner.
static void addVerboseOption(const string &usage, bool advanced=false)
Enable a 'verbose' bool option, with usage information.
static void addOption(const word &optName, const string ¶m="", const string &usage="", bool advanced=false)
Add an option to validOptions with usage information.
virtual void setTime(const Time &t)
Reset the time and time-index to those of the given time.
label nInternalFaces() const noexcept
Number of internal faces.
label timeIndex() const noexcept
Return current time index.
static word controlDictName
The default control dictionary name (normally "controlDict")
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
A list of pointers to objects of type <T>, without allocation/deallocation management of the pointers...
errorManip< error > abort(error &err)
const T * set(const label i) const
Return const pointer to element (can be nullptr), or nullptr for out-of-range access (ie...
const fileName & caseName() const noexcept
Return case name (parallel run) or global case (serial run)
static label procPatchPairs(const UPtrList< polyMesh > &meshes, List< DynamicList< label >> &localPatch, List< DynamicList< label >> &remoteMesh, List< DynamicList< label >> &remotePatch)
Helper: find pairs of processor patches. Return number of non-processor patches.
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO...
const word & name() const noexcept
The patch name.
static word timeName(const scalar t, const int precision=precision_)
Return time name of given scalar time formatted with the given precision.
const word & constant() const noexcept
Return constant name.
const fileName & rootPath() const noexcept
Return root path.
const faceZoneMesh & faceZones() const noexcept
Return face zone mesh.
virtual void rename(const word &newName)
Rename.
IOstreamOption::streamFormat writeFormat() const noexcept
The write stream format.
fileName path() const
Return the full path to the (processor local) case.
dimensionedScalar pow(const dimensionedScalar &ds, const dimensionedScalar &expt)
const pointZoneMesh & pointZones() const noexcept
Return point zone mesh.
UIndirectList< label > labelUIndList
UIndirectList of labels.
static void patchFacePairs(const UPtrList< polyMesh > &meshes, const List< DynamicList< label >> &localPatch, const List< DynamicList< label >> &remoteMesh, const List< DynamicList< label >> &remotePatch, labelListList &localBoundaryFace, labelListList &remoteFaceMesh, labelListList &remoteBoundaryFace)
Helper: expand list of coupled patches into pairs of coupled faces.
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
label nCells() const noexcept
Number of mesh cells.
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers...
Mesh data needed to do the Finite Volume discretisation.
Direct mesh changes based on v1.3 polyTopoChange syntax.
label start() const
Return start label of this patch in the polyMesh face list.
const cellZoneMesh & cellZones() const noexcept
Return cell zone mesh.
messageStream Info
Information stream (stdout output on master, null elsewhere)
Pointer management similar to std::unique_ptr, with some additional methods and type checking...
Mesh consisting of general polyhedral cells.
static autoPtr< T > New(Args &&... args)
Construct autoPtr with forwarding arguments.
A patch is a list of labels that address the faces in the global face list.
Foam::argList args(argc, argv)
A IOList wrapper for writing external data.
Defines the attributes of an object for which implicit objectRegistry management is supported...
A primitive field of type <T> with automated input and output.
static void writeMaps(Ostream &os, const word &key, const labelListList &maps)
static const word & regionName(const word ®ion)
The mesh region name or word::null if polyMesh::defaultRegion.
static Map< label > findSharedPoints(const polyMesh &, const scalar mergeTol)
Find topologically and geometrically shared points.
bool found(const word &optName) const
Return true if the named option is found.
static void addOptions(const bool constant=true, const bool withZero=false)
Add timeSelector options to argList::validOptions.
bool set(const Key &key, const T &obj)
Copy assign a new entry, overwriting existing entries.
static constexpr const zero Zero
Global zero (0)