From 7fa1e73a35cda24f0526edb7d67934a4355b92ff Mon Sep 17 00:00:00 2001 From: mattijs <mattijs> Date: Thu, 30 Dec 2010 08:39:40 +0000 Subject: [PATCH] ENH: scotchDecomp : allow decomposition in parallel All of graph gets sent to master which does the decomposition --- .../decompose/scotchDecomp/scotchDecomp.C | 140 +++++++++++++++++- .../decompose/scotchDecomp/scotchDecomp.H | 19 ++- 2 files changed, 151 insertions(+), 8 deletions(-) diff --git a/src/parallel/decompose/scotchDecomp/scotchDecomp.C b/src/parallel/decompose/scotchDecomp/scotchDecomp.C index 1d3f91906d5..e22300e057d 100644 --- a/src/parallel/decompose/scotchDecomp/scotchDecomp.C +++ b/src/parallel/decompose/scotchDecomp/scotchDecomp.C @@ -108,8 +108,8 @@ License #include "addToRunTimeSelectionTable.H" #include "floatScalar.H" #include "Time.H" -#include "cyclicPolyPatch.H" #include "OFstream.H" +#include "globalIndex.H" extern "C" { @@ -162,7 +162,6 @@ void Foam::scotchDecomp::check(const int retVal, const char* str) } -// Call scotch with options from dictionary. Foam::label Foam::scotchDecomp::decompose ( const fileName& meshPath, @@ -172,6 +171,128 @@ Foam::label Foam::scotchDecomp::decompose List<int>& finalDecomp ) +{ + if (!Pstream::parRun()) + { + decomposeOneProc + ( + meshPath, + adjncy, + xadj, + cWeights, + finalDecomp + ); + } + else + { + if (debug) + { + Info<< "scotchDecomp : running in parallel." + << " Decomposing all of graph on master processor." << endl; + } + globalIndex globalCells(xadj.size()-1); + label nTotalConnections = returnReduce(adjncy.size(), sumOp<label>()); + + // Send all to master. Use scheduled to save some storage. + if (Pstream::master()) + { + Field<int> allAdjncy(nTotalConnections); + Field<int> allXadj(globalCells.size()+1); + scalarField allWeights(globalCells.size()); + + // Insert my own + label nTotalCells = 0; + forAll(cWeights, cellI) + { + allXadj[nTotalCells] = xadj[cellI]; + allWeights[nTotalCells++] = cWeights[cellI]; + } + nTotalConnections = 0; + forAll(adjncy, i) + { + allAdjncy[nTotalConnections++] = adjncy[i]; + } + + for (int slave=1; slave<Pstream::nProcs(); slave++) + { + IPstream fromSlave(Pstream::scheduled, slave); + Field<int> nbrAdjncy(fromSlave); + Field<int> nbrXadj(fromSlave); + scalarField nbrWeights(fromSlave); + + // Append. + //label procStart = nTotalCells; + forAll(nbrXadj, cellI) + { + allXadj[nTotalCells] = nTotalConnections+nbrXadj[cellI]; + allWeights[nTotalCells++] = nbrWeights[cellI]; + } + // No need to renumber xadj since already global. + forAll(nbrAdjncy, i) + { + allAdjncy[nTotalConnections++] = nbrAdjncy[i]; + } + } + allXadj[nTotalCells] = nTotalConnections; + + + Field<int> allFinalDecomp; + decomposeOneProc + ( + meshPath, + allAdjncy, + allXadj, + allWeights, + allFinalDecomp + ); + + + // Send allFinalDecomp back + for (int slave=1; slave<Pstream::nProcs(); slave++) + { + OPstream toSlave(Pstream::scheduled, slave); + toSlave << SubField<int> + ( + allFinalDecomp, + globalCells.localSize(slave), + globalCells.offset(slave) + ); + } + // Get my own part (always first) + finalDecomp = SubField<int> + ( + allFinalDecomp, + globalCells.localSize() + ); + } + else + { + // Send my part of the graph (already in global numbering) + { + OPstream toMaster(Pstream::scheduled, Pstream::masterNo()); + toMaster<< adjncy << SubField<int>(xadj, xadj.size()-1) + << cWeights; + } + + // Receive back decomposition + IPstream fromMaster(Pstream::scheduled, Pstream::masterNo()); + fromMaster >> finalDecomp; + } + } + return 0; +} + + +// Call scotch with options from dictionary. +Foam::label Foam::scotchDecomp::decomposeOneProc +( + const fileName& meshPath, + const List<int>& adjncy, + const List<int>& xadj, + const scalarField& cWeights, + + List<int>& finalDecomp +) { // Dump graph if (decompositionDict_.found("scotchCoeffs")) @@ -247,7 +368,8 @@ Foam::label Foam::scotchDecomp::decompose // Check for externally provided cellweights and if so initialise weights - scalar minWeights = gMin(cWeights); + // Note: min, not gMin since routine runs on master only. + scalar minWeights = min(cWeights); if (cWeights.size() > 0) { if (minWeights <= 0) @@ -432,7 +554,7 @@ Foam::labelList Foam::scotchDecomp::decompose << exit(FatalError); } - + // Calculate local or global (if Pstream::parRun()) connectivity CompactListList<label> cellCells; calcCellCells(mesh, identity(mesh.nCells()), mesh.nCells(), cellCells); @@ -475,6 +597,7 @@ Foam::labelList Foam::scotchDecomp::decompose << exit(FatalError); } + // Calculate local or global (if Pstream::parRun()) connectivity CompactListList<label> cellCells; calcCellCells(mesh, agglom, agglomPoints.size(), cellCells); @@ -528,7 +651,14 @@ Foam::labelList Foam::scotchDecomp::decompose // Decompose using weights List<int> finalDecomp; - decompose(".", cellCells.m(), cellCells.offsets(), cWeights, finalDecomp); + decompose + ( + "scotch", + cellCells.m(), + cellCells.offsets(), + cWeights, + finalDecomp + ); // Copy back to labelList labelList decomp(finalDecomp.size()); diff --git a/src/parallel/decompose/scotchDecomp/scotchDecomp.H b/src/parallel/decompose/scotchDecomp/scotchDecomp.H index 27601b19202..6ec5c474c24 100644 --- a/src/parallel/decompose/scotchDecomp/scotchDecomp.H +++ b/src/parallel/decompose/scotchDecomp/scotchDecomp.H @@ -25,7 +25,10 @@ Class Foam::scotchDecomp Description - Scotch domain decomposition + Scotch domain decomposition. + When run in parallel will collect the whole graph on to the master, + decompose and send back. Run ptscotchDecomp for proper distributed + decomposition. SourceFiles scotchDecomp.C @@ -62,6 +65,16 @@ class scotchDecomp List<int>& finalDecomp ); + //- Decompose non-parallel + label decomposeOneProc + ( + const fileName& meshPath, + const List<int>& adjncy, + const List<int>& xadj, + const scalarField& cWeights, + List<int>& finalDecomp + ); + //- Disallow default bitwise copy construct and assignment void operator=(const scotchDecomp&); scotchDecomp(const scotchDecomp&); @@ -88,8 +101,8 @@ public: virtual bool parallelAware() const { - // Metis does not know about proc boundaries - return false; + // Knows about coupled boundaries + return true; } //- Return for every coordinate the wanted processor number. Use the -- GitLab