Skip to content
Snippets Groups Projects
Commit 55df3b3f authored by Thomas Witkowski's avatar Thomas Witkowski
Browse files

Introduced initial partitioner.

parent c3cc7b1a
No related branches found
No related tags found
No related merge requests found
......@@ -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() {}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment