From 84b1464805def42f8f07718ca9bf92df01ed5928 Mon Sep 17 00:00:00 2001
From: Thomas Witkowski <thomas.witkowski@gmx.de>
Date: Tue, 25 Jan 2011 09:11:27 +0000
Subject: [PATCH] Forgotten to add the ZoltanPartitioner files to repository.

---
 AMDiS/src/parallel/ZoltanPartitioner.cc | 242 ++++++++++++++++++++++++
 AMDiS/src/parallel/ZoltanPartitioner.h  |  82 ++++++++
 2 files changed, 324 insertions(+)
 create mode 100644 AMDiS/src/parallel/ZoltanPartitioner.cc
 create mode 100644 AMDiS/src/parallel/ZoltanPartitioner.h

diff --git a/AMDiS/src/parallel/ZoltanPartitioner.cc b/AMDiS/src/parallel/ZoltanPartitioner.cc
new file mode 100644
index 00000000..11708dda
--- /dev/null
+++ b/AMDiS/src/parallel/ZoltanPartitioner.cc
@@ -0,0 +1,242 @@
+//
+// Software License for AMDiS
+//
+// Copyright (c) 2010 Dresden University of Technology 
+// All rights reserved.
+// Authors: Simon Vey, Thomas Witkowski et al.
+//
+// This file is part of AMDiS
+//
+// See also license.opensource.txt in the distribution.
+
+#include <boost/lexical_cast.hpp>
+#include "parallel/ZoltanPartitioner.h"
+#include "Traverse.h"
+#include "ElInfo.h"
+
+namespace AMDiS {
+
+  ZoltanPartitioner::ZoltanPartitioner(MPI::Intracomm *comm)
+    : MeshPartitioner(comm),
+      zoltan(*comm)
+  {
+    zoltan.Set_Num_Obj_Fn(ZoltanFunctions::getNumObj, this);
+    zoltan.Set_Obj_List_Fn(ZoltanFunctions::getObjectList, this);
+    zoltan.Set_Num_Geom_Fn(ZoltanFunctions::getNumGeom, this);
+    zoltan.Set_Geom_Multi_Fn(ZoltanFunctions::getGeomMulti, this);
+  }
+
+
+  bool ZoltanPartitioner::partition(map<int, double> &elemWeights,
+				    PartitionMode mode)
+  {
+    FUNCNAME("ZoltanPartitioner::partition()");
+
+    using boost::lexical_cast;
+
+    int changes;
+    int nGid, nLid;
+
+    int nImportEls;   
+    ZOLTAN_ID_PTR import_global_ids, import_local_ids;
+    int *import_procs;
+    int *import_to_part;
+
+    int nExportEls;
+    ZOLTAN_ID_PTR export_global_ids, export_local_ids;
+    int *export_procs;
+    int *export_to_part;
+
+    zoltan.Set_Param("LB_METHOD", "RCB");
+    zoltan.Set_Param("NUM_GLOBAL_PARTS", 
+		     lexical_cast<string>(mpiComm->Get_size()).c_str());
+    int err = zoltan.LB_Partition(changes, nGid, nLid, 
+				  nImportEls,
+				  import_global_ids,
+				  import_local_ids,
+				  import_procs,
+				  import_to_part,
+				  nExportEls,
+				  export_global_ids,
+				  export_local_ids,
+				  export_procs,
+				  export_to_part);
+    
+    recvElements.clear();
+    sendElements.clear();
+
+    if (err == ZOLTAN_OK && changes != 0) {   
+      if (nImportEls > 0) {
+	for (int i = 0; i < nImportEls; i++) {
+	  int recvElIndex = import_global_ids[i];
+	  
+	  elementInRank[recvElIndex] = true;
+	  recvElements[import_procs[i]].push_back(recvElIndex);
+	}
+      }
+      
+      if (nExportEls > 0) {
+	for (int i = 0; i < nExportEls; i++) {
+	  int sendElIndex = export_global_ids[i];
+	  
+	  elementInRank[sendElIndex] = false;
+	  sendElements[export_procs[i]].push_back(sendElIndex);
+	}      
+      }
+    }
+
+    zoltan.LB_Free_Part(&import_global_ids, &import_local_ids, 
+			&import_procs, &import_to_part);
+    zoltan.LB_Free_Part(&export_global_ids, &export_local_ids, 
+			&export_procs, &export_to_part);      
+
+    if (err != ZOLTAN_OK)
+      return false;
+
+    return true;
+  }
+
+
+  void ZoltanPartitioner::getPartitionMap(map<int, int> &partitionMap)
+  {
+    FUNCNAME("ZoltanPartitioner::getPartitionMap()");
+
+    int mpiSize = mpiComm->Get_size();
+
+    vector<int> localElements;
+    for (map<int, bool>::iterator it = elementInRank.begin(); 
+	 it != elementInRank.end(); ++it)
+      if (it->second)
+	localElements.push_back(it->first);
+ 
+    int nLocalElements = localElements.size();
+    vector<int> nPartitionElements(mpiSize);
+    vector<int> elDist(mpiSize + 1);
+    mpiComm->Allgather(&nLocalElements, 1, MPI_INT, &(elDist[1]), 1, MPI_INT);
+
+    elDist[0] = 0;
+    nPartitionElements[0] = elDist[1];
+
+    for (int i = 2; i <= mpiSize; i++) {
+      nPartitionElements[i - 1] = elDist[i];
+      elDist[i] += elDist[i - 1];
+    }
+
+    int nOverallElements = elDist[mpiSize];
+
+    TEST_EXIT_DBG(nOverallElements == static_cast<int>(elementInRank.size()))
+      ("Number of elements differs: %d %d!\n", nOverallElements, elementInRank.size());
+
+    vector<int> partitionElements(nOverallElements);
+
+    // distribute partition elements
+    mpiComm->Allgatherv(&(localElements[0]),
+			nLocalElements, 
+			MPI_INT, 
+			&(partitionElements[0]), 
+			&(nPartitionElements[0]), 
+			&(elDist[0]),
+			MPI_INT);
+
+    // fill partitionMap
+    for (int i = 0; i < mpiSize; i++)
+      for (int j = 0; j < nPartitionElements[i]; j++)
+	partitionMap[partitionElements[elDist[i] + j]] = i;
+  }
+
+  
+
+  int ZoltanFunctions::getNumObj(void *data, int *ierr)
+  {
+    ZoltanPartitioner* zoltan = (ZoltanPartitioner*)data;
+    map<int, bool>& elInRank = zoltan->getElementInRank();
+
+    int nObjects = 0;
+    for (map<int, bool>::iterator it = elInRank.begin(); it != elInRank.end(); ++it)
+      if (it->second)
+	nObjects++;
+
+    *ierr = ZOLTAN_OK;
+
+    return nObjects;
+  }
+
+
+  void ZoltanFunctions::getObjectList(void *data, 
+				      int sizeGid, 
+				      int sizeLid,
+				      ZOLTAN_ID_PTR globalId, 
+				      ZOLTAN_ID_PTR localId,
+				      int wgt_dim, 
+				      float *obj_wgts, 
+				      int *ierr)
+  {
+    ZoltanPartitioner* zoltan = (ZoltanPartitioner*)data;
+    map<int, bool>& elInRank = zoltan->getElementInRank();
+    int localCounter = 0;
+
+    for (map<int, bool>::iterator it = elInRank.begin(); it != elInRank.end(); ++it) {
+      if (it->second) {
+	globalId[localCounter] = it->first;
+	localId[localCounter] = localCounter;
+	localCounter++;
+      }
+    }
+
+    *ierr = ZOLTAN_OK;
+  }
+
+
+  int ZoltanFunctions::getNumGeom(void *data, int *ierr)
+  {
+    ZoltanPartitioner* zoltan = (ZoltanPartitioner*)data;
+    *ierr = ZOLTAN_OK;
+
+    return zoltan->getMesh()->getGeo(WORLD);
+  }
+
+
+  void ZoltanFunctions::getGeomMulti(void *data, 
+				     int num_gid_entries, 
+				     int num_lid_entries, 
+				     int num_obj, 
+				     ZOLTAN_ID_PTR global_ids, 
+				     ZOLTAN_ID_PTR local_ids, 
+				     int num_dim, 
+				     double *geom_vec, 
+				     int *ierr)
+  {
+    FUNCNAME("ZoltanFunctions::getGeomMulti()");
+
+    ZoltanPartitioner* zoltan = (ZoltanPartitioner*)data;
+    Mesh *mesh = zoltan->getMesh();
+
+    TEST_EXIT_DBG(num_dim == mesh->getGeo(WORLD))("Should not happen!\n");
+
+    map<int, WorldVector<double> > elIndexToCoords;    
+    DimVec<double> bary(mesh->getDim(), DEFAULT_VALUE, 1.0 / mesh->getGeo(VERTEX));
+    WorldVector<double> coords;
+    TraverseStack stack;
+    ElInfo *elInfo = 
+      stack.traverseFirst(mesh, 0, Mesh::CALL_EL_LEVEL | Mesh::FILL_COORDS);
+    while (elInfo) {
+      elInfo->coordToWorld(bary, coords);
+      elIndexToCoords[elInfo->getElement()->getIndex()] = coords;
+
+      elInfo = stack.traverseNext(elInfo);
+    }
+
+    int c = 0;
+    for (int i = 0; i < num_obj; i++) {
+      int elIndex = global_ids[i];
+
+      TEST_EXIT_DBG(elIndexToCoords.count(elIndex))("Should not happen!\n");
+      
+      for (int j = 0; j < num_dim; j++)
+	geom_vec[c++] = elIndexToCoords[elIndex][j];
+    }
+
+    *ierr = ZOLTAN_OK;
+  }
+  
+}
diff --git a/AMDiS/src/parallel/ZoltanPartitioner.h b/AMDiS/src/parallel/ZoltanPartitioner.h
new file mode 100644
index 00000000..1558a172
--- /dev/null
+++ b/AMDiS/src/parallel/ZoltanPartitioner.h
@@ -0,0 +1,82 @@
+// ============================================================================
+// ==                                                                        ==
+// == AMDiS - Adaptive multidimensional simulations                          ==
+// ==                                                                        ==
+// ==  http://www.amdis-fem.org                                              ==
+// ==                                                                        ==
+// ============================================================================
+//
+// Software License for AMDiS
+//
+// Copyright (c) 2010 Dresden University of Technology 
+// All rights reserved.
+// Authors: Simon Vey, Thomas Witkowski et al.
+//
+// This file is part of AMDiS
+//
+// See also license.opensource.txt in the distribution.
+
+
+
+/** \file ZoltanPartitioner.h */
+
+#ifndef AMDIS_ZOLTAN_PARTITIONER_H
+#define AMDIS_ZOLTAN_PARTITIONER_H
+
+#include <zoltan_cpp.h>
+#include <set>
+#include "AMDiS_fwd.h"
+#include "parallel/MeshPartitioner.h"
+
+namespace AMDiS {
+
+  using namespace std;
+
+  class ZoltanPartitioner : public MeshPartitioner
+  {
+  public:
+    ZoltanPartitioner(MPI::Intracomm *comm);
+
+    ~ZoltanPartitioner() {}
+      
+    /// \ref MeshPartitioner::partition
+    bool partition(map<int, double> &elemWeights, PartitionMode mode = INITIAL);
+
+    /// \ref MeshPartitioner::getPartitionMap
+    void getPartitionMap(map<int, int> &partitionMap);
+
+  protected:
+    Zoltan zoltan;
+  };
+
+
+  class ZoltanFunctions
+  {
+  public:
+    static int getNumObj(void *data, int *ierr);   
+
+    static void getObjectList(void *data, 
+			      int sizeGid, 
+			      int sizeLid,
+			      ZOLTAN_ID_PTR globalId, 
+			      ZOLTAN_ID_PTR localId,
+			      int wgt_dim, 
+			      float *obj_wgts, 
+			      int *ierr);
+
+    static int getNumGeom(void *data, int *ierr);
+
+    static void getGeomMulti(void *data, 
+			     int num_gid_entries, 
+			     int num_lid_entries, 
+			     int num_obj, 
+			     ZOLTAN_ID_PTR global_ids, 
+			     ZOLTAN_ID_PTR local_ids, 
+			     int num_dim, 
+			     double *geom_vec, 
+			     int *ierr); 
+  };
+
+}
+
+#endif
-- 
GitLab