61 void printMeshData(
const polyMesh& mesh)
65 globalIndex globalCells(mesh.nCells());
68 const labelList& pPatches = mesh.globalData().processorPatches();
69 patchNeiProcNo[Pstream::myProcNo()].
setSize(pPatches.size());
70 patchSize[Pstream::myProcNo()].setSize(pPatches.size());
73 const processorPolyPatch& ppp = refCast<const processorPolyPatch>
75 mesh.boundaryMesh()[pPatches[i]]
77 patchNeiProcNo[Pstream::myProcNo()][i] = ppp.neighbProcNo();
78 patchSize[Pstream::myProcNo()][i] = ppp.size();
80 Pstream::gatherList(patchNeiProcNo);
81 Pstream::gatherList(patchSize);
86 globalIndex globalBoundaryFaces(mesh.nFaces()-mesh.nInternalFaces());
88 label maxProcCells = 0;
89 label totProcFaces = 0;
90 label maxProcPatches = 0;
91 label totProcPatches = 0;
92 label maxProcFaces = 0;
94 for (
label proci = 0; proci < Pstream::nProcs(); proci++)
97 <<
"Processor " << proci <<
nl 98 <<
" Number of cells = " << globalCells.localSize(proci)
101 label nProcFaces = 0;
103 const labelList& nei = patchNeiProcNo[proci];
105 forAll(patchNeiProcNo[proci], i)
107 Info<<
" Number of faces shared with processor " 108 << patchNeiProcNo[proci][i] <<
" = " << patchSize[proci][i]
111 nProcFaces += patchSize[proci][i];
114 Info<<
" Number of processor patches = " << nei.size() <<
nl 115 <<
" Number of processor faces = " << nProcFaces <<
nl 116 <<
" Number of boundary faces = " 117 << globalBoundaryFaces.localSize(proci) <<
endl;
119 maxProcCells =
max(maxProcCells, globalCells.localSize(proci));
120 totProcFaces += nProcFaces;
121 totProcPatches += nei.size();
122 maxProcPatches =
max(maxProcPatches, nei.size());
123 maxProcFaces =
max(maxProcFaces, nProcFaces);
128 scalar avgProcCells = scalar(globalCells.size())/Pstream::nProcs();
129 scalar avgProcPatches = scalar(totProcPatches)/Pstream::nProcs();
130 scalar avgProcFaces = scalar(totProcFaces)/Pstream::nProcs();
133 if (totProcPatches == 0)
137 if (totProcFaces == 0)
143 <<
"Number of processor faces = " << totProcFaces/2 <<
nl 144 <<
"Max number of cells = " << maxProcCells
145 <<
" (" << 100.0*(maxProcCells-avgProcCells)/avgProcCells
146 <<
"% above average " << avgProcCells <<
")" <<
nl 147 <<
"Max number of processor patches = " << maxProcPatches
148 <<
" (" << 100.0*(maxProcPatches-avgProcPatches)/avgProcPatches
149 <<
"% above average " << avgProcPatches <<
")" <<
nl 150 <<
"Max number of faces between processors = " << maxProcFaces
151 <<
" (" << 100.0*(maxProcFaces-avgProcFaces)/avgProcFaces
152 <<
"% above average " << avgProcFaces <<
")" <<
nl 158 void writeDecomposition
165 Info<<
"Writing wanted cell distribution to volScalarField " << name
166 <<
" for postprocessing purposes." <<
nl <<
endl;
173 mesh.time().timeName(),
176 IOobject::AUTO_WRITE,
181 extrapolatedCalculatedFvPatchScalarField::typeName
186 procCells[cI] = decomp[cI];
188 procCells.correctBoundaryConditions();
194 template<
class GeoField>
198 const typename GeoField::Mesh& mesh,
199 const autoPtr<fvMeshSubset>& subsetterPtr,
200 IOobjectList& allObjects,
201 PtrList<GeoField>& fields
205 IOobjectList
objects(allObjects.lookupClass(GeoField::typeName));
212 Pstream::scatter(masterNames);
214 if (haveMesh[Pstream::myProcNo()] && objectNames != masterNames)
217 <<
"differing fields of type " << GeoField::typeName
218 <<
" on processors." << endl
219 <<
"Master has:" << masterNames << endl
220 << Pstream::myProcNo() <<
" has:" << objectNames
224 fields.setSize(masterNames.size());
227 if (Pstream::master())
231 const word& name = masterNames[i];
233 io.writeOpt() = IOobject::AUTO_WRITE;
236 fields.set(i,
new GeoField(io, mesh));
239 if (subsetterPtr.valid())
241 tmp<GeoField> tsubfld = subsetterPtr().interpolate(fields[i]);
244 for (
label proci = 1; proci < Pstream::nProcs(); proci++)
246 if (!haveMesh[proci])
248 OPstream toProc(Pstream::commsTypes::blocking, proci);
255 else if (!haveMesh[Pstream::myProcNo()])
261 const word& name = masterNames[i];
266 Pstream::commsTypes::blocking,
269 dictionary fieldDict(fromMaster);
279 mesh.thisDb().time().timeName(),
298 const word& name = masterNames[i];
300 io.writeOpt() = IOobject::AUTO_WRITE;
303 fields.set(i,
new GeoField(io, mesh));
309 int main(
int argc,
char *argv[])
315 timeSelector::addOptions();
319 if (
env(
"FOAM_SIGFPE"))
322 <<
"Detected floating point exception trapping (FOAM_SIGFPE)." 323 <<
" This might give" <<
nl 324 <<
" problems when mapping fields. Switch it off in case" 325 <<
" of problems." <<
endl;
338 regIOobject::fileModificationChecking = regIOobject::timeStamp;
344 runTime.functionObjects().off();
346 word regionName = polyMesh::defaultRegion;
351 meshSubDir = regionName/polyMesh::meshSubDir;
355 meshSubDir = polyMesh::meshSubDir;
357 Info<<
"Using mesh subdirectory " << meshSubDir <<
nl <<
endl;
365 fileName masterInstDir;
366 if (Pstream::master())
368 masterInstDir =
runTime.findInstance(meshSubDir,
"points");
370 Pstream::scatter(masterInstDir);
373 const fileName meshPath =
runTime.path()/masterInstDir/meshSubDir;
375 Info<<
"Found points in " << meshPath <<
nl <<
endl;
378 boolList haveMesh(Pstream::nProcs(),
false);
379 haveMesh[Pstream::myProcNo()] =
isDir(meshPath);
380 Pstream::gatherList(haveMesh);
381 Pstream::scatterList(haveMesh);
382 Info<<
"Per processor mesh availability : " << haveMesh <<
endl;
383 const bool allHaveMesh = (
findIndex(haveMesh,
false) == -1);
399 Info<<
"Before distribution:" <<
endl;
404 IOdictionary decompositionDict
411 IOobject::MUST_READ_IF_MODIFIED,
420 autoPtr<decompositionMethod> decomposer
428 if (!decomposer().parallelAware())
431 <<
"You have selected decomposition method " 432 << decomposer().typeName
433 <<
" which does" << endl
434 <<
"not synchronise the decomposition across" 435 <<
" processor patches." << endl
436 <<
" You might want to select a decomposition method which" 437 <<
" is aware of this. Continuing." 441 finalDecomp = decomposer().decompose(mesh, mesh.cellCentres());
447 writeDecomposition(
"decomposition", mesh, finalDecomp);
456 autoPtr<fvMeshSubset> subsetterPtr;
461 const polyBoundaryMesh& patches = mesh.boundaryMesh();
467 if (isA<processorPolyPatch>(patches[
patchi]))
477 <<
"Cannot find non-processor patch on processor " 478 << Pstream::myProcNo() << endl
484 subsetterPtr.reset(
new fvMeshSubset(mesh));
485 subsetterPtr().setLargeCellSubset(
labelHashSet(0), nonProci,
false);
493 IOobjectList::iterator iter =
objects.find(
"decomposition");
502 PtrList<volScalarField> volScalarFields;
512 PtrList<volVectorField> volVectorFields;
522 PtrList<volSphericalTensorField> volSphereTensorFields;
529 volSphereTensorFields
532 PtrList<volSymmTensorField> volSymmTensorFields;
542 PtrList<volTensorField> volTensorFields;
555 PtrList<surfaceScalarField> surfScalarFields;
565 PtrList<surfaceVectorField> surfVectorFields;
575 PtrList<surfaceSphericalTensorField> surfSphereTensorFields;
582 surfSphereTensorFields
585 PtrList<surfaceSymmTensorField> surfSymmTensorFields;
595 PtrList<surfaceTensorField> surfTensorFields;
610 PtrList<pointScalarField> pointScalarFields;
620 PtrList<pointVectorField> pointVectorFields;
630 PtrList<pointSphericalTensorField> pointSphereTensorFields;
637 pointSphereTensorFields
640 PtrList<pointSymmTensorField> pointSymmTensorFields;
647 pointSymmTensorFields
650 PtrList<pointTensorField> pointTensorFields;
665 fvMeshDistribute distributor(mesh);
671 autoPtr<mapDistributePolyMesh> map = distributor.distribute(finalDecomp);
678 Info<<
"After distribution:" <<
endl;
688 mesh.setInstance(masterInstDir);
699 nFaces[Pstream::myProcNo()] = mesh.nFaces();
700 Pstream::gatherList(nFaces);
701 Pstream::scatterList(nFaces);
704 <<
"You can pick up the redecomposed mesh from the polyMesh directory" 705 <<
" in " <<
runTime.timeName() <<
"." <<
nl 706 <<
"If you redecomposed the mesh to less processors you can delete" 708 <<
"the processor directories with 0 sized meshes in them." <<
nl 709 <<
"Below is a sample set of commands to do this." 710 <<
" Take care when issuing these" <<
nl 711 <<
"commands." <<
nl <<
endl;
715 fileName procDir =
"processor" +
name(proci);
717 if (nFaces[proci] == 0)
719 Info<<
" rm -r " << procDir.c_str() <<
nl;
723 fileName timeDir = procDir/
runTime.timeName()/meshSubDir;
724 fileName constDir = procDir/
runTime.constant()/meshSubDir;
726 Info<<
" rm -r " << constDir.c_str() <<
nl 727 <<
" mv " << timeDir.c_str()
728 <<
' ' << constDir.c_str() <<
nl;
List< instant > instantList
List of instants.
List< labelList > labelListList
A List of labelList.
#define forAll(list, i)
Loop across all elements in list.
virtual Ostream & write(const char)=0
Write character.
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Inter-processor communication reduction functions.
void readFields(const typename GeoFieldType::Mesh &mesh, const IOobjectList &objects, const HashSet< word > &selectedFields, LIFOStack< regIOobject *> &storedObjects)
Read the selected GeometricFields of the specified type.
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Ostream & endl(Ostream &os)
Add newline and flush stream.
bool optionFound(const word &opt) const
Return true if the named option is found.
const dimensionSet dimless
bool optionReadIfPresent(const word &opt, T &) const
Read a value from the named option if present.
List< bool > boolList
Bool container classes.
GeometricField< scalar, fvPatchField, volMesh > volScalarField
HashSet< label, Hash< label > > labelHashSet
A HashSet with label keys.
autoPtr< BasicCompressibleMomentumTransportModel > New(const volScalarField &rho, const volVectorField &U, const surfaceScalarField &phi, const typename BasicCompressibleMomentumTransportModel::transportModel &transport)
bool isDir(const fileName &, const bool followLink=true)
Does the name exist as a directory in the file system?
Load or create (0 size) a mesh. Used in distributing meshes to a larger number of processors...
List< label > labelList
A List of labels.
errorManip< error > abort(error &err)
autoPtr< fvMesh > loadOrCreateMesh(const IOobject &io)
Load (if it exists) or create zero cell mesh given an IOobject:
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurrence of given element and return index,.
bool mkDir(const fileName &, mode_t=0777)
Make a directory and return an error if it could not be created.
word name(const complex &)
Return a string representation of a complex.
fileName path() const
Return the path to the caseName.
List< word > wordList
A List of words.
void setSize(const label)
Reset size of List.
#define WarningInFunction
Report a warning using Foam::Warning.
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
prefixOSstream Pout(cout, "Pout")
bool env(const word &)
Return true if environment variable of given name is defined.
Foam::argList args(argc, argv)