ENH: add decomposePar -dry-run option

- can be used to test the behaviour of the decomposion and its
  characteristics without writing any decomposition to disk.
  Combine with -cellDist to visualize the expected decomposition
  result.
This commit is contained in:
Mark Olesen
2018-07-19 11:04:38 +02:00
parent 7cb5b638ad
commit ed4ffd8f89
7 changed files with 401 additions and 42 deletions

View File

@ -2,6 +2,7 @@ decomposePar.C
domainDecomposition.C
domainDecompositionMesh.C
domainDecompositionDistribute.C
domainDecompositionDryRun.C
dimFieldDecomposer.C
pointFieldDecomposer.C
faMeshDecomposition.C

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2016-2017 OpenCFD Ltd.
\\/ M anipulation | Copyright (C) 2016-2018 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -35,9 +35,12 @@ Usage
\b decomposePar [OPTION]
Options:
- \par -dry-run
Test without actually decomposing
- \par -cellDist
Write the cell distribution as a labelList, for use with 'manual'
decomposition method or as a volScalarField for post-processing.
decomposition method and as a volScalarField for visualization.
- \par -region \<regionName\>
Decompose named region. Does not check for existence of processor*.
@ -83,6 +86,7 @@ Usage
#include "fvCFD.H"
#include "IOobjectList.H"
#include "domainDecomposition.H"
#include "domainDecompositionDryRun.H"
#include "labelIOField.H"
#include "labelFieldIOField.H"
#include "scalarIOField.H"
@ -239,10 +243,21 @@ int main(int argc, char *argv[])
"operate on all regions in regionProperties"
);
argList::addBoolOption
(
"dry-run",
"Test without writing the decomposition. "
"Changes -cellDist to only write volScalarField."
);
argList::addBoolOption
(
"verbose",
"Additional verbosity"
);
argList::addBoolOption
(
"cellDist",
"write cell distribution as a labelList - for use with 'manual' "
"decomposition method or as a volScalarField for post-processing."
"Write cell distribution as a labelList - for use with 'manual' "
"decomposition method and as a volScalarField for visualization."
);
argList::addBoolOption
(
@ -280,13 +295,17 @@ int main(int argc, char *argv[])
#include "setRootCase.H"
const bool dryrun = args.found("dry-run");
const bool optRegion = args.found("region");
const bool allRegions = args.found("allRegions");
const bool writeCellDist = args.found("cellDist");
const bool verbose = args.found("verbose");
// Most of these are ignored for dry-run (not triggered anywhere)
const bool copyZero = args.found("copyZero");
const bool copyUniform = args.found("copyUniform");
const bool decomposeSets = !args.found("noSets");
const bool ifRequiredDecomposition = args.found("ifRequired");
const bool decomposeIfRequired = args.found("ifRequired");
bool decomposeFieldsOnly = args.found("fields");
bool forceOverwrite = args.found("force");
@ -294,8 +313,18 @@ int main(int argc, char *argv[])
// Set time from database
#include "createTime.H"
// Allow override of time
instantList times = timeSelector::selectIfPresent(runTime, args);
// Allow override of time (unless dry-run)
instantList times;
if (dryrun)
{
Info<< "\ndry-run: ignoring -copy*, -fields, -force, time selection"
<< nl;
}
else
{
times = timeSelector::selectIfPresent(runTime, args);
}
// Allow override of decomposeParDict location
@ -305,7 +334,7 @@ int main(int argc, char *argv[])
wordList regionNames;
if (allRegions)
{
Info<< "Decomposing all regions in regionProperties" << nl << endl;
Info<< "Decomposing all regions in regionProperties" << nl << nl;
regionProperties rp(runTime);
wordHashSet names;
@ -329,6 +358,29 @@ int main(int argc, char *argv[])
const word& regionDir =
(regionName == fvMesh::defaultRegion ? word::null : regionName);
if (dryrun)
{
Info<< "dry-run: decomposing mesh " << regionName << nl << nl
<< "Create mesh..." << flush;
domainDecompositionDryRun decompTest
(
IOobject
(
regionName,
runTime.timeName(),
runTime,
IOobject::MUST_READ,
IOobject::NO_WRITE,
false
),
decompDictFile
);
decompTest.execute(writeCellDist, verbose);
continue;
}
Info<< "\n\nDecomposing mesh " << regionName << nl << endl;
// Determine the existing processor count directly
@ -346,7 +398,7 @@ int main(int argc, char *argv[])
(
"decomposeParDict",
runTime.time().system(),
regionDir, // use region if non-standard
regionDir, // region (if non-default)
runTime,
IOobject::MUST_READ,
IOobject::NO_WRITE,
@ -378,9 +430,9 @@ int main(int argc, char *argv[])
{
bool procDirsProblem = true;
if (ifRequiredDecomposition && nProcs == nDomains)
if (decomposeIfRequired && nProcs == nDomains)
{
// we can reuse the decomposition
// We can reuse the decomposition
decomposeFieldsOnly = true;
procDirsProblem = false;
forceOverwrite = false;
@ -485,28 +537,7 @@ int main(int argc, char *argv[])
{
const labelList& procIds = mesh.cellToProc();
// Write the decomposition as labelList for use with 'manual'
// decomposition method.
labelIOList cellDecomposition
(
IOobject
(
"cellDecomposition",
mesh.facesInstance(),
mesh,
IOobject::NO_READ,
IOobject::NO_WRITE,
false
),
procIds
);
cellDecomposition.write();
Info<< nl << "Wrote decomposition to "
<< cellDecomposition.objectPath()
<< " for use in manual decomposition." << endl;
// Write as volScalarField for postprocessing.
// Write decomposition as volScalarField for visualization
volScalarField cellDist
(
IOobject
@ -531,8 +562,29 @@ int main(int argc, char *argv[])
cellDist.write();
Info<< nl << "Wrote decomposition as volScalarField to "
<< cellDist.name() << " for use in postprocessing."
<< cellDist.name() << " for visualization."
<< endl;
// Write decomposition as labelList for use with 'manual'
// decomposition method.
labelIOList cellDecomposition
(
IOobject
(
"cellDecomposition",
mesh.facesInstance(),
mesh,
IOobject::NO_READ,
IOobject::NO_WRITE,
false
),
procIds
);
cellDecomposition.write();
Info<< nl << "Wrote decomposition to "
<< cellDecomposition.objectPath()
<< " for use in manual decomposition." << endl;
}
fileOperations::collatedFileOperation::maxThreadFileBufferSize =

View File

@ -159,8 +159,10 @@ public:
// Constructors
//- Construct from IOobjects (for mesh and optional non-standard
//- decomposeParDict location)
//- Construct from components.
// \param io the IOobject for mesh
// \param decompDictFile optional non-standard location for the
// decomposeParDict file
domainDecomposition
(
const IOobject& io,
@ -186,7 +188,7 @@ public:
return distributed_;
}
//- Decompose mesh.
//- Decompose mesh
void decomposeMesh();
//- Write decomposition

View File

@ -0,0 +1,200 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 OpenCFD Ltd.
\\/ 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/>.
\*---------------------------------------------------------------------------*/
#include "domainDecompositionDryRun.H"
#include "volFields.H"
#include "decompositionModel.H"
#include "decompositionInformation.H"
#include "zeroGradientFvPatchFields.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::domainDecompositionDryRun::domainDecompositionDryRun
(
const IOobject& io,
const fileName& decompDictFile,
const label nDomains,
const word& methodName
)
:
mesh_(io),
decompDictFile_(decompDictFile),
nDomainsOverride_(nDomains),
methodNameOverride_(methodName)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::domainDecompositionDryRun::execute
(
const bool writeCellDist,
const bool verbose
)
{
cpuTime decompositionTime;
Info<< "\nCalculating distribution of cells. nCells = "
<< mesh_.nCells() << endl;
const decompositionModel& model = decompositionModel::New
(
mesh_,
decompDictFile_
);
// Allow overrides for testing
dictionary& modelDict = const_cast<decompositionModel&>(model);
if (nDomainsOverride_ > 0)
{
modelDict.add
(
word("numberOfSubdomains"),
nDomainsOverride_,
true
);
}
if (!methodNameOverride_.empty())
{
modelDict.add
(
word("method"),
methodNameOverride_,
true
);
}
scalarField cellWeights;
word weightName;
if (model.readIfPresent("weightField", weightName))
{
volScalarField weights
(
IOobject
(
weightName,
mesh_.time().timeName(),
mesh_,
IOobject::MUST_READ,
IOobject::NO_WRITE
),
mesh_
);
cellWeights = weights.primitiveField();
}
decompositionMethod& method = model.decomposer();
CompactListList<label> cellCells;
decompositionMethod::calcCellCells
(
mesh_,
identity(mesh_.nCells()),
mesh_.nCells(),
false,
cellCells
);
labelList cellToProc = method.decompose(mesh_, cellWeights);
Info<< "\nFinished decomposition into "
<< method.nDomains() << " domains in "
<< decompositionTime.elapsedCpuTime() << " s" << nl << nl;
decompositionInformation info
(
cellCells,
cellToProc,
method.nDomains()
);
if (writeCellDist)
{
// Write decomposition as volScalarField for visualization
volScalarField cellDist
(
IOobject
(
"cellDist",
mesh_.time().timeName(),
mesh_,
IOobject::NO_READ,
IOobject::AUTO_WRITE
),
mesh_,
dimensionedScalar("cellDist", dimless, -1),
zeroGradientFvPatchScalarField::typeName
);
forAll(cellToProc, celli)
{
cellDist[celli] = cellToProc[celli];
}
cellDist.correctBoundaryConditions();
cellDist.write();
Info<< "Wrote decomposition as volScalarField for visualization:"
<< nl << cellDist.objectPath() << nl;
// Less likely that this is actually required, but may be useful...
//
// // Write decomposition as labelList for use with 'manual'
// // decomposition method.
// labelIOList cellDecomposition
// (
// IOobject
// (
// "cellDecomposition",
// mesh_.facesInstance(),
// mesh_,
// IOobject::NO_READ,
// IOobject::NO_WRITE,
// false
// ),
// std::move(cellToProc)
// );
// cellDecomposition.write();
//
// Info<< "Wrote decomposition for use in manual decomposition:"
// << nl << cellDecomposition.objectPath() << nl;
// #endif
Info<< nl;
}
if (verbose)
{
info.printDetails(Info);
Info<< nl;
}
info.printSummary(Info);
}
// ************************************************************************* //

View File

@ -0,0 +1,102 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 OpenCFD Ltd.
\\/ 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/>.
Class
Foam::domainDecompositionDryRun
Description
Testing of domain decomposition for finite-volume meshes
SourceFiles
domainDecompositionDryRun.C
\*---------------------------------------------------------------------------*/
#ifndef domainDecompositionDryRun_H
#define domainDecompositionDryRun_H
#include "fvMesh.H"
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class domainDecompositionDryRun Declaration
\*---------------------------------------------------------------------------*/
class domainDecompositionDryRun
{
// Private Data
//- The mesh
fvMesh mesh_;
//- Optional non-standard file for decomposeParDict
const fileName decompDictFile_;
//- Optional override for numberOfSubdomains in decomposeParDict
const label nDomainsOverride_;
//- Optional override for method in decomposeParDict
const word methodNameOverride_;
public:
// Constructors
//- Construct from components.
// \param io the IOobject for mesh
// \param decompDictFile optional non-standard location for the
// decomposeParDict file
// \param nDomains optional override value for numberOfSubdomains
// \param methodName optional override value for decomposition method
domainDecompositionDryRun
(
const IOobject& io,
const fileName& decompDictFile = "",
const label nDomains = 0,
const word& methodName = ""
);
//- Destructor
~domainDecompositionDryRun() = default;
// Member Functions
//- Perform dry-run
void execute(const bool writeCellDist, const bool verbose = false);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -135,8 +135,10 @@ public:
// Constructors
//- Construct from fvMesh (for mesh and optional non-standard
//- decomposeParDict location)
//- Construct from components.
// \param mesh the fvMesh
// \param decompDictFile optional non-standard location for the
// decomposeParDict file
faMeshDecomposition
(
const fvMesh& mesh,