6#include <kernel/geometry/parti_zoltan.hpp> 
   12using namespace Geometry;
 
   27extern "C" int feat_zoltan_num_elems(
void* data, 
int* ierr)
 
   30  const Adjacency::Graph& grp = 
reinterpret_cast<const PartiZoltan::Hypergraph*
>(data)->sub_graph;
 
   31  return int(grp.get_num_nodes_domain());
 
   45extern "C" void feat_zoltan_elem_list(
void* data, 
int size_gid, 
int size_lid,
 
   46  ZOLTAN_ID_PTR global_id, ZOLTAN_ID_PTR DOXY(local_id), 
int wgt_dim, 
float* obj_wgts, 
int* ierr)
 
   51  const PartiZoltan::Hypergraph& hyg = *
reinterpret_cast<const PartiZoltan::Hypergraph*
>(data);
 
   52  const Index n = hyg.sub_graph.get_num_nodes_domain();
 
   53  for(
Index i(0); i < n; ++i)
 
   54    global_id[i] = ZOLTAN_ID_TYPE(hyg.first_elem + i);
 
   57    for(
Index i(0); i < n; ++i)
 
   58      obj_wgts[i] = hyg.weights[i];
 
   72extern "C" void feat_zoltan_hypergraph_size(
void* data, 
int* num_lists, 
int* num_nonzeroes, 
int* format, 
int* ierr)
 
   75  const Adjacency::Graph& grp = 
reinterpret_cast<const PartiZoltan::Hypergraph*
>(data)->sub_graph;
 
   76  *num_lists = int(grp.get_num_nodes_domain());
 
   78  *format = ZOLTAN_COMPRESSED_EDGE;
 
   91extern "C" void feat_zoltan_hypergraph_data(
void* data, 
int size_gid, 
int num_edges, 
int num_nonzeroes,
 
   92  int format, ZOLTAN_ID_PTR edgeGID, 
int* vtxPtr, ZOLTAN_ID_PTR vtxGID, 
int* ierr)
 
   94  const Adjacency::Graph& grp = 
reinterpret_cast<const PartiZoltan::Hypergraph*
>(data)->sub_graph;
 
   96  XASSERT(num_edges == 
int(grp.get_num_nodes_domain()));
 
   98  XASSERT(format == ZOLTAN_COMPRESSED_EDGE);
 
  104  for(
int i(0); i < num_edges; ++i)
 
  106    edgeGID[i] = ZOLTAN_ID_TYPE(i);
 
  107    vtxPtr[i] = int(dom_ptr[i]);
 
  111  for(
int i(0); i < num_nonzeroes; ++i)
 
  113    vtxGID[i] = ZOLTAN_ID_TYPE(img_idx[i]);
 
  124      _zoltan_comm(Dist::Comm::null()),
 
  125      _max_procs(max_procs),
 
  126      _min_elems(min_elems),
 
  135    PartiZoltan::~PartiZoltan()
 
  139        Zoltan_Destroy(
reinterpret_cast<Zoltan_Struct**
>(&_zz));
 
  144    bool PartiZoltan::execute(
const Adjacency::Graph& faces_at_elem, 
const Index num_parts, 
const std::vector<Real>& weights)
 
  147      this->_num_parts = num_parts;
 
  148      this->_num_elems = faces_at_elem.get_num_nodes_domain();
 
  151      int num_procs = Math::max(1, 
int(faces_at_elem.get_num_nodes_domain() / _min_elems));
 
  153        Math::mini(num_procs, _max_procs);
 
  154      Math::mini(num_procs, 
int(num_parts));
 
  155      Math::mini(num_procs, _comm.size());
 
  158      if(num_procs < _comm.size())
 
  159        _zoltan_comm = _comm.comm_create_range_incl(num_procs);
 
  161        _zoltan_comm = _comm.comm_dup();
 
  165      const int z_size = _zoltan_comm.size();
 
  168      XASSERTM(
Index(z_size) <= num_parts, 
"thou shall not create less partitions than thou hast ranks");
 
  176        this->_create_hypergraph(faces_at_elem, weights);
 
  179        is_ok = this->_apply_zoltan();
 
  183      return this->_broadcast_coloring(is_ok);
 
  186    void PartiZoltan::_create_hypergraph(
const Adjacency::Graph& faces_at_elem, 
const std::vector<Real>& weights)
 
  189      const Index num_elems = faces_at_elem.get_num_nodes_domain();
 
  190      const Index num_faces = faces_at_elem.get_num_nodes_image();
 
  193      const int z_rank = _zoltan_comm.rank();
 
  194      const int z_size = _zoltan_comm.size();
 
  202      Index my_num_elems = end_elem - first_elem;
 
  208      const Index first_ptr = dom_ptr[first_elem];
 
  209      const Index my_num_idx = dom_ptr[end_elem] - first_ptr;
 
  212      Index* my_dom_ptr = faces_at_my_elem.get_domain_ptr();
 
  213      Index* my_img_idx = faces_at_my_elem.get_image_idx();
 
  214      for(
Index i(0); i <= my_num_elems; ++i)
 
  215        my_dom_ptr[i] = dom_ptr[first_elem + i] - first_ptr;
 
  216      for(
Index i(0); i < my_num_idx; ++i)
 
  217        my_img_idx[i] = img_idx[first_ptr + i];
 
  220      Adjacency::Graph elems_at_faces(Adjacency::RenderType::transpose, faces_at_elem);
 
  223      this->_hypergraph.first_elem = first_elem;
 
  224      this->_hypergraph.sub_graph = 
Adjacency::Graph(Adjacency::RenderType::injectify_sorted, faces_at_my_elem, elems_at_faces);
 
  229        XASSERT(end_elem <= weights.size());
 
  230        this->_hypergraph.weights.resize(my_num_elems);
 
  231        for(
Index i(0); i < my_num_elems; ++i)
 
  232          this->_hypergraph.weights[i] = 
float(weights[first_elem + i]);
 
  236    bool PartiZoltan::_apply_zoltan()
 
  239      Zoltan_Struct* zz = Zoltan_Create(_zoltan_comm.mpi_comm());
 
  243      Zoltan_Set_Param(zz, 
"DEBUG_LEVEL", 
"0");
 
  244      Zoltan_Set_Param(zz, 
"LB_METHOD", 
"HYPERGRAPH");
 
  245      Zoltan_Set_Param(zz, 
"HYPERGRAPH_PACKAGE", 
"PHG");
 
  246      Zoltan_Set_Param(zz, 
"LB_APPROACH", 
"PARTITION");
 
  247      Zoltan_Set_Param(zz, 
"NUM_GID_ENTRIES", 
"1");
 
  248      Zoltan_Set_Param(zz, 
"NUM_LID_ENTRIES", 
"0");
 
  249      Zoltan_Set_Param(zz, 
"RETURN_LISTS", 
"PARTS");
 
  250      Zoltan_Set_Param(zz, 
"NUM_GLOBAL_PARTS", 
stringify(this->_num_parts).c_str());
 
  251      Zoltan_Set_Param(zz, 
"OBJ_WEIGHT_DIM", this->_hypergraph.weights.empty() ? 
"0" : 
"1");
 
  252      Zoltan_Set_Param(zz, 
"EDGE_WEIGHT_DIM", 
"0");
 
  254      Zoltan_Set_Param(zz, 
"PHG_EDGE_SIZE_THRESHOLD", 
"1.0"); 
 
  257      Zoltan_Set_Num_Obj_Fn(zz, feat_zoltan_num_elems, &this->_hypergraph);
 
  258      Zoltan_Set_Obj_List_Fn(zz, feat_zoltan_elem_list, &this->_hypergraph);
 
  259      Zoltan_Set_HG_Size_CS_Fn(zz, feat_zoltan_hypergraph_size, &this->_hypergraph);
 
  260      Zoltan_Set_HG_CS_Fn(zz, feat_zoltan_hypergraph_data, &this->_hypergraph);
 
  262      int changes(0), num_gid_entries(0), num_lid_entries(0), num_import(0), num_export(0);
 
  263      ZOLTAN_ID_PTR import_global_ids(
nullptr);
 
  264      ZOLTAN_ID_PTR import_local_ids(
nullptr);
 
  265      int* import_procs(
nullptr);
 
  266      int* import_parts(
nullptr);
 
  267      ZOLTAN_ID_PTR export_global_ids(
nullptr);
 
  268      ZOLTAN_ID_PTR export_local_ids(
nullptr);
 
  269      int* export_procs(
nullptr);
 
  270      int* export_parts(
nullptr);
 
  272      int rtn = Zoltan_LB_Partition(zz, &changes, &num_gid_entries, &num_lid_entries,
 
  273        &num_import, &import_global_ids, &import_local_ids, &import_procs, &import_parts,
 
  274        &num_export, &export_global_ids, &export_local_ids, &export_procs, &export_parts);
 
  277      bool gather_ok = 
true;
 
  279        gather_ok = this->_gather_coloring(num_export, export_parts);
 
  281      Zoltan_LB_Free_Part(&import_global_ids, &import_local_ids, &import_procs, &import_parts);
 
  282      Zoltan_LB_Free_Part(&export_global_ids, &export_local_ids, &export_procs, &export_parts);
 
  287      return gather_ok && (rtn == ZOLTAN_OK);
 
  290    bool PartiZoltan::_gather_coloring(
const int num_export, 
const int* export_parts)
 
  293      const Index z_rank = 
Index(_zoltan_comm.rank());
 
  294      const Index z_size = 
Index(_zoltan_comm.size());
 
  298      _zoltan_comm.allreduce(&max_export, &max_export, 1u, Dist::op_max);
 
  302      std::vector<int> send_buf(max_export);
 
  303      send_buf[0] = num_export;
 
  305        send_buf[i+1] = export_parts[i];
 
  308      std::vector<int> recv_buf(z_rank == 0 ? max_export * z_size : 
Index(0));
 
  309      _zoltan_comm.gather(send_buf.data(), max_export, recv_buf.data(), max_export, 0);
 
  317      for(
Index i(0); i < z_size; ++i)
 
  318        num_elems += 
Index(recv_buf[i*max_export]);
 
  322      Index* col = this->_coloring.get_coloring();
 
  325      for(
Index i(0), k(0); i < z_size; ++i)
 
  327        Index off = i*max_export;
 
  329        for(
Index j(1); j <= n; ++j, ++k)
 
  330          col[k] = 
Index(recv_buf[off+j]);
 
  334      std::vector<int> color_counts(this->_num_parts, 0);
 
  335      for(
Index i(0); i < this->_num_elems; ++i)
 
  336        ++color_counts[col[i]];
 
  339      for(
Index i(0); i < this->_num_parts; ++i)
 
  341        if(color_counts[i] == 0)
 
  349    bool PartiZoltan::_broadcast_coloring(
bool zoltan_ok)
 
  353      int was_ok(zoltan_ok ? 0 : 1),  was_all_ok(0);
 
  354      this->_comm.allreduce(&was_ok, &was_all_ok, std::size_t(1), Dist::op_sum);
 
  359      if(this->_comm.rank() > 0)
 
  363      this->_comm.bcast(this->_coloring.get_coloring(), this->_num_elems, 0);
 
  374void zoltan_did_not_make_it_to_the_feat_parti() {}
 
#define XASSERT(expr)
Assertion macro definition.
#define XASSERTM(expr, msg)
Assertion macro definition with custom message.
Coloring object implementation.
Adjacency Graph implementation.
Index * get_domain_ptr()
Returns the domain pointer array.
Index * get_image_idx()
Returns the image node index array.
Index get_num_indices() const
Returns the total number indices.
PartiZoltan(const Dist::Comm &comm, Index min_elems=1000u, int max_procs=1000)
Constructor.
String stringify(const T_ &item)
Converts an item into a String.
std::uint64_t Index
Index data type.