mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: Removed parmetis. Use ptscotch instead.
This commit is contained in:
@ -11,7 +11,7 @@ EXE_INC = \
|
|||||||
EXE_LIBS = \
|
EXE_LIBS = \
|
||||||
-lfiniteVolume \
|
-lfiniteVolume \
|
||||||
-ldecompositionMethods \
|
-ldecompositionMethods \
|
||||||
-L$(FOAM_MPI_LIBBIN) -lptscotchDecomp -lparMetisDecomp -lmetisDecomp \
|
-L$(FOAM_MPI_LIBBIN) -lptscotchDecomp \
|
||||||
-lmeshTools \
|
-lmeshTools \
|
||||||
-ldynamicMesh \
|
-ldynamicMesh \
|
||||||
-lautoMesh
|
-lautoMesh
|
||||||
|
|||||||
@ -347,7 +347,7 @@ int main(int argc, char *argv[])
|
|||||||
<< "You have selected decomposition method "
|
<< "You have selected decomposition method "
|
||||||
<< decomposer.typeName
|
<< decomposer.typeName
|
||||||
<< " which is not parallel aware." << endl
|
<< " which is not parallel aware." << endl
|
||||||
<< "Please select one that is (hierarchical, ptscotch, parMetis)"
|
<< "Please select one that is (hierarchical, ptscotch)"
|
||||||
<< exit(FatalError);
|
<< exit(FatalError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -7,6 +7,6 @@ EXE_INC = \
|
|||||||
EXE_LIBS = \
|
EXE_LIBS = \
|
||||||
-lfiniteVolume \
|
-lfiniteVolume \
|
||||||
-ldecompositionMethods \
|
-ldecompositionMethods \
|
||||||
-L$(FOAM_MPI_LIBBIN) -lptscotchDecomp -lparMetisDecomp -lmetisDecomp \
|
-L$(FOAM_MPI_LIBBIN) -lptscotchDecomp \
|
||||||
-lmeshTools \
|
-lmeshTools \
|
||||||
-ldynamicMesh
|
-ldynamicMesh
|
||||||
|
|||||||
1
src/dummyThirdParty/Allwmake
vendored
1
src/dummyThirdParty/Allwmake
vendored
@ -5,7 +5,6 @@ set -x
|
|||||||
wmake libso scotchDecomp
|
wmake libso scotchDecomp
|
||||||
wmake libso ptscotchDecomp
|
wmake libso ptscotchDecomp
|
||||||
wmake libso metisDecomp
|
wmake libso metisDecomp
|
||||||
wmake libso parMetisDecomp
|
|
||||||
wmake libso MGridGen
|
wmake libso MGridGen
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +0,0 @@
|
|||||||
dummyParMetisDecomp.C
|
|
||||||
|
|
||||||
LIB = $(FOAM_LIBBIN)/dummy/libparMetisDecomp
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
EXE_INC = \
|
|
||||||
-I$(FOAM_SRC)/parallel/decompose/decompositionMethods/lnInclude \
|
|
||||||
-I$(FOAM_SRC)/parallel/decompose/parMetisDecomp/lnInclude
|
|
||||||
|
|
||||||
LIB_LIBS =
|
|
||||||
@ -1,166 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
========= |
|
|
||||||
\\ / 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 2 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, write to the Free Software Foundation,
|
|
||||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#include "parMetisDecomp.H"
|
|
||||||
#include "addToRunTimeSelectionTable.H"
|
|
||||||
#include "polyMesh.H"
|
|
||||||
#include "Time.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
namespace Foam
|
|
||||||
{
|
|
||||||
defineTypeNameAndDebug(parMetisDecomp, 0);
|
|
||||||
|
|
||||||
addToRunTimeSelectionTable
|
|
||||||
(
|
|
||||||
decompositionMethod,
|
|
||||||
parMetisDecomp,
|
|
||||||
dictionaryMesh
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char* notImplementedMessage =
|
|
||||||
"You are trying to use parMetis but do not have the parMetisDecomp library "
|
|
||||||
"loaded.\n"
|
|
||||||
"This message is from the dummy parMetisDecomp stub library instead.\n"
|
|
||||||
"\n"
|
|
||||||
"Please install parMetis and make sure that libparMetis.so is in your "
|
|
||||||
"LD_LIBRARY_PATH.\n"
|
|
||||||
"The parMetisDecomp library can then be built in "
|
|
||||||
"$FOAM_SRC/parallel/decompose/decompositionMethods/parMetisDecomp\n";
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
|
||||||
|
|
||||||
//- Does prevention of 0 cell domains and calls parmetis.
|
|
||||||
Foam::label Foam::parMetisDecomp::decompose
|
|
||||||
(
|
|
||||||
Field<int>& xadj,
|
|
||||||
Field<int>& adjncy,
|
|
||||||
const pointField& cellCentres,
|
|
||||||
Field<int>& cellWeights,
|
|
||||||
Field<int>& faceWeights,
|
|
||||||
const List<int>& options,
|
|
||||||
|
|
||||||
List<int>& finalDecomp
|
|
||||||
)
|
|
||||||
{
|
|
||||||
FatalErrorIn
|
|
||||||
(
|
|
||||||
"label parMetisDecomp::decompose"
|
|
||||||
"("
|
|
||||||
"Field<int>&, "
|
|
||||||
"Field<int>&, "
|
|
||||||
"const pointField&, "
|
|
||||||
"Field<int>&, "
|
|
||||||
"Field<int>&, "
|
|
||||||
"const List<int>&, "
|
|
||||||
"List<int>&"
|
|
||||||
")"
|
|
||||||
)<< notImplementedMessage << exit(FatalError);
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
Foam::parMetisDecomp::parMetisDecomp
|
|
||||||
(
|
|
||||||
const dictionary& decompositionDict,
|
|
||||||
const polyMesh& mesh
|
|
||||||
)
|
|
||||||
:
|
|
||||||
decompositionMethod(decompositionDict),
|
|
||||||
mesh_(mesh)
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
Foam::labelList Foam::parMetisDecomp::decompose
|
|
||||||
(
|
|
||||||
const pointField& cc,
|
|
||||||
const scalarField& cWeights
|
|
||||||
)
|
|
||||||
{
|
|
||||||
FatalErrorIn
|
|
||||||
(
|
|
||||||
"labelList parMetisDecomp::decompose"
|
|
||||||
"("
|
|
||||||
"const pointField&, "
|
|
||||||
"const scalarField&"
|
|
||||||
")"
|
|
||||||
) << notImplementedMessage << exit(FatalError);
|
|
||||||
|
|
||||||
return labelList();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Foam::labelList Foam::parMetisDecomp::decompose
|
|
||||||
(
|
|
||||||
const labelList& cellToRegion,
|
|
||||||
const pointField& regionPoints,
|
|
||||||
const scalarField& regionWeights
|
|
||||||
)
|
|
||||||
{
|
|
||||||
FatalErrorIn
|
|
||||||
(
|
|
||||||
"labelList parMetisDecomp::decompose"
|
|
||||||
"("
|
|
||||||
"const labelList&, "
|
|
||||||
"const pointField&, "
|
|
||||||
"const scalarField&"
|
|
||||||
")"
|
|
||||||
) << notImplementedMessage << exit(FatalError);
|
|
||||||
|
|
||||||
return labelList();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Foam::labelList Foam::parMetisDecomp::decompose
|
|
||||||
(
|
|
||||||
const labelListList& globalCellCells,
|
|
||||||
const pointField& cellCentres,
|
|
||||||
const scalarField& cWeights
|
|
||||||
)
|
|
||||||
{
|
|
||||||
FatalErrorIn
|
|
||||||
(
|
|
||||||
"labelList parMetisDecomp::decompose"
|
|
||||||
"("
|
|
||||||
"const labelListList&, "
|
|
||||||
"const pointField&, "
|
|
||||||
"const scalarField&"
|
|
||||||
")"
|
|
||||||
) << notImplementedMessage << exit(FatalError);
|
|
||||||
|
|
||||||
return labelList();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
||||||
@ -431,7 +431,7 @@ Foam::autoHexMeshDriver::autoHexMeshDriver
|
|||||||
<< "You have selected decomposition method "
|
<< "You have selected decomposition method "
|
||||||
<< decomposer.typeName
|
<< decomposer.typeName
|
||||||
<< " which is not parallel aware." << endl
|
<< " which is not parallel aware." << endl
|
||||||
<< "Please select one that is (parMetis, hierarchical)"
|
<< "Please select one that is (hierarchical, ptscotch)"
|
||||||
<< exit(FatalError);
|
<< exit(FatalError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,7 +9,7 @@ wmake libso metisDecomp
|
|||||||
|
|
||||||
if [ -d "$FOAM_MPI_LIBBIN" ]
|
if [ -d "$FOAM_MPI_LIBBIN" ]
|
||||||
then
|
then
|
||||||
( WM_OPTIONS=${WM_OPTIONS}$WM_MPLIB; wmake libso ptscotchDecomp && wmake libso parMetisDecomp )
|
( WM_OPTIONS=${WM_OPTIONS}$WM_MPLIB; wmake libso ptscotchDecomp )
|
||||||
fi
|
fi
|
||||||
|
|
||||||
wmake libso decompositionMethods
|
wmake libso decompositionMethods
|
||||||
|
|||||||
@ -4,7 +4,6 @@ set -x
|
|||||||
|
|
||||||
wmakeLnInclude decompositionMethods
|
wmakeLnInclude decompositionMethods
|
||||||
wmakeLnInclude metisDecomp
|
wmakeLnInclude metisDecomp
|
||||||
wmakeLnInclude parMetisDecomp
|
|
||||||
wmakeLnInclude scotchDecomp
|
wmakeLnInclude scotchDecomp
|
||||||
wmakeLnInclude ptscotchDecomp
|
wmakeLnInclude ptscotchDecomp
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,3 @@
|
|||||||
EXE_INC =
|
EXE_INC =
|
||||||
|
|
||||||
LIB_LIBS = \
|
LIB_LIBS =
|
||||||
/* -L$(FOAM_LIBBIN)/dummy */ \
|
|
||||||
/* -L$(FOAM_MPI_LIBBIN) */ \
|
|
||||||
/* -lscotchDecomp */ \
|
|
||||||
/* -lmetisDecomp */ \
|
|
||||||
/* -lparMetisDecomp */
|
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +0,0 @@
|
|||||||
parMetisDecomp.C
|
|
||||||
|
|
||||||
LIB = $(FOAM_MPI_LIBBIN)/libparMetisDecomp
|
|
||||||
@ -1,14 +0,0 @@
|
|||||||
include $(RULES)/mplib$(WM_MPLIB)
|
|
||||||
|
|
||||||
EXE_INC = \
|
|
||||||
$(PFLAGS) $(PINC) \
|
|
||||||
-I$(WM_THIRD_PARTY_DIR)/ParMetis-3.1/ParMETISLib \
|
|
||||||
-I$(WM_THIRD_PARTY_DIR)/ParMetis-3.1 \
|
|
||||||
-I../decompositionMethods/lnInclude \
|
|
||||||
-I../metisDecomp/lnInclude \
|
|
||||||
-I../scotchDecomp/lnInclude
|
|
||||||
|
|
||||||
LIB_LIBS = \
|
|
||||||
-L$(FOAM_MPI_LIBBIN) \
|
|
||||||
-lmetis-parmetis \
|
|
||||||
-lparmetis
|
|
||||||
@ -1,873 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
========= |
|
|
||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
||||||
\\ / O peration |
|
|
||||||
\\ / A nd | Copyright (C) 1991-2009 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 2 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, write to the Free Software Foundation,
|
|
||||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#include "parMetisDecomp.H"
|
|
||||||
#include "metisDecomp.H"
|
|
||||||
#include "syncTools.H"
|
|
||||||
#include "addToRunTimeSelectionTable.H"
|
|
||||||
#include "floatScalar.H"
|
|
||||||
#include "polyMesh.H"
|
|
||||||
#include "Time.H"
|
|
||||||
#include "labelIOField.H"
|
|
||||||
#include "globalIndex.H"
|
|
||||||
|
|
||||||
#include <mpi.h>
|
|
||||||
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
# include "parmetis.h"
|
|
||||||
}
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
namespace Foam
|
|
||||||
{
|
|
||||||
defineTypeNameAndDebug(parMetisDecomp, 0);
|
|
||||||
|
|
||||||
addToRunTimeSelectionTable
|
|
||||||
(
|
|
||||||
decompositionMethod,
|
|
||||||
parMetisDecomp,
|
|
||||||
dictionaryMesh
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
|
||||||
|
|
||||||
//- Does prevention of 0 cell domains and calls parmetis.
|
|
||||||
Foam::label Foam::parMetisDecomp::decompose
|
|
||||||
(
|
|
||||||
Field<int>& xadj,
|
|
||||||
Field<int>& adjncy,
|
|
||||||
const pointField& cellCentres,
|
|
||||||
Field<int>& cellWeights,
|
|
||||||
Field<int>& faceWeights,
|
|
||||||
const List<int>& options,
|
|
||||||
|
|
||||||
List<int>& finalDecomp
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// C style numbering
|
|
||||||
int numFlag = 0;
|
|
||||||
|
|
||||||
// Number of dimensions
|
|
||||||
int nDims = 3;
|
|
||||||
|
|
||||||
|
|
||||||
if (cellCentres.size() != xadj.size()-1)
|
|
||||||
{
|
|
||||||
FatalErrorIn("parMetisDecomp::decompose(..)")
|
|
||||||
<< "cellCentres:" << cellCentres.size()
|
|
||||||
<< " xadj:" << xadj.size()
|
|
||||||
<< abort(FatalError);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Get number of cells on all processors
|
|
||||||
List<int> nLocalCells(Pstream::nProcs());
|
|
||||||
nLocalCells[Pstream::myProcNo()] = xadj.size()-1;
|
|
||||||
Pstream::gatherList(nLocalCells);
|
|
||||||
Pstream::scatterList(nLocalCells);
|
|
||||||
|
|
||||||
// Get cell offsets.
|
|
||||||
List<int> cellOffsets(Pstream::nProcs()+1);
|
|
||||||
int nGlobalCells = 0;
|
|
||||||
forAll(nLocalCells, procI)
|
|
||||||
{
|
|
||||||
cellOffsets[procI] = nGlobalCells;
|
|
||||||
nGlobalCells += nLocalCells[procI];
|
|
||||||
}
|
|
||||||
cellOffsets[Pstream::nProcs()] = nGlobalCells;
|
|
||||||
|
|
||||||
// Convert pointField into float
|
|
||||||
Field<floatScalar> xyz(3*cellCentres.size());
|
|
||||||
int compI = 0;
|
|
||||||
forAll(cellCentres, cellI)
|
|
||||||
{
|
|
||||||
const point& cc = cellCentres[cellI];
|
|
||||||
xyz[compI++] = float(cc.x());
|
|
||||||
xyz[compI++] = float(cc.y());
|
|
||||||
xyz[compI++] = float(cc.z());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure every domain has at least one cell
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
// (Metis falls over with 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 = nLocalCells.size()-1; procI >=1; procI--)
|
|
||||||
{
|
|
||||||
if (nLocalCells[procI]-nSendCells[procI] < 1)
|
|
||||||
{
|
|
||||||
nSendCells[procI-1] = nSendCells[procI]-nLocalCells[procI]+1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// First receive (so increasing the sizes of all arrays)
|
|
||||||
|
|
||||||
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);
|
|
||||||
Field<floatScalar> prevXyz(fromPrevProc);
|
|
||||||
Field<int> prevCellWeights(fromPrevProc);
|
|
||||||
Field<int> prevFaceWeights(fromPrevProc);
|
|
||||||
|
|
||||||
if (prevXadj.size() != nSendCells[Pstream::myProcNo()-1])
|
|
||||||
{
|
|
||||||
FatalErrorIn("parMetisDecomp::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);
|
|
||||||
// Coords
|
|
||||||
prepend(prevXyz, xyz);
|
|
||||||
// Weights
|
|
||||||
prepend(prevCellWeights, cellWeights);
|
|
||||||
prepend(prevFaceWeights, faceWeights);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// 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)
|
|
||||||
<< SubField<floatScalar>(xyz, nDims*nCells, nDims*startCell)
|
|
||||||
<<
|
|
||||||
(
|
|
||||||
cellWeights.size()
|
|
||||||
? static_cast<const Field<int>&>
|
|
||||||
(
|
|
||||||
Field<int>::subField(cellWeights, nCells, startCell)
|
|
||||||
)
|
|
||||||
: Field<int>(0)
|
|
||||||
)
|
|
||||||
<<
|
|
||||||
(
|
|
||||||
faceWeights.size()
|
|
||||||
? static_cast<const Field<int>&>
|
|
||||||
(
|
|
||||||
Field<int>::subField(faceWeights, nFaces, startFace)
|
|
||||||
)
|
|
||||||
: Field<int>(0)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Remove data that has been sent
|
|
||||||
if (faceWeights.size())
|
|
||||||
{
|
|
||||||
faceWeights.setSize(faceWeights.size()-nFaces);
|
|
||||||
}
|
|
||||||
if (cellWeights.size())
|
|
||||||
{
|
|
||||||
cellWeights.setSize(cellWeights.size()-nCells);
|
|
||||||
}
|
|
||||||
xyz.setSize(xyz.size()-nDims*nCells);
|
|
||||||
adjncy.setSize(adjncy.size()-nFaces);
|
|
||||||
xadj.setSize(xadj.size() - nCells);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Adapt number of cells
|
|
||||||
forAll(nSendCells, procI)
|
|
||||||
{
|
|
||||||
// Sent cells
|
|
||||||
nLocalCells[procI] -= nSendCells[procI];
|
|
||||||
|
|
||||||
if (procI >= 1)
|
|
||||||
{
|
|
||||||
// Received cells
|
|
||||||
nLocalCells[procI] += nSendCells[procI-1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Adapt cellOffsets
|
|
||||||
nGlobalCells = 0;
|
|
||||||
forAll(nLocalCells, procI)
|
|
||||||
{
|
|
||||||
cellOffsets[procI] = nGlobalCells;
|
|
||||||
nGlobalCells += nLocalCells[procI];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (nLocalCells[Pstream::myProcNo()] != (xadj.size()-1))
|
|
||||||
{
|
|
||||||
FatalErrorIn("parMetisDecomp::decompose(..)")
|
|
||||||
<< "Have connectivity for " << xadj.size()-1
|
|
||||||
<< " cells but nLocalCells:" << nLocalCells[Pstream::myProcNo()]
|
|
||||||
<< abort(FatalError);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Weight info
|
|
||||||
int wgtFlag = 0;
|
|
||||||
int* vwgtPtr = NULL;
|
|
||||||
int* adjwgtPtr = NULL;
|
|
||||||
|
|
||||||
if (cellWeights.size())
|
|
||||||
{
|
|
||||||
vwgtPtr = cellWeights.begin();
|
|
||||||
wgtFlag += 2; // Weights on vertices
|
|
||||||
}
|
|
||||||
if (faceWeights.size())
|
|
||||||
{
|
|
||||||
adjwgtPtr = faceWeights.begin();
|
|
||||||
wgtFlag += 1; // Weights on edges
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Number of weights or balance constraints
|
|
||||||
int nCon = 1;
|
|
||||||
// Per processor, per constraint the weight
|
|
||||||
Field<floatScalar> tpwgts(nCon*nProcessors_, 1./nProcessors_);
|
|
||||||
// Imbalance tolerance
|
|
||||||
Field<floatScalar> ubvec(nCon, 1.02);
|
|
||||||
if (nProcessors_ == 1)
|
|
||||||
{
|
|
||||||
// If only one processor there is no imbalance.
|
|
||||||
ubvec[0] = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
MPI_Comm comm = MPI_COMM_WORLD;
|
|
||||||
|
|
||||||
// output: cell -> processor addressing
|
|
||||||
finalDecomp.setSize(nLocalCells[Pstream::myProcNo()]);
|
|
||||||
|
|
||||||
// output: number of cut edges
|
|
||||||
int edgeCut = 0;
|
|
||||||
|
|
||||||
|
|
||||||
ParMETIS_V3_PartGeomKway
|
|
||||||
(
|
|
||||||
cellOffsets.begin(), // vtxDist
|
|
||||||
xadj.begin(),
|
|
||||||
adjncy.begin(),
|
|
||||||
vwgtPtr, // vertexweights
|
|
||||||
adjwgtPtr, // edgeweights
|
|
||||||
&wgtFlag,
|
|
||||||
&numFlag,
|
|
||||||
&nDims,
|
|
||||||
xyz.begin(),
|
|
||||||
&nCon,
|
|
||||||
&nProcessors_, // nParts
|
|
||||||
tpwgts.begin(),
|
|
||||||
ubvec.begin(),
|
|
||||||
const_cast<List<int>&>(options).begin(),
|
|
||||||
&edgeCut,
|
|
||||||
finalDecomp.begin(),
|
|
||||||
&comm
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
// 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 edgeCut;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
Foam::parMetisDecomp::parMetisDecomp
|
|
||||||
(
|
|
||||||
const dictionary& decompositionDict,
|
|
||||||
const polyMesh& mesh
|
|
||||||
)
|
|
||||||
:
|
|
||||||
decompositionMethod(decompositionDict),
|
|
||||||
mesh_(mesh)
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
Foam::labelList Foam::parMetisDecomp::decompose
|
|
||||||
(
|
|
||||||
const pointField& cc,
|
|
||||||
const scalarField& cWeights
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (cc.size() != mesh_.nCells())
|
|
||||||
{
|
|
||||||
FatalErrorIn
|
|
||||||
(
|
|
||||||
"parMetisDecomp::decompose"
|
|
||||||
"(const pointField&, const scalarField&)"
|
|
||||||
) << "Can use this decomposition method only for the whole mesh"
|
|
||||||
<< endl
|
|
||||||
<< "and supply one coordinate (cellCentre) for every cell." << endl
|
|
||||||
<< "The number of coordinates " << cc.size() << endl
|
|
||||||
<< "The number of cells in the mesh " << mesh_.nCells()
|
|
||||||
<< exit(FatalError);
|
|
||||||
}
|
|
||||||
|
|
||||||
// For running sequential ...
|
|
||||||
if (Pstream::nProcs() <= 1)
|
|
||||||
{
|
|
||||||
return metisDecomp(decompositionDict_, mesh_).decompose
|
|
||||||
(
|
|
||||||
cc,
|
|
||||||
cWeights
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Connections
|
|
||||||
Field<int> adjncy;
|
|
||||||
// Offsets into adjncy
|
|
||||||
Field<int> xadj;
|
|
||||||
calcDistributedCSR
|
|
||||||
(
|
|
||||||
mesh_,
|
|
||||||
adjncy,
|
|
||||||
xadj
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
// decomposition options. 0 = use defaults
|
|
||||||
List<int> options(3, 0);
|
|
||||||
//options[0] = 1; // don't use defaults but use values below
|
|
||||||
//options[1] = -1; // full debug info
|
|
||||||
//options[2] = 15; // random number seed
|
|
||||||
|
|
||||||
// cell weights (so on the vertices of the dual)
|
|
||||||
Field<int> cellWeights;
|
|
||||||
|
|
||||||
// face weights (so on the edges of the dual)
|
|
||||||
Field<int> faceWeights;
|
|
||||||
|
|
||||||
|
|
||||||
// Check for externally provided cellweights and if so initialise weights
|
|
||||||
scalar minWeights = gMin(cWeights);
|
|
||||||
if (cWeights.size() > 0)
|
|
||||||
{
|
|
||||||
if (minWeights <= 0)
|
|
||||||
{
|
|
||||||
WarningIn
|
|
||||||
(
|
|
||||||
"metisDecomp::decompose"
|
|
||||||
"(const pointField&, const scalarField&)"
|
|
||||||
) << "Illegal minimum weight " << minWeights
|
|
||||||
<< endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cWeights.size() != mesh_.nCells())
|
|
||||||
{
|
|
||||||
FatalErrorIn
|
|
||||||
(
|
|
||||||
"parMetisDecomp::decompose"
|
|
||||||
"(const pointField&, const scalarField&)"
|
|
||||||
) << "Number of cell weights " << cWeights.size()
|
|
||||||
<< " does not equal number of cells " << mesh_.nCells()
|
|
||||||
<< exit(FatalError);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert to integers.
|
|
||||||
cellWeights.setSize(cWeights.size());
|
|
||||||
forAll(cellWeights, i)
|
|
||||||
{
|
|
||||||
cellWeights[i] = int(cWeights[i]/minWeights);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Check for user supplied weights and decomp options
|
|
||||||
if (decompositionDict_.found("metisCoeffs"))
|
|
||||||
{
|
|
||||||
const dictionary& metisCoeffs =
|
|
||||||
decompositionDict_.subDict("metisCoeffs");
|
|
||||||
word weightsFile;
|
|
||||||
|
|
||||||
if (metisCoeffs.readIfPresent("cellWeightsFile", weightsFile))
|
|
||||||
{
|
|
||||||
Info<< "parMetisDecomp : Using cell-based weights read from "
|
|
||||||
<< weightsFile << endl;
|
|
||||||
|
|
||||||
labelIOField cellIOWeights
|
|
||||||
(
|
|
||||||
IOobject
|
|
||||||
(
|
|
||||||
weightsFile,
|
|
||||||
mesh_.time().timeName(),
|
|
||||||
mesh_,
|
|
||||||
IOobject::MUST_READ,
|
|
||||||
IOobject::AUTO_WRITE
|
|
||||||
)
|
|
||||||
);
|
|
||||||
cellWeights.transfer(cellIOWeights);
|
|
||||||
|
|
||||||
if (cellWeights.size() != mesh_.nCells())
|
|
||||||
{
|
|
||||||
FatalErrorIn
|
|
||||||
(
|
|
||||||
"parMetisDecomp::decompose"
|
|
||||||
"(const pointField&, const scalarField&)"
|
|
||||||
) << "Number of cell weights " << cellWeights.size()
|
|
||||||
<< " read from " << cellIOWeights.objectPath()
|
|
||||||
<< " does not equal number of cells " << mesh_.nCells()
|
|
||||||
<< exit(FatalError);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (metisCoeffs.readIfPresent("faceWeightsFile", weightsFile))
|
|
||||||
{
|
|
||||||
Info<< "parMetisDecomp : Using face-based weights read from "
|
|
||||||
<< weightsFile << endl;
|
|
||||||
|
|
||||||
labelIOField weights
|
|
||||||
(
|
|
||||||
IOobject
|
|
||||||
(
|
|
||||||
weightsFile,
|
|
||||||
mesh_.time().timeName(),
|
|
||||||
mesh_,
|
|
||||||
IOobject::MUST_READ,
|
|
||||||
IOobject::AUTO_WRITE
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (weights.size() != mesh_.nFaces())
|
|
||||||
{
|
|
||||||
FatalErrorIn
|
|
||||||
(
|
|
||||||
"parMetisDecomp::decompose"
|
|
||||||
"(const pointField&, const scalarField&)"
|
|
||||||
) << "Number of face weights " << weights.size()
|
|
||||||
<< " does not equal number of internal and boundary faces "
|
|
||||||
<< mesh_.nFaces()
|
|
||||||
<< exit(FatalError);
|
|
||||||
}
|
|
||||||
|
|
||||||
faceWeights.setSize(adjncy.size());
|
|
||||||
|
|
||||||
// Assume symmetric weights. Keep same ordering as adjncy.
|
|
||||||
List<int> nFacesPerCell(mesh_.nCells(), 0);
|
|
||||||
|
|
||||||
// Handle internal faces
|
|
||||||
for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
|
|
||||||
{
|
|
||||||
label w = weights[faceI];
|
|
||||||
|
|
||||||
label own = mesh_.faceOwner()[faceI];
|
|
||||||
label nei = mesh_.faceNeighbour()[faceI];
|
|
||||||
|
|
||||||
faceWeights[xadj[own] + nFacesPerCell[own]++] = w;
|
|
||||||
faceWeights[xadj[nei] + nFacesPerCell[nei]++] = w;
|
|
||||||
}
|
|
||||||
// Coupled boundary faces
|
|
||||||
const polyBoundaryMesh& patches = mesh_.boundaryMesh();
|
|
||||||
|
|
||||||
forAll(patches, patchI)
|
|
||||||
{
|
|
||||||
const polyPatch& pp = patches[patchI];
|
|
||||||
|
|
||||||
if (pp.coupled())
|
|
||||||
{
|
|
||||||
label faceI = pp.start();
|
|
||||||
|
|
||||||
forAll(pp, i)
|
|
||||||
{
|
|
||||||
label w = weights[faceI];
|
|
||||||
label own = mesh_.faceOwner()[faceI];
|
|
||||||
faceWeights[xadj[own] + nFacesPerCell[own]++] = w;
|
|
||||||
faceI++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (metisCoeffs.readIfPresent("options", options))
|
|
||||||
{
|
|
||||||
Info<< "Using Metis options " << options
|
|
||||||
<< nl << endl;
|
|
||||||
|
|
||||||
if (options.size() != 3)
|
|
||||||
{
|
|
||||||
FatalErrorIn
|
|
||||||
(
|
|
||||||
"parMetisDecomp::decompose"
|
|
||||||
"(const pointField&, const scalarField&)"
|
|
||||||
) << "Number of options " << options.size()
|
|
||||||
<< " should be three." << exit(FatalError);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Do actual decomposition
|
|
||||||
List<int> finalDecomp;
|
|
||||||
decompose
|
|
||||||
(
|
|
||||||
xadj,
|
|
||||||
adjncy,
|
|
||||||
cc,
|
|
||||||
cellWeights,
|
|
||||||
faceWeights,
|
|
||||||
options,
|
|
||||||
|
|
||||||
finalDecomp
|
|
||||||
);
|
|
||||||
|
|
||||||
// Copy back to labelList
|
|
||||||
labelList decomp(finalDecomp.size());
|
|
||||||
forAll(decomp, i)
|
|
||||||
{
|
|
||||||
decomp[i] = finalDecomp[i];
|
|
||||||
}
|
|
||||||
return decomp;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Foam::labelList Foam::parMetisDecomp::decompose
|
|
||||||
(
|
|
||||||
const labelList& cellToRegion,
|
|
||||||
const pointField& regionPoints,
|
|
||||||
const scalarField& regionWeights
|
|
||||||
)
|
|
||||||
{
|
|
||||||
const labelList& faceOwner = mesh_.faceOwner();
|
|
||||||
const labelList& faceNeighbour = mesh_.faceNeighbour();
|
|
||||||
const polyBoundaryMesh& patches = mesh_.boundaryMesh();
|
|
||||||
|
|
||||||
if (cellToRegion.size() != mesh_.nCells())
|
|
||||||
{
|
|
||||||
FatalErrorIn
|
|
||||||
(
|
|
||||||
"parMetisDecomp::decompose(const labelList&, const pointField&)"
|
|
||||||
) << "Size of cell-to-coarse map " << cellToRegion.size()
|
|
||||||
<< " differs from number of cells in mesh " << mesh_.nCells()
|
|
||||||
<< exit(FatalError);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Global region numbering engine
|
|
||||||
globalIndex globalRegions(regionPoints.size());
|
|
||||||
|
|
||||||
|
|
||||||
// Get renumbered owner region on other side of coupled faces
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
List<int> globalNeighbour(mesh_.nFaces()-mesh_.nInternalFaces());
|
|
||||||
|
|
||||||
forAll(patches, patchI)
|
|
||||||
{
|
|
||||||
const polyPatch& pp = patches[patchI];
|
|
||||||
|
|
||||||
if (pp.coupled())
|
|
||||||
{
|
|
||||||
label faceI = pp.start();
|
|
||||||
label bFaceI = pp.start() - mesh_.nInternalFaces();
|
|
||||||
|
|
||||||
forAll(pp, i)
|
|
||||||
{
|
|
||||||
label ownRegion = cellToRegion[faceOwner[faceI]];
|
|
||||||
globalNeighbour[bFaceI++] = globalRegions.toGlobal(ownRegion);
|
|
||||||
faceI++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the cell on the other side of coupled patches
|
|
||||||
syncTools::swapBoundaryFaceList(mesh_, globalNeighbour, false);
|
|
||||||
|
|
||||||
|
|
||||||
// Get globalCellCells on coarse mesh
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
labelListList globalRegionRegions;
|
|
||||||
{
|
|
||||||
List<DynamicList<label> > dynRegionRegions(regionPoints.size());
|
|
||||||
|
|
||||||
// Internal faces first
|
|
||||||
forAll(faceNeighbour, faceI)
|
|
||||||
{
|
|
||||||
label ownRegion = cellToRegion[faceOwner[faceI]];
|
|
||||||
label neiRegion = cellToRegion[faceNeighbour[faceI]];
|
|
||||||
|
|
||||||
if (ownRegion != neiRegion)
|
|
||||||
{
|
|
||||||
label globalOwn = globalRegions.toGlobal(ownRegion);
|
|
||||||
label globalNei = globalRegions.toGlobal(neiRegion);
|
|
||||||
|
|
||||||
if (findIndex(dynRegionRegions[ownRegion], globalNei) == -1)
|
|
||||||
{
|
|
||||||
dynRegionRegions[ownRegion].append(globalNei);
|
|
||||||
}
|
|
||||||
if (findIndex(dynRegionRegions[neiRegion], globalOwn) == -1)
|
|
||||||
{
|
|
||||||
dynRegionRegions[neiRegion].append(globalOwn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Coupled boundary faces
|
|
||||||
forAll(patches, patchI)
|
|
||||||
{
|
|
||||||
const polyPatch& pp = patches[patchI];
|
|
||||||
|
|
||||||
if (pp.coupled())
|
|
||||||
{
|
|
||||||
label faceI = pp.start();
|
|
||||||
label bFaceI = pp.start() - mesh_.nInternalFaces();
|
|
||||||
|
|
||||||
forAll(pp, i)
|
|
||||||
{
|
|
||||||
label ownRegion = cellToRegion[faceOwner[faceI]];
|
|
||||||
label globalNei = globalNeighbour[bFaceI++];
|
|
||||||
faceI++;
|
|
||||||
|
|
||||||
if (findIndex(dynRegionRegions[ownRegion], globalNei) == -1)
|
|
||||||
{
|
|
||||||
dynRegionRegions[ownRegion].append(globalNei);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
globalRegionRegions.setSize(dynRegionRegions.size());
|
|
||||||
forAll(dynRegionRegions, i)
|
|
||||||
{
|
|
||||||
globalRegionRegions[i].transfer(dynRegionRegions[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
labelList regionDecomp
|
|
||||||
(
|
|
||||||
decompose
|
|
||||||
(
|
|
||||||
globalRegionRegions,
|
|
||||||
regionPoints,
|
|
||||||
regionWeights
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Rework back into decomposition for original mesh_
|
|
||||||
labelList cellDistribution(cellToRegion.size());
|
|
||||||
|
|
||||||
forAll(cellDistribution, cellI)
|
|
||||||
{
|
|
||||||
cellDistribution[cellI] = regionDecomp[cellToRegion[cellI]];
|
|
||||||
}
|
|
||||||
return cellDistribution;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Foam::labelList Foam::parMetisDecomp::decompose
|
|
||||||
(
|
|
||||||
const labelListList& globalCellCells,
|
|
||||||
const pointField& cellCentres,
|
|
||||||
const scalarField& cWeights
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (cellCentres.size() != globalCellCells.size())
|
|
||||||
{
|
|
||||||
FatalErrorIn
|
|
||||||
(
|
|
||||||
"parMetisDecomp::decompose(const labelListList&"
|
|
||||||
", const pointField&, const scalarField&)"
|
|
||||||
) << "Inconsistent number of cells (" << globalCellCells.size()
|
|
||||||
<< ") and number of cell centres (" << cellCentres.size()
|
|
||||||
<< ") or weights (" << cWeights.size() << ")." << exit(FatalError);
|
|
||||||
}
|
|
||||||
|
|
||||||
// For running sequential ...
|
|
||||||
if (Pstream::nProcs() <= 1)
|
|
||||||
{
|
|
||||||
return metisDecomp(decompositionDict_, mesh_)
|
|
||||||
.decompose(globalCellCells, cellCentres, cWeights);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Make Metis Distributed CSR (Compressed Storage Format) storage
|
|
||||||
|
|
||||||
// Connections
|
|
||||||
Field<int> adjncy;
|
|
||||||
// Offsets into adjncy
|
|
||||||
Field<int> xadj;
|
|
||||||
calcCSR(globalCellCells, adjncy, xadj);
|
|
||||||
|
|
||||||
// decomposition options. 0 = use defaults
|
|
||||||
List<int> options(3, 0);
|
|
||||||
//options[0] = 1; // don't use defaults but use values below
|
|
||||||
//options[1] = -1; // full debug info
|
|
||||||
//options[2] = 15; // random number seed
|
|
||||||
|
|
||||||
// cell weights (so on the vertices of the dual)
|
|
||||||
Field<int> cellWeights;
|
|
||||||
|
|
||||||
// face weights (so on the edges of the dual)
|
|
||||||
Field<int> faceWeights;
|
|
||||||
|
|
||||||
|
|
||||||
// Check for externally provided cellweights and if so initialise weights
|
|
||||||
scalar minWeights = gMin(cWeights);
|
|
||||||
if (cWeights.size() > 0)
|
|
||||||
{
|
|
||||||
if (minWeights <= 0)
|
|
||||||
{
|
|
||||||
WarningIn
|
|
||||||
(
|
|
||||||
"parMetisDecomp::decompose(const labelListList&"
|
|
||||||
", const pointField&, const scalarField&)"
|
|
||||||
) << "Illegal minimum weight " << minWeights
|
|
||||||
<< endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cWeights.size() != globalCellCells.size())
|
|
||||||
{
|
|
||||||
FatalErrorIn
|
|
||||||
(
|
|
||||||
"parMetisDecomp::decompose(const labelListList&"
|
|
||||||
", const pointField&, const scalarField&)"
|
|
||||||
) << "Number of cell weights " << cWeights.size()
|
|
||||||
<< " does not equal number of cells " << globalCellCells.size()
|
|
||||||
<< exit(FatalError);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert to integers.
|
|
||||||
cellWeights.setSize(cWeights.size());
|
|
||||||
forAll(cellWeights, i)
|
|
||||||
{
|
|
||||||
cellWeights[i] = int(cWeights[i]/minWeights);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Check for user supplied weights and decomp options
|
|
||||||
if (decompositionDict_.found("metisCoeffs"))
|
|
||||||
{
|
|
||||||
const dictionary& metisCoeffs =
|
|
||||||
decompositionDict_.subDict("metisCoeffs");
|
|
||||||
|
|
||||||
if (metisCoeffs.readIfPresent("options", options))
|
|
||||||
{
|
|
||||||
Info<< "Using Metis options " << options
|
|
||||||
<< nl << endl;
|
|
||||||
|
|
||||||
if (options.size() != 3)
|
|
||||||
{
|
|
||||||
FatalErrorIn
|
|
||||||
(
|
|
||||||
"parMetisDecomp::decompose(const labelListList&"
|
|
||||||
", const pointField&, const scalarField&)"
|
|
||||||
) << "Number of options " << options.size()
|
|
||||||
<< " should be three." << exit(FatalError);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Do actual decomposition
|
|
||||||
List<int> finalDecomp;
|
|
||||||
decompose
|
|
||||||
(
|
|
||||||
xadj,
|
|
||||||
adjncy,
|
|
||||||
cellCentres,
|
|
||||||
cellWeights,
|
|
||||||
faceWeights,
|
|
||||||
options,
|
|
||||||
|
|
||||||
finalDecomp
|
|
||||||
);
|
|
||||||
|
|
||||||
// Copy back to labelList
|
|
||||||
labelList decomp(finalDecomp.size());
|
|
||||||
forAll(decomp, i)
|
|
||||||
{
|
|
||||||
decomp[i] = finalDecomp[i];
|
|
||||||
}
|
|
||||||
return decomp;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
||||||
@ -1,175 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
========= |
|
|
||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
||||||
\\ / O peration |
|
|
||||||
\\ / A nd | Copyright (C) 1991-2009 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 2 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, write to the Free Software Foundation,
|
|
||||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
Class
|
|
||||||
Foam::parMetisDecomp
|
|
||||||
|
|
||||||
Description
|
|
||||||
|
|
||||||
SourceFiles
|
|
||||||
parMetisDecomp.C
|
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#ifndef parMetisDecomp_H
|
|
||||||
#define parMetisDecomp_H
|
|
||||||
|
|
||||||
#include "decompositionMethod.H"
|
|
||||||
|
|
||||||
namespace Foam
|
|
||||||
{
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
Class parMetisDecomp Declaration
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
class parMetisDecomp
|
|
||||||
:
|
|
||||||
public decompositionMethod
|
|
||||||
{
|
|
||||||
// Private data
|
|
||||||
|
|
||||||
const polyMesh& mesh_;
|
|
||||||
|
|
||||||
|
|
||||||
// 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>&);
|
|
||||||
|
|
||||||
label decompose
|
|
||||||
(
|
|
||||||
Field<int>& xadj,
|
|
||||||
Field<int>& adjncy,
|
|
||||||
const pointField& cellCentres,
|
|
||||||
Field<int>& cellWeights,
|
|
||||||
Field<int>& faceWeights,
|
|
||||||
const List<int>& options,
|
|
||||||
|
|
||||||
List<int>& finalDecomp
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
//- Disallow default bitwise copy construct and assignment
|
|
||||||
void operator=(const parMetisDecomp&);
|
|
||||||
parMetisDecomp(const parMetisDecomp&);
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
//- Runtime type information
|
|
||||||
TypeName("parMetis");
|
|
||||||
|
|
||||||
|
|
||||||
// Constructors
|
|
||||||
|
|
||||||
//- Construct given the decomposition dictionary and mesh
|
|
||||||
parMetisDecomp
|
|
||||||
(
|
|
||||||
const dictionary& decompositionDict,
|
|
||||||
const polyMesh& mesh
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
// Destructor
|
|
||||||
|
|
||||||
~parMetisDecomp()
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
// Member Functions
|
|
||||||
|
|
||||||
//- parMetis handles Foam processor boundaries
|
|
||||||
virtual bool parallelAware() const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//- Return for every coordinate the wanted processor number. Use the
|
|
||||||
// mesh connectivity (if needed)
|
|
||||||
// Weights get normalised so the minimum value is 1 before truncation
|
|
||||||
// to an integer so the weights should be multiples of the minimum
|
|
||||||
// value. The overall sum of weights might otherwise overflow.
|
|
||||||
virtual labelList decompose
|
|
||||||
(
|
|
||||||
const pointField& points,
|
|
||||||
const scalarField& pointWeights
|
|
||||||
);
|
|
||||||
|
|
||||||
//- Return for every coordinate the wanted processor number. Gets
|
|
||||||
// passed agglomeration map (from fine to coarse cells) and coarse cell
|
|
||||||
// location. Can be overridden by decomposers that provide this
|
|
||||||
// functionality natively.
|
|
||||||
// See note on weights above.
|
|
||||||
virtual labelList decompose
|
|
||||||
(
|
|
||||||
const labelList& cellToRegion,
|
|
||||||
const pointField& regionPoints,
|
|
||||||
const scalarField& regionWeights
|
|
||||||
);
|
|
||||||
|
|
||||||
//- Return for every coordinate the wanted processor number. Explicitly
|
|
||||||
// provided mesh connectivity.
|
|
||||||
// The connectivity is equal to mesh.cellCells() except for
|
|
||||||
// - in parallel the cell numbers are global cell numbers (starting
|
|
||||||
// from 0 at processor0 and then incrementing all through the
|
|
||||||
// processors)
|
|
||||||
// - the connections are across coupled patches
|
|
||||||
// See note on weights above.
|
|
||||||
virtual labelList decompose
|
|
||||||
(
|
|
||||||
const labelListList& globalCellCells,
|
|
||||||
const pointField& cc,
|
|
||||||
const scalarField& cWeights
|
|
||||||
);
|
|
||||||
|
|
||||||
//- Helper to convert mesh connectivity into distributed CSR
|
|
||||||
static void calcMetisDistributedCSR
|
|
||||||
(
|
|
||||||
const polyMesh&,
|
|
||||||
List<int>& adjncy,
|
|
||||||
List<int>& xadj
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
} // End namespace Foam
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
#ifdef NoRepository
|
|
||||||
# include "parMetisDecompTemplates.C"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
||||||
@ -1,76 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
========= |
|
|
||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
||||||
\\ / O peration |
|
|
||||||
\\ / A nd | Copyright (C) 1991-2009 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 2 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, write to the Free Software Foundation,
|
|
||||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#include "parMetisDecomp.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
// Insert at front of list
|
|
||||||
template<class Type>
|
|
||||||
void Foam::parMetisDecomp::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::parMetisDecomp::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];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
||||||
@ -4,9 +4,7 @@ EXE_INC = \
|
|||||||
$(PFLAGS) $(PINC) \
|
$(PFLAGS) $(PINC) \
|
||||||
-I$(WM_THIRD_PARTY_DIR)/scotch_5.1/include \
|
-I$(WM_THIRD_PARTY_DIR)/scotch_5.1/include \
|
||||||
-I/usr/include/scotch \
|
-I/usr/include/scotch \
|
||||||
/* -I$(LIB_SRC)/parallel/decompose/parMetisDecomp */ \
|
-I../decompositionMethods/lnInclude
|
||||||
/* -I$(LIB_SRC)/parallel/decompose/scotchDecomp */ \
|
|
||||||
-I$(LIB_SRC)/parallel/decompose/decompositionMethods/lnInclude
|
|
||||||
|
|
||||||
LIB_LIBS = \
|
LIB_LIBS = \
|
||||||
-L$(FOAM_MPI_LIBBIN) -lptscotch -lptscotcherrexit
|
-L$(FOAM_MPI_LIBBIN) -lptscotch -lptscotcherrexit
|
||||||
|
|||||||
@ -474,7 +474,7 @@ Foam::labelList Foam::scotchDecomp::decompose
|
|||||||
{
|
{
|
||||||
FatalErrorIn
|
FatalErrorIn
|
||||||
(
|
(
|
||||||
"parMetisDecomp::decompose(const labelList&, const pointField&)"
|
"scotchDecomp::decompose(const labelList&, const pointField&)"
|
||||||
) << "Size of cell-to-coarse map " << agglom.size()
|
) << "Size of cell-to-coarse map " << agglom.size()
|
||||||
<< " differs from number of cells in mesh " << mesh_.nCells()
|
<< " differs from number of cells in mesh " << mesh_.nCells()
|
||||||
<< exit(FatalError);
|
<< exit(FatalError);
|
||||||
|
|||||||
@ -19,7 +19,7 @@ numberOfSubdomains 6;
|
|||||||
|
|
||||||
method hierarchical;
|
method hierarchical;
|
||||||
// method metis;
|
// method metis;
|
||||||
// method parMetis;
|
// method ptscotch;
|
||||||
|
|
||||||
simpleCoeffs
|
simpleCoeffs
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user