Commit 55df3b3f authored by Thomas Witkowski's avatar Thomas Witkowski

Introduced initial partitioner.

parent c3cc7b1a
......@@ -16,15 +16,15 @@
namespace AMDiS {
CheckerPartitioner::CheckerPartitioner(MPI::Intracomm *comm)
: MeshPartitioner(comm),
CheckerPartitioner::CheckerPartitioner(string name, MPI::Intracomm *comm)
: MeshPartitioner(name, comm),
mpiRank(mpiComm->Get_rank()),
mpiSize(mpiComm->Get_size()),
mode(0),
multilevel(false)
{
string modestr = "";
Parameters::get("parallel->partitioner->mode", modestr);
Parameters::get(initFileStr + "->mode", modestr);
if (modestr == "x-stripes")
mode = 1;
......
......@@ -35,7 +35,7 @@ namespace AMDiS {
class CheckerPartitioner : public MeshPartitioner
{
public:
CheckerPartitioner(MPI::Intracomm *comm);
CheckerPartitioner(string name, MPI::Intracomm *comm);
~CheckerPartitioner() {}
......
......@@ -77,6 +77,7 @@ namespace AMDiS {
mesh(NULL),
refineManager(NULL),
partitioner(NULL),
initialPartitioner(NULL),
deserialized(false),
writeSerializationFile(false),
repartitioningAllowed(false),
......@@ -104,36 +105,57 @@ namespace AMDiS {
Parameters::get(name + "->repartition ith change", repartitionIthChange);
Parameters::get(name + "->repartition wait after fail", repartitioningWaitAfterFail);
Parameters::get(name + "->mesh adaptivity", meshAdaptivity);
// === Create partitioner object. ===
string partStr = "parmetis";
Parameters::get(name + "->partitioner", partStr);
if (partStr == "parmetis")
partitioner = new ParMetisPartitioner(&mpiComm);
partitioner = new ParMetisPartitioner("parallel->partitioner", &mpiComm);
if (partStr == "zoltan") {
#ifdef HAVE_ZOLTAN
partitioner = new ZoltanPartitioner(&mpiComm);
partitioner = new ZoltanPartitioner("parallel->partitioner", &mpiComm);
#else
ERROR_EXIT("AMDiS was compiled without Zoltan support. Therefore you cannot make use of it!\n");
#endif
}
if (partStr == "checker")
partitioner = new CheckerPartitioner(&mpiComm);
partitioner = new CheckerPartitioner("parallel->partitioner", &mpiComm);
if (partStr == "simple")
partitioner = new SimplePartitioner(&mpiComm);
partitioner = new SimplePartitioner("parallel->partitioner", &mpiComm);
// === Create initial partitioner object. ===
partStr = "";
Parameters::get(name + "->initial partitioner", partStr);
if (partStr == "") {
initialPartitioner = partitioner;
} else {
if (partStr == "checker") {
initialPartitioner =
new CheckerPartitioner("parallel->initial partitioner", &mpiComm);
} else {
ERROR_EXIT("Not yet supported, but very easy to implement!\n");
}
}
// === And read some more parameters. ===
int tmp = 0;
Parameters::get(name + "->box partitioning", tmp);
partitioner->setBoxPartitioning(static_cast<bool>(tmp));
initialPartitioner->setBoxPartitioning(static_cast<bool>(tmp));
Parameters::get(name + "->print timings", printTimings);
Parameters::get(name + "->print memory usage", printMemoryUsage);
TEST_EXIT(partitioner)("Could not create partitioner \"%s\"!\n", partStr.c_str());
// If required, create hierarchical mesh level structure.
createMeshLevelStructure();
}
......@@ -141,8 +163,10 @@ namespace AMDiS {
MeshDistributor::~MeshDistributor()
{
if (partitioner)
if (partitioner) {
delete partitioner;
partitioner = NULL;
}
}
......@@ -357,18 +381,24 @@ namespace AMDiS {
createMacroElementInfo();
// create an initial partitioning of the mesh
bool useInitialPartitioning = partitioner->createInitialPartitioning();
bool useInitialPartitioning =
initialPartitioner->createInitialPartitioning();
// set the element weights, which are 1 at the very first begin
setInitialElementWeights();
if (!useInitialPartitioning) {
if (!useInitialPartitioning) {
// and now partition the mesh
bool partitioningSucceed = partitioner->partition(elemWeights, INITIAL);
bool partitioningSucceed =
initialPartitioner->partition(elemWeights, INITIAL);
TEST_EXIT(partitioningSucceed)("Initial partitioning does not work!\n");
}
partitioner->createPartitionMap(partitionMap);
initialPartitioner->createPartitionMap(partitionMap);
if (initialPartitioner != partitioner) {
*partitioner = *initialPartitioner;
}
}
......@@ -462,6 +492,7 @@ namespace AMDiS {
}
partitioner->setMesh(mesh);
initialPartitioner->setMesh(mesh);
// === Check whether the stationary problem should be serialized. ===
......@@ -1446,15 +1477,7 @@ namespace AMDiS {
if (!partitioner->meshChanged()) {
MSG("Mesh partition does not create a new partition!\n");
MSG("Try to refine partitioning!\n");
partitioningSucceed = partitioner->partition(elemWeights, REFINE_PART);
if (partitioningSucceed) {
MSG("OKAY, ERST MAL GUT!\n");
if (partitioner->meshChanged())
MSG("UND JA, DAS WARS!\n");
else
MSG("NE, LEIDER NICHT!\n");
}
partitioningSucceed = partitioner->partition(elemWeights, REFINE_PART);
if (!partitioningSucceed || !partitioner->meshChanged()) {
mpiComm.Barrier();
repartitioningFailed = repartitioningWaitAfterFail;;
......
......@@ -504,6 +504,12 @@ namespace AMDiS {
/// the ranks.
MeshPartitioner *partitioner;
/// Pointer to a mesh partitioner that is used for the very first
/// partitioning of the mesh. In most cases, this pointer points to the
/// same object as \ref partitioner, but this must not be the case in
/// general.
MeshPartitioner *initialPartitioner;
/// Weights for the elements, i.e., the number of leaf elements within
/// this element.
map<int, double> elemWeights;
......
......@@ -34,7 +34,8 @@ namespace AMDiS {
map<int, int> arhElCodeSize;
string partitioningFile = "";
Parameters::get("parallel->initial partitioning file", partitioningFile);
Parameters::get(initFileStr + "->initial partitioning file",
partitioningFile);
if (partitioningFile != "") {
MSG("Read initial partitioning file: %s\n", partitioningFile.c_str());
......@@ -54,7 +55,8 @@ namespace AMDiS {
useInitialPartitioning = true;
} else {
string arhMetaFile = "";
Parameters::get("parallel->partitioner->read meta arh", arhMetaFile);
Parameters::get(initFileStr + "->read meta arh",
arhMetaFile);
bool partitioningArhBased = (arhMetaFile != "");
if (partitioningArhBased) {
int nProc = ArhReader::readMetaData(arhMetaFile, mapElInRank, arhElCodeSize);
......
......@@ -53,8 +53,9 @@ namespace AMDiS {
class MeshPartitioner
{
public:
MeshPartitioner(MPI::Intracomm *comm)
: mpiComm(comm),
MeshPartitioner(string name, MPI::Intracomm *comm)
: initFileStr(name),
mpiComm(comm),
mesh(NULL),
boxPartitioning(false),
mapLocalGlobal(NULL)
......@@ -149,6 +150,9 @@ namespace AMDiS {
}
protected:
/// Prefix for reading parameters from init file.
string initFileStr;
/// Pointer to the MPI communicator the mesh partitioner should make use of.
MPI::Intracomm *mpiComm;
......
......@@ -168,8 +168,8 @@ namespace AMDiS {
class ParMetisPartitioner : public MeshPartitioner
{
public:
ParMetisPartitioner(MPI::Intracomm *comm)
: MeshPartitioner(comm),
ParMetisPartitioner(string name, MPI::Intracomm *comm)
: MeshPartitioner(name, comm),
parMetisMesh(NULL),
itr(1000000.0)
{}
......
......@@ -40,8 +40,8 @@ namespace AMDiS {
class SimplePartitioner : public MeshPartitioner
{
public:
SimplePartitioner(MPI::Intracomm *comm)
: MeshPartitioner(comm)
SimplePartitioner(string name, MPI::Intracomm *comm)
: MeshPartitioner(name, comm)
{}
~SimplePartitioner() {}
......
......@@ -18,8 +18,9 @@
namespace AMDiS {
ZoltanPartitioner::ZoltanPartitioner(MPI::Intracomm *comm)
: MeshPartitioner(comm),
ZoltanPartitioner::ZoltanPartitioner(string name,
MPI::Intracomm *comm)
: MeshPartitioner(name, comm),
zoltan(*comm),
elWeights(NULL)
{}
......
......@@ -37,7 +37,7 @@ namespace AMDiS {
class ZoltanPartitioner : public MeshPartitioner
{
public:
ZoltanPartitioner(MPI::Intracomm *comm);
ZoltanPartitioner(string name, MPI::Intracomm *comm);
~ZoltanPartitioner() {}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment