mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
Merge branch 'master' of ssh://noisy/home/noisy3/OpenFOAM/OpenFOAM-dev
This commit is contained in:
@ -104,6 +104,8 @@
|
||||
taking film into account
|
||||
+ Parallel aware
|
||||
*** *New* ptscotch decomposition method
|
||||
*** *Updated* decomposePar maps polyPatches instead of recreating them so
|
||||
polyPatches holding data can map the data.
|
||||
*** *Updated* particle tracking algorithm
|
||||
+ uses non-blocking parallel transfers
|
||||
+ does 'minimum-tet' decomposition of face to work with warped faces (snappyHexMesh!)
|
||||
@ -150,7 +152,12 @@
|
||||
OpenFOAM.
|
||||
+ *New* wall functions:
|
||||
+ kappatJayatillekeWallFunction: incompressible RAS thermal wall function
|
||||
|
||||
+ directMappedFixedValue:
|
||||
+ takes interpolationScheme so can interpolate instead of always getting
|
||||
cell value
|
||||
+ takes optional fieldName to sample
|
||||
+ directMapped patch added 'normal' method to calculate sample points
|
||||
to e.g. sample fields just above wall (e.g. for streaklines)
|
||||
* Utilities
|
||||
There have been some utilities added and updated in this release.
|
||||
*** *New* utilities
|
||||
@ -172,8 +179,10 @@
|
||||
*** Updated utilities
|
||||
+ =setFields=: optionally use faceSets to set patch values (see e.g. hotRoom tutorial).
|
||||
+ =blockMesh=: specify patches via dictionary instead of type only. This
|
||||
makes rereading the boundary superfluous. see
|
||||
makes rereading the boundary file superfluous. see
|
||||
e.g. pitzDailyDirectMapped tutorial.
|
||||
+ =setSet=: allows time range (e.g. 0:100) in combination with -batch argument
|
||||
to execute the commands for multiple times.
|
||||
* Post-processing
|
||||
+ =foamToEnsight=: parallel continuous data. new =-nodeValues= option to generate and output nodal
|
||||
field data.
|
||||
@ -190,6 +199,12 @@
|
||||
specified time has been reached, e.g. to automagically change fvSchemes and
|
||||
fvSolution during a calculation
|
||||
+ =streamLine=: generate streamlines; ouputs both trajectory and field data
|
||||
+ =surfaceInterpolateFields=: constructs face interpolate of registered
|
||||
volFields for any future functionObjects that need surfaceFields.
|
||||
+ =readFields=: reads field if not yet registered. Makes functionObjects
|
||||
useable through standalone execFlowFunctionObjects.
|
||||
+ =faceSource=: can now calculate on a sampledSurface (e.g. flow through a
|
||||
triSurfaceMesh)
|
||||
|
||||
* New tutorials
|
||||
There is a large number of new tutorials for existing and new solvers in the
|
||||
|
||||
@ -19,15 +19,17 @@ FoamFile
|
||||
|
||||
numberOfSubdomains 8;
|
||||
|
||||
|
||||
//- Keep owner and neighbour on same processor for faces in zones:
|
||||
// preserveFaceZones (heater solid1 solid3);
|
||||
|
||||
|
||||
//- Keep owner and neighbour on same processor for faces in patches:
|
||||
// (makes sense only for cyclic patches)
|
||||
//preservePatches (cyclic_half0 cyclic_half1);
|
||||
|
||||
//- Use the volScalarField named here as a weight for each cell in the
|
||||
// decomposition. For example, use a particle population field to decompose
|
||||
// for a balanced number of particles in a lagrangian simulation.
|
||||
// weightField dsmcRhoNMean;
|
||||
|
||||
method scotch;
|
||||
// method hierarchical;
|
||||
@ -59,11 +61,8 @@ multiLevelCoeffs
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Desired output
|
||||
|
||||
|
||||
|
||||
simpleCoeffs
|
||||
{
|
||||
n (2 1 1);
|
||||
|
||||
@ -24,7 +24,6 @@ License
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "domainDecomposition.H"
|
||||
#include "Time.H"
|
||||
#include "dictionary.H"
|
||||
#include "labelIOList.H"
|
||||
#include "processorPolyPatch.H"
|
||||
@ -341,10 +340,10 @@ bool Foam::domainDecomposition::writeDecomposition()
|
||||
const labelList& curProcessorPatchStarts =
|
||||
procProcessorPatchStartIndex_[procI];
|
||||
|
||||
const labelListList& curSubPatchIDs =
|
||||
const labelListList& curSubPatchIDs =
|
||||
procProcessorPatchSubPatchIDs_[procI];
|
||||
|
||||
const labelListList& curSubStarts =
|
||||
const labelListList& curSubStarts =
|
||||
procProcessorPatchSubPatchStarts_[procI];
|
||||
|
||||
const polyPatchList& meshPatches = boundaryMesh();
|
||||
|
||||
@ -41,6 +41,9 @@ SourceFiles
|
||||
#include "SLList.H"
|
||||
#include "PtrList.H"
|
||||
#include "point.H"
|
||||
#include "Time.H"
|
||||
#include "volFields.H"
|
||||
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
@ -80,7 +83,7 @@ class domainDecomposition
|
||||
// original face. In order to do this properly, all face
|
||||
// indices will be incremented by 1 and the decremented as
|
||||
// necessary to avoid the problem of face number zero having no
|
||||
// sign.
|
||||
// sign.
|
||||
List<DynamicList<label> > procFaceAddressing_;
|
||||
|
||||
//- Labels of cells for each processor
|
||||
|
||||
@ -114,7 +114,35 @@ void Foam::domainDecomposition::distributeCells()
|
||||
|
||||
if (sameProcFaces.empty())
|
||||
{
|
||||
cellToProc_ = decomposePtr().decompose(*this, cellCentres());
|
||||
if (decompositionDict_.found("weightField"))
|
||||
{
|
||||
word weightName = decompositionDict_.lookup("weightField");
|
||||
|
||||
volScalarField weights
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
weightName,
|
||||
time().timeName(),
|
||||
*this,
|
||||
IOobject::MUST_READ,
|
||||
IOobject::NO_WRITE
|
||||
),
|
||||
*this
|
||||
);
|
||||
|
||||
cellToProc_ = decomposePtr().decompose
|
||||
(
|
||||
*this,
|
||||
cellCentres(),
|
||||
weights.internalField()
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
cellToProc_ = decomposePtr().decompose(*this, cellCentres());
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -173,12 +201,49 @@ void Foam::domainDecomposition::distributeCells()
|
||||
|
||||
// Do decomposition on agglomeration
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
cellToProc_ = decomposePtr().decompose
|
||||
(
|
||||
*this,
|
||||
globalRegion,
|
||||
regionCentres
|
||||
);
|
||||
if (decompositionDict_.found("weightField"))
|
||||
{
|
||||
scalarField regionWeights(globalRegion.nRegions(), 0);
|
||||
|
||||
word weightName = decompositionDict_.lookup("weightField");
|
||||
|
||||
volScalarField weights
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
weightName,
|
||||
time().timeName(),
|
||||
*this,
|
||||
IOobject::MUST_READ,
|
||||
IOobject::NO_WRITE
|
||||
),
|
||||
*this
|
||||
);
|
||||
|
||||
forAll(globalRegion, cellI)
|
||||
{
|
||||
label regionI = globalRegion[cellI];
|
||||
|
||||
regionWeights[regionI] += weights.internalField()[cellI];
|
||||
}
|
||||
|
||||
cellToProc_ = decomposePtr().decompose
|
||||
(
|
||||
*this,
|
||||
globalRegion,
|
||||
regionCentres,
|
||||
regionWeights
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
cellToProc_ = decomposePtr().decompose
|
||||
(
|
||||
*this,
|
||||
globalRegion,
|
||||
regionCentres
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Info<< "\nFinished decomposition in "
|
||||
|
||||
@ -86,9 +86,35 @@ autoPtr<fvMesh> createMesh
|
||||
if (!haveMesh)
|
||||
{
|
||||
// Create dummy mesh. Only used on procs that don't have mesh.
|
||||
// WIP: how to avoid parallel comms when loading IOdictionaries?
|
||||
// For now just give error message.
|
||||
if
|
||||
(
|
||||
regIOobject::fileModificationChecking
|
||||
== regIOobject::timeStampMaster
|
||||
|| regIOobject::fileModificationChecking
|
||||
== regIOobject::inotifyMaster
|
||||
)
|
||||
{
|
||||
FatalErrorIn("createMesh(..)")
|
||||
<< "Cannot use 'fileModificationChecking' mode "
|
||||
<< regIOobject::fileCheckTypesNames
|
||||
[
|
||||
regIOobject::fileModificationChecking
|
||||
]
|
||||
<< " since this uses parallel communication."
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
fvMesh dummyMesh
|
||||
(
|
||||
io,
|
||||
IOobject
|
||||
(
|
||||
regionName,
|
||||
instDir,
|
||||
runTime,
|
||||
IOobject::NO_READ
|
||||
),
|
||||
xferCopy(pointField()),
|
||||
xferCopy(faceList()),
|
||||
xferCopy(labelList()),
|
||||
@ -510,16 +536,14 @@ int main(int argc, char *argv[])
|
||||
"specify the merge distance relative to the bounding box size "
|
||||
"(default 1E-6)"
|
||||
);
|
||||
// Create argList. This will check for non-existing processor dirs.
|
||||
# include "setRootCase.H"
|
||||
|
||||
//- Not useful anymore. See above.
|
||||
//// Create processor directory if non-existing
|
||||
//if (!Pstream::master() && !isDir(args.path()))
|
||||
//{
|
||||
// Pout<< "Creating case directory " << args.path() << endl;
|
||||
// mkDir(args.path());
|
||||
//}
|
||||
// Create processor directory if non-existing
|
||||
if (!Pstream::master() && !isDir(args.path()))
|
||||
{
|
||||
Pout<< "Creating case directory " << args.path() << endl;
|
||||
mkDir(args.path());
|
||||
}
|
||||
|
||||
# include "createTime.H"
|
||||
|
||||
|
||||
@ -319,7 +319,7 @@ void Foam::fileMonitor::checkFiles() const
|
||||
|
||||
if (ready < 0)
|
||||
{
|
||||
FatalErrorIn("fileMonitor::updateStates()")
|
||||
FatalErrorIn("fileMonitor::checkFiles()")
|
||||
<< "Problem in issuing select."
|
||||
<< abort(FatalError);
|
||||
}
|
||||
@ -335,7 +335,7 @@ void Foam::fileMonitor::checkFiles() const
|
||||
|
||||
if (nBytes < 0)
|
||||
{
|
||||
FatalErrorIn("fileMonitor::updateStates(const fileName&)")
|
||||
FatalErrorIn("fileMonitor::checkFiles()")
|
||||
<< "read of " << watcher_->inotifyFd_
|
||||
<< " failed with " << label(nBytes)
|
||||
<< abort(FatalError);
|
||||
@ -374,7 +374,7 @@ void Foam::fileMonitor::checkFiles() const
|
||||
)
|
||||
{
|
||||
// Correct directory and name
|
||||
state_[i] = MODIFIED;
|
||||
localState_[i] = MODIFIED;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -403,18 +403,17 @@ void Foam::fileMonitor::checkFiles() const
|
||||
|
||||
if (newTime == 0)
|
||||
{
|
||||
state_[watchFd] = DELETED;
|
||||
localState_[watchFd] = DELETED;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (newTime > (oldTime + regIOobject::fileModificationSkew))
|
||||
{
|
||||
watcher_->lastMod_[watchFd] = newTime;
|
||||
state_[watchFd] = MODIFIED;
|
||||
localState_[watchFd] = MODIFIED;
|
||||
}
|
||||
else
|
||||
{
|
||||
state_[watchFd] = UNMODIFIED;
|
||||
localState_[watchFd] = UNMODIFIED;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -422,12 +421,14 @@ void Foam::fileMonitor::checkFiles() const
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
Foam::fileMonitor::fileMonitor(const bool useInotify)
|
||||
:
|
||||
useInotify_(useInotify),
|
||||
localState_(20),
|
||||
state_(20),
|
||||
watchFile_(20),
|
||||
freeWatchFds_(2),
|
||||
@ -476,6 +477,7 @@ Foam::label Foam::fileMonitor::addWatch(const fileName& fName)
|
||||
}
|
||||
else
|
||||
{
|
||||
localState_(watchFd) = UNMODIFIED;
|
||||
state_(watchFd) = UNMODIFIED;
|
||||
watchFile_(watchFd) = fName;
|
||||
}
|
||||
@ -517,30 +519,26 @@ void Foam::fileMonitor::updateStates
|
||||
{
|
||||
if (Pstream::master() || !masterOnly)
|
||||
{
|
||||
// Update the localState_
|
||||
checkFiles();
|
||||
}
|
||||
|
||||
if (syncPar)
|
||||
{
|
||||
// Pack current state (might be on master only)
|
||||
// Pack local state (might be on master only)
|
||||
PackedList<2> stats(state_.size(), MODIFIED);
|
||||
if (Pstream::master() || !masterOnly)
|
||||
{
|
||||
forAll(state_, watchFd)
|
||||
{
|
||||
stats[watchFd] = static_cast<unsigned int>(state_[watchFd]);
|
||||
stats[watchFd] = static_cast<unsigned int>
|
||||
(
|
||||
localState_[watchFd]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Save local state for warning message below
|
||||
PackedList<2> thisProcStats;
|
||||
if (!masterOnly)
|
||||
{
|
||||
thisProcStats = stats;
|
||||
}
|
||||
|
||||
|
||||
// Scatter or reduce to synchronise state
|
||||
if (masterOnly)
|
||||
{
|
||||
@ -573,43 +571,49 @@ void Foam::fileMonitor::updateStates
|
||||
}
|
||||
|
||||
|
||||
// Update local state
|
||||
// Update synchronised state
|
||||
forAll(state_, watchFd)
|
||||
{
|
||||
if (masterOnly)
|
||||
// Assign synchronised state
|
||||
unsigned int stat = stats[watchFd];
|
||||
state_[watchFd] = fileState(stat);
|
||||
|
||||
if (!masterOnly)
|
||||
{
|
||||
// No need to check for inconsistent state. Just assign.
|
||||
unsigned int stat = stats[watchFd];
|
||||
state_[watchFd] = fileState(stat);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check for inconsistent state before assigning.
|
||||
if (thisProcStats[watchFd] != UNMODIFIED)
|
||||
// Give warning for inconsistent state
|
||||
if (state_[watchFd] != localState_[watchFd])
|
||||
{
|
||||
if (stats[watchFd] == UNMODIFIED)
|
||||
if (debug)
|
||||
{
|
||||
WarningIn("fileMonitor::updateStates(const bool) const")
|
||||
<< "Delaying reading " << watchFile_[watchFd]
|
||||
Pout<< "fileMonitor : Delaying reading "
|
||||
<< watchFile_[watchFd]
|
||||
<< " due to inconsistent "
|
||||
"file time-stamps between processors"
|
||||
<< endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int stat = stats[watchFd];
|
||||
state_[watchFd] = fileState(stat);
|
||||
}
|
||||
|
||||
WarningIn
|
||||
(
|
||||
"fileMonitor::updateStates"
|
||||
"(const bool, const bool) const"
|
||||
) << "Delaying reading " << watchFile_[watchFd]
|
||||
<< " due to inconsistent "
|
||||
"file time-stamps between processors" << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
state_ = localState_;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::fileMonitor::setUnmodified(const label watchFd)
|
||||
{
|
||||
state_[watchFd] = UNMODIFIED;
|
||||
localState_[watchFd] = UNMODIFIED;
|
||||
|
||||
if (!useInotify_)
|
||||
{
|
||||
|
||||
@ -71,7 +71,7 @@ public:
|
||||
{
|
||||
UNMODIFIED = 0,
|
||||
MODIFIED = 1,
|
||||
DELETED = 2,
|
||||
DELETED = 2
|
||||
};
|
||||
|
||||
static const NamedEnum<fileState, 3> fileStateNames_;
|
||||
@ -82,7 +82,10 @@ private:
|
||||
//- Whether to use inotify (requires -DFOAM_USE_INOTIFY, see above)
|
||||
const bool useInotify_;
|
||||
|
||||
//- State for all watchFds
|
||||
//- State for all watchFds based on local files
|
||||
mutable DynamicList<fileState> localState_;
|
||||
|
||||
//- State for all watchFds - synchronised
|
||||
mutable DynamicList<fileState> state_;
|
||||
|
||||
//- Filename for all watchFds
|
||||
@ -97,7 +100,7 @@ private:
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Update state_ from any events.
|
||||
//- Update localState_ from any events.
|
||||
void checkFiles() const;
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
|
||||
@ -60,7 +60,6 @@ Foam::regIOobject::fileCheckTypes Foam::regIOobject::fileModificationChecking
|
||||
debug::optimisationSwitches().lookup
|
||||
(
|
||||
"fileModificationChecking"
|
||||
//Foam::regIOobject::timeStamp
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
@ -31,6 +31,7 @@ License
|
||||
#include "IOobject.H"
|
||||
#include "JobInfo.H"
|
||||
#include "labelList.H"
|
||||
#include "regIOobject.H"
|
||||
|
||||
#include <cctype>
|
||||
|
||||
@ -767,6 +768,16 @@ Foam::argList::argList
|
||||
sigQuit_.set(bannerEnabled);
|
||||
sigSegv_.set(bannerEnabled);
|
||||
|
||||
if (bannerEnabled)
|
||||
{
|
||||
Info<< "Monitoring run-time modified files using "
|
||||
<< regIOobject::fileCheckTypesNames
|
||||
[
|
||||
regIOobject::fileModificationChecking
|
||||
]
|
||||
<< endl;
|
||||
}
|
||||
|
||||
if (Pstream::master() && bannerEnabled)
|
||||
{
|
||||
Info<< endl;
|
||||
|
||||
@ -58,13 +58,35 @@ void Foam::ptscotchDecomp::check(const int retVal, const char* str)
|
||||
{}
|
||||
|
||||
|
||||
Foam::label Foam::ptscotchDecomp::decomposeZeroDomains
|
||||
(
|
||||
const List<int>& initxadj,
|
||||
const List<int>& initadjncy,
|
||||
const scalarField& initcWeights,
|
||||
|
||||
List<int>& finalDecomp
|
||||
) const
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"label ptscotchDecomp::decompose"
|
||||
"("
|
||||
"const List<int>&, "
|
||||
"const List<int>&, "
|
||||
"const scalarField&, "
|
||||
"List<int>&"
|
||||
")"
|
||||
) << notImplementedMessage << exit(FatalError);
|
||||
|
||||
return -1;
|
||||
}
|
||||
Foam::label Foam::ptscotchDecomp::decompose
|
||||
(
|
||||
List<int>& adjncy,
|
||||
List<int>& xadj,
|
||||
const List<int>& adjncy,
|
||||
const List<int>& xadj,
|
||||
const scalarField& cWeights,
|
||||
List<int>& finalDecomp
|
||||
)
|
||||
) const
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
|
||||
@ -62,37 +62,29 @@ void Foam::Particle<ParticleType>::correctAfterParallelTransfer
|
||||
|
||||
if (!ppp.parallel())
|
||||
{
|
||||
if (ppp.forwardT().size() == 1)
|
||||
{
|
||||
const tensor& T = ppp.forwardT()[0];
|
||||
transformPosition(T);
|
||||
static_cast<ParticleType&>(*this).transformProperties(T);
|
||||
}
|
||||
else
|
||||
{
|
||||
const tensor& T = ppp.forwardT()[faceI_];
|
||||
transformPosition(T);
|
||||
static_cast<ParticleType&>(*this).transformProperties(T);
|
||||
}
|
||||
const tensor& T =
|
||||
(
|
||||
ppp.forwardT().size() == 1
|
||||
? ppp.forwardT()[0]
|
||||
: ppp.forwardT()[faceI_]
|
||||
);
|
||||
|
||||
transformPosition(T);
|
||||
static_cast<ParticleType&>(*this).transformProperties(T);
|
||||
}
|
||||
else if (ppp.separated())
|
||||
{
|
||||
if (ppp.separation().size() == 1)
|
||||
{
|
||||
position_ -= ppp.separation()[0];
|
||||
static_cast<ParticleType&>(*this).transformProperties
|
||||
(
|
||||
-ppp.separation()[0]
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
position_ -= ppp.separation()[faceI_];
|
||||
static_cast<ParticleType&>(*this).transformProperties
|
||||
(
|
||||
-ppp.separation()[faceI_]
|
||||
);
|
||||
}
|
||||
const vector& s =
|
||||
(
|
||||
(ppp.separation().size() == 1)
|
||||
? ppp.separation()[0]
|
||||
: ppp.separation()[faceI_]
|
||||
);
|
||||
position_ -= s;
|
||||
static_cast<ParticleType&>(*this).transformProperties
|
||||
(
|
||||
-s
|
||||
);
|
||||
}
|
||||
|
||||
tetFaceI_ = faceI_ + ppp.start();
|
||||
@ -815,21 +807,34 @@ void Foam::Particle<ParticleType>::hitCyclicPatch
|
||||
// See note in correctAfterParallelTransfer for tetPtI_ addressing.
|
||||
tetPtI_ = cloud_.polyMesh_.faces()[tetFaceI_].size() - 1 - tetPtI_;
|
||||
|
||||
const cyclicPolyPatch& receiveCpp = cpp.neighbPatch();
|
||||
|
||||
// Now the particle is on the receiving side
|
||||
|
||||
if (!cpp.parallel())
|
||||
if (!receiveCpp.parallel())
|
||||
{
|
||||
const tensor& T = cpp.reverseT()[0];
|
||||
const tensor& T =
|
||||
(
|
||||
receiveCpp.forwardT().size() == 1
|
||||
? receiveCpp.forwardT()[0]
|
||||
: receiveCpp.forwardT()[receiveCpp.whichFace(faceI_)]
|
||||
);
|
||||
|
||||
transformPosition(T);
|
||||
static_cast<ParticleType&>(*this).transformProperties(T);
|
||||
}
|
||||
else if (cpp.separated())
|
||||
else if (receiveCpp.separated())
|
||||
{
|
||||
position_ += cpp.separation()[0];
|
||||
const vector& s =
|
||||
(
|
||||
(receiveCpp.separation().size() == 1)
|
||||
? receiveCpp.separation()[0]
|
||||
: receiveCpp.separation()[receiveCpp.whichFace(faceI_)]
|
||||
);
|
||||
position_ -= s;
|
||||
static_cast<ParticleType&>(*this).transformProperties
|
||||
(
|
||||
cpp.separation()[0]
|
||||
-s
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -108,6 +108,7 @@ License
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
#include "Time.H"
|
||||
#include "OFstream.H"
|
||||
#include "globalIndex.H"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
@ -157,16 +158,204 @@ void Foam::ptscotchDecomp::check(const int retVal, const char* str)
|
||||
}
|
||||
|
||||
|
||||
//- Does prevention of 0 cell domains and calls ptscotch.
|
||||
Foam::label Foam::ptscotchDecomp::decomposeZeroDomains
|
||||
(
|
||||
const List<int>& initadjncy,
|
||||
const List<int>& initxadj,
|
||||
const scalarField& initcWeights,
|
||||
|
||||
List<int>& finalDecomp
|
||||
) const
|
||||
{
|
||||
globalIndex globalCells(initxadj.size()-1);
|
||||
|
||||
bool hasZeroDomain = false;
|
||||
for (label procI = 0; procI < Pstream::nProcs(); procI++)
|
||||
{
|
||||
if (globalCells.localSize(procI) == 0)
|
||||
{
|
||||
hasZeroDomain = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasZeroDomain)
|
||||
{
|
||||
return decompose
|
||||
(
|
||||
initadjncy,
|
||||
initxadj,
|
||||
initcWeights,
|
||||
finalDecomp
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Info<< "ptscotchDecomp : have graphs with locally 0 cells."
|
||||
<< " trickling down." << endl;
|
||||
}
|
||||
|
||||
// Make sure every domain has at least one cell
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// (scotch does not like zero sized domains)
|
||||
// Trickle cells from processors that have them up to those that
|
||||
// don't.
|
||||
|
||||
|
||||
// Number of cells to send to the next processor
|
||||
// (is same as number of cells next processor has to receive)
|
||||
List<int> nSendCells(Pstream::nProcs(), 0);
|
||||
|
||||
for (label procI = nSendCells.size()-1; procI >=1; procI--)
|
||||
{
|
||||
label nLocalCells = globalCells.localSize(procI);
|
||||
if (nLocalCells-nSendCells[procI] < 1)
|
||||
{
|
||||
nSendCells[procI-1] = nSendCells[procI]-nLocalCells+1;
|
||||
}
|
||||
}
|
||||
|
||||
// First receive (so increasing the sizes of all arrays)
|
||||
|
||||
Field<int> xadj(initxadj);
|
||||
Field<int> adjncy(initadjncy);
|
||||
scalarField cWeights(initcWeights);
|
||||
|
||||
if (Pstream::myProcNo() >= 1 && nSendCells[Pstream::myProcNo()-1] > 0)
|
||||
{
|
||||
// Receive cells from previous processor
|
||||
IPstream fromPrevProc(Pstream::blocking, Pstream::myProcNo()-1);
|
||||
|
||||
Field<int> prevXadj(fromPrevProc);
|
||||
Field<int> prevAdjncy(fromPrevProc);
|
||||
scalarField prevCellWeights(fromPrevProc);
|
||||
|
||||
if (prevXadj.size() != nSendCells[Pstream::myProcNo()-1])
|
||||
{
|
||||
FatalErrorIn("ptscotchDecomp::decompose(..)")
|
||||
<< "Expected from processor " << Pstream::myProcNo()-1
|
||||
<< " connectivity for " << nSendCells[Pstream::myProcNo()-1]
|
||||
<< " nCells but only received " << prevXadj.size()
|
||||
<< abort(FatalError);
|
||||
}
|
||||
|
||||
// Insert adjncy
|
||||
prepend(prevAdjncy, adjncy);
|
||||
// Adapt offsets and prepend xadj
|
||||
xadj += prevAdjncy.size();
|
||||
prepend(prevXadj, xadj);
|
||||
// Weights
|
||||
prepend(prevCellWeights, cWeights);
|
||||
}
|
||||
|
||||
|
||||
// Send to my next processor
|
||||
|
||||
if (nSendCells[Pstream::myProcNo()] > 0)
|
||||
{
|
||||
// Send cells to next processor
|
||||
OPstream toNextProc(Pstream::blocking, Pstream::myProcNo()+1);
|
||||
|
||||
int nCells = nSendCells[Pstream::myProcNo()];
|
||||
int startCell = xadj.size()-1 - nCells;
|
||||
int startFace = xadj[startCell];
|
||||
int nFaces = adjncy.size()-startFace;
|
||||
|
||||
// Send for all cell data: last nCells elements
|
||||
// Send for all face data: last nFaces elements
|
||||
toNextProc
|
||||
<< Field<int>::subField(xadj, nCells, startCell)-startFace
|
||||
<< Field<int>::subField(adjncy, nFaces, startFace)
|
||||
<<
|
||||
(
|
||||
cWeights.size()
|
||||
? scalarField::subField(cWeights, nCells, startCell)
|
||||
: scalarField(0)
|
||||
);
|
||||
|
||||
// Remove data that has been sent
|
||||
if (cWeights.size())
|
||||
{
|
||||
cWeights.setSize(cWeights.size()-nCells);
|
||||
}
|
||||
adjncy.setSize(adjncy.size()-nFaces);
|
||||
xadj.setSize(xadj.size() - nCells);
|
||||
}
|
||||
|
||||
|
||||
// Do decomposition as normal. Sets finalDecomp.
|
||||
label result = decompose(adjncy, xadj, cWeights, finalDecomp);
|
||||
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Info<< "ptscotchDecomp : have graphs with locally 0 cells."
|
||||
<< " trickling up." << endl;
|
||||
}
|
||||
|
||||
|
||||
// If we sent cells across make sure we undo it
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
// Receive back from next processor if I sent something
|
||||
if (nSendCells[Pstream::myProcNo()] > 0)
|
||||
{
|
||||
IPstream fromNextProc(Pstream::blocking, Pstream::myProcNo()+1);
|
||||
|
||||
List<int> nextFinalDecomp(fromNextProc);
|
||||
|
||||
if (nextFinalDecomp.size() != nSendCells[Pstream::myProcNo()])
|
||||
{
|
||||
FatalErrorIn("parMetisDecomp::decompose(..)")
|
||||
<< "Expected from processor " << Pstream::myProcNo()+1
|
||||
<< " decomposition for " << nSendCells[Pstream::myProcNo()]
|
||||
<< " nCells but only received " << nextFinalDecomp.size()
|
||||
<< abort(FatalError);
|
||||
}
|
||||
|
||||
append(nextFinalDecomp, finalDecomp);
|
||||
}
|
||||
|
||||
// Send back to previous processor.
|
||||
if (Pstream::myProcNo() >= 1 && nSendCells[Pstream::myProcNo()-1] > 0)
|
||||
{
|
||||
OPstream toPrevProc(Pstream::blocking, Pstream::myProcNo()-1);
|
||||
|
||||
int nToPrevious = nSendCells[Pstream::myProcNo()-1];
|
||||
|
||||
toPrevProc <<
|
||||
SubList<int>
|
||||
(
|
||||
finalDecomp,
|
||||
nToPrevious,
|
||||
finalDecomp.size()-nToPrevious
|
||||
);
|
||||
|
||||
// Remove locally what has been sent
|
||||
finalDecomp.setSize(finalDecomp.size()-nToPrevious);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// Call scotch with options from dictionary.
|
||||
Foam::label Foam::ptscotchDecomp::decompose
|
||||
(
|
||||
List<int>& adjncy,
|
||||
List<int>& xadj,
|
||||
const List<int>& adjncy,
|
||||
const List<int>& xadj,
|
||||
const scalarField& cWeights,
|
||||
|
||||
List<int>& finalDecomp
|
||||
)
|
||||
) const
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "ptscotchDecomp : entering with xadj:" << xadj.size() << endl;
|
||||
}
|
||||
|
||||
// // Dump graph
|
||||
// if (decompositionDict_.found("ptscotchCoeffs"))
|
||||
// {
|
||||
@ -262,8 +451,7 @@ Foam::label Foam::ptscotchDecomp::decompose
|
||||
{
|
||||
WarningIn
|
||||
(
|
||||
"ptscotchDecomp::decompose"
|
||||
"(const pointField&, const scalarField&)"
|
||||
"ptscotchDecomp::decompose(..)"
|
||||
) << "Illegal minimum weight " << minWeights
|
||||
<< endl;
|
||||
}
|
||||
@ -272,8 +460,7 @@ Foam::label Foam::ptscotchDecomp::decompose
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"ptscotchDecomp::decompose"
|
||||
"(const pointField&, const scalarField&)"
|
||||
"ptscotchDecomp::decompose(..)"
|
||||
) << "Number of cell weights " << cWeights.size()
|
||||
<< " does not equal number of cells " << xadj.size()-1
|
||||
<< exit(FatalError);
|
||||
@ -289,8 +476,25 @@ Foam::label Foam::ptscotchDecomp::decompose
|
||||
|
||||
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "SCOTCH_dgraphInit" << endl;
|
||||
}
|
||||
SCOTCH_Dgraph grafdat;
|
||||
check(SCOTCH_dgraphInit(&grafdat, MPI_COMM_WORLD), "SCOTCH_dgraphInit");
|
||||
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "SCOTCH_dgraphBuild with:" << nl
|
||||
<< "xadj.size() : " << xadj.size()-1 << nl
|
||||
<< "xadj : " << long(xadj.begin()) << nl
|
||||
<< "velotab : " << long(velotab.begin()) << nl
|
||||
<< "adjncy.size() : " << adjncy.size() << nl
|
||||
<< "adjncy : " << long(adjncy.begin()) << nl
|
||||
<< endl;
|
||||
}
|
||||
|
||||
check
|
||||
(
|
||||
SCOTCH_dgraphBuild
|
||||
@ -302,19 +506,25 @@ Foam::label Foam::ptscotchDecomp::decompose
|
||||
const_cast<SCOTCH_Num*>(xadj.begin()),
|
||||
// vertloctab, start index per cell into
|
||||
// adjncy
|
||||
&xadj[1], // vendloctab, end index ,,
|
||||
const_cast<SCOTCH_Num*>(&xadj[1]),// vendloctab, end index ,,
|
||||
|
||||
velotab.begin(), // veloloctab, vertex weights
|
||||
const_cast<SCOTCH_Num*>(velotab.begin()),// veloloctab, vtx weights
|
||||
NULL, // vlblloctab
|
||||
|
||||
adjncy.size(), // edgelocnbr, number of arcs
|
||||
adjncy.size(), // edgelocsiz
|
||||
adjncy.begin(), // edgeloctab
|
||||
const_cast<SCOTCH_Num*>(adjncy.begin()), // edgeloctab
|
||||
NULL, // edgegsttab
|
||||
NULL // edlotab, edge weights
|
||||
),
|
||||
"SCOTCH_dgraphBuild"
|
||||
);
|
||||
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "SCOTCH_dgraphCheck" << endl;
|
||||
}
|
||||
check(SCOTCH_dgraphCheck(&grafdat), "SCOTCH_dgraphCheck");
|
||||
|
||||
|
||||
@ -322,6 +532,10 @@ Foam::label Foam::ptscotchDecomp::decompose
|
||||
// ~~~~~~~~~~~~
|
||||
// (fully connected network topology since using switch)
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "SCOTCH_archInit" << endl;
|
||||
}
|
||||
SCOTCH_Arch archdat;
|
||||
check(SCOTCH_archInit(&archdat), "SCOTCH_archInit");
|
||||
|
||||
@ -349,6 +563,10 @@ Foam::label Foam::ptscotchDecomp::decompose
|
||||
}
|
||||
else
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "SCOTCH_archCmplt" << endl;
|
||||
}
|
||||
check
|
||||
(
|
||||
SCOTCH_archCmplt(&archdat, nProcessors_),
|
||||
@ -373,6 +591,10 @@ Foam::label Foam::ptscotchDecomp::decompose
|
||||
);
|
||||
# endif
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "SCOTCH_dgraphMap" << endl;
|
||||
}
|
||||
finalDecomp.setSize(xadj.size()-1);
|
||||
finalDecomp = 0;
|
||||
check
|
||||
@ -406,6 +628,10 @@ Foam::label Foam::ptscotchDecomp::decompose
|
||||
// "SCOTCH_graphPart"
|
||||
//);
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "SCOTCH_dgraphExit" << endl;
|
||||
}
|
||||
// Release storage for graph
|
||||
SCOTCH_dgraphExit(&grafdat);
|
||||
// Release storage for strategy
|
||||
@ -465,7 +691,13 @@ Foam::labelList Foam::ptscotchDecomp::decompose
|
||||
|
||||
// Decompose using default weights
|
||||
List<int> finalDecomp;
|
||||
decompose(cellCells.m(), cellCells.offsets(), pointWeights, finalDecomp);
|
||||
decomposeZeroDomains
|
||||
(
|
||||
cellCells.m(),
|
||||
cellCells.offsets(),
|
||||
pointWeights,
|
||||
finalDecomp
|
||||
);
|
||||
|
||||
// Copy back to labelList
|
||||
labelList decomp(finalDecomp.size());
|
||||
@ -510,7 +742,13 @@ Foam::labelList Foam::ptscotchDecomp::decompose
|
||||
|
||||
// Decompose using weights
|
||||
List<int> finalDecomp;
|
||||
decompose(cellCells.m(), cellCells.offsets(), pointWeights, finalDecomp);
|
||||
decomposeZeroDomains
|
||||
(
|
||||
cellCells.m(),
|
||||
cellCells.offsets(),
|
||||
pointWeights,
|
||||
finalDecomp
|
||||
);
|
||||
|
||||
// Rework back into decomposition for original mesh
|
||||
labelList fineDistribution(agglom.size());
|
||||
@ -557,7 +795,13 @@ Foam::labelList Foam::ptscotchDecomp::decompose
|
||||
|
||||
// Decompose using weights
|
||||
List<int> finalDecomp;
|
||||
decompose(cellCells.m(), cellCells.offsets(), cWeights, finalDecomp);
|
||||
decomposeZeroDomains
|
||||
(
|
||||
cellCells.m(),
|
||||
cellCells.offsets(),
|
||||
cWeights,
|
||||
finalDecomp
|
||||
);
|
||||
|
||||
// Copy back to labelList
|
||||
labelList decomp(finalDecomp.size());
|
||||
|
||||
@ -50,16 +50,33 @@ class ptscotchDecomp
|
||||
{
|
||||
// Private Member Functions
|
||||
|
||||
//- Insert list in front of list.
|
||||
template<class Type>
|
||||
static void prepend(const UList<Type>&, List<Type>&);
|
||||
//- Insert list at end of list.
|
||||
template<class Type>
|
||||
static void append(const UList<Type>&, List<Type>&);
|
||||
|
||||
//- Check and print error message
|
||||
static void check(const int, const char*);
|
||||
|
||||
//- Decompose with optionally zero sized domains
|
||||
label decomposeZeroDomains
|
||||
(
|
||||
const List<int>& initadjncy,
|
||||
const List<int>& initxadj,
|
||||
const scalarField& initcWeights,
|
||||
List<int>& finalDecomp
|
||||
) const;
|
||||
|
||||
//- Decompose
|
||||
label decompose
|
||||
(
|
||||
List<int>& adjncy,
|
||||
List<int>& xadj,
|
||||
const List<int>& adjncy,
|
||||
const List<int>& xadj,
|
||||
const scalarField& cWeights,
|
||||
List<int>& finalDecomp
|
||||
);
|
||||
) const;
|
||||
|
||||
//- Disallow default bitwise copy construct and assignment
|
||||
void operator=(const ptscotchDecomp&);
|
||||
@ -135,6 +152,12 @@ public:
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
# include "ptscotchDecompTemplates.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -0,0 +1,76 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2010-2010 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 "ptscotchDecomp.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
// Insert at front of list
|
||||
template<class Type>
|
||||
void Foam::ptscotchDecomp::prepend
|
||||
(
|
||||
const UList<Type>& extraLst,
|
||||
List<Type>& lst
|
||||
)
|
||||
{
|
||||
label nExtra = extraLst.size();
|
||||
|
||||
// Make space for initial elements
|
||||
lst.setSize(lst.size() + nExtra);
|
||||
for (label i = lst.size()-1; i >= nExtra; i--)
|
||||
{
|
||||
lst[i] = lst[i-nExtra];
|
||||
}
|
||||
|
||||
// Insert at front
|
||||
forAll(extraLst, i)
|
||||
{
|
||||
lst[i] = extraLst[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Insert at back of list
|
||||
template<class Type>
|
||||
void Foam::ptscotchDecomp::append
|
||||
(
|
||||
const UList<Type>& extraLst,
|
||||
List<Type>& lst
|
||||
)
|
||||
{
|
||||
label sz = lst.size();
|
||||
|
||||
// Make space for initial elements
|
||||
lst.setSize(sz + extraLst.size());
|
||||
|
||||
// Insert at back
|
||||
forAll(extraLst, i)
|
||||
{
|
||||
lst[sz++] = extraLst[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
Reference in New Issue
Block a user