AFEPack
MPI_ULoadBalance.h
浏览该文件的文档。
00001 
00051 #ifndef __MPI_ULoadBalance_h__
00052 #define __MPI_ULoadBalance_h__
00053 
00054 #ifdef __MPI_LoadBalance_h__
00055 #error "MPI_LoadBalance.h 和 MPI_ULoadBalance.h 是冲突的,不能一起用。"
00056 #endif
00057 
00058 #include <sys/types.h>
00059 #include <sys/stat.h>
00060 #include <unistd.h>
00061 #include <cstdio>
00062 
00063 #include <boost/program_options.hpp>
00064 #include <boost/archive/binary_iarchive.hpp>
00065 #include <boost/archive/binary_oarchive.hpp>
00066 #include <boost/archive/text_iarchive.hpp>
00067 #include <boost/archive/text_oarchive.hpp>
00068 
00069 #include <AFEPack/Serialization.h>
00070 #include "MPI.h"
00071 #include "MPI_UGeometry_archive.h"
00072 #include "MPI_Migration.h"
00073 
00074 namespace MPI {
00075 
00076   template <class FOREST>
00077     class HLoadBalance {
00078   public:
00079     typedef FOREST forest_t;
00080     enum {dim = FOREST::dim, dow = FOREST::dow};
00081     typedef typename forest_t::matcher_t matcher_t;
00082     
00083     struct rank_map_val {
00084       int old_rank; 
00085       bool is_dummy; 
00086     };
00087     typedef std::map<int,rank_map_val> rank_map_t;
00088   private:
00089   // 在计算每个几何体上的负载是使用的性质
00090   property_id_t<u_int> _pid_loading;
00091 
00096   property_id_t<rank_map_t> _pid_rank_map;
00097 
00098   // 部分需要拆分和合并的几何体的全局标号
00099   property_id_t<unsigned long> _pid_global_idx;
00100 
00101   // 元素为(全局标号,对象指针)的对
00102   std::map<unsigned long, void *> _global_pointer_to_merge;
00103   std::map<unsigned long, std::list<void *> > _global_pointer_to_merge_later;
00104 
00105   // (进程,列表(全局标号,维数,对象指针)组)的映射
00106   typedef std::map<unsigned long, std::pair<int, void *> > tuple_map_t;
00107   std::map<int, tuple_map_t> _global_pointer_to_share;
00108 
00109   typedef BirdView<forest_t> birdview_t;
00110   typedef BirdViewSet<forest_t> birdview_set_t;
00111   typedef HLoadBalance<forest_t> this_t;
00112 
00113   forest_t * _forest; 
00114   std::vector<u_int> _cut_point; 
00115   std::vector<int> _new_rank; 
00116 
00117   typename forest_t::container_t _nre; 
00118 
00119   public:
00120   HLoadBalance(forest_t& forest) : _forest(&forest) {}
00121   ~HLoadBalance() {}
00122 
00123   private:
00124   template <class GEO> rank_map_t *
00125   new_rank_map(const GEO& geo) const {
00126     return geo.new_property(_pid_rank_map);
00127   }
00128   template <class GEO> unsigned long *
00129   new_global_idx(const GEO& geo) const {
00130     return geo.new_property(_pid_global_idx);
00131   }
00132 
00133   public:
00134   void clear() {
00135     free_property_id(_pid_loading);
00136     free_property_id(_pid_rank_map);
00137     free_property_id(_pid_global_idx);
00138     _global_pointer_to_merge.clear();
00139     _global_pointer_to_merge_later.clear();
00140     _global_pointer_to_share.clear();
00141     _cut_point.clear();
00142     _new_rank.clear();
00143   }
00144 
00145   template <class GEO> rank_map_t *
00146   get_rank_map(const GEO& geo) const {
00147     return geo.get_property(_pid_rank_map);
00148   }
00149   template <class GEO> unsigned long *
00150   get_global_idx(const GEO& geo) const {
00151     return geo.get_property(_pid_global_idx);
00152   }
00153 
00157   template <class GEO> bool 
00158     is_on_this_new_rank(const GEO& geo,
00159                         int new_rank) const {
00160     rank_map_t * p_map = this->get_rank_map(geo);
00161     if (p_map == NULL) return false;
00162     typename rank_map_t::iterator
00163       the_pair = p_map->find(new_rank);
00164     return (the_pair != p_map->end());
00165   }
00166 
00175   template <class GEO> bool
00176     is_save_on_this_rank(const GEO& geo,
00177                          int new_rank) const {
00178     rank_map_t * p_map = this->get_rank_map(geo);
00179     if (p_map == NULL) return false;
00180     typename rank_map_t::iterator
00181       the_pair = p_map->find(new_rank);
00183     if (the_pair == p_map->end()) return false;
00184 
00186     return (the_pair->second.old_rank == _forest->rank()); 
00187   }
00188 
00192   template <class GEO> bool 
00193     is_dummy_on_this_new_rank(const GEO& geo,
00194                                 int new_rank) const {
00195     rank_map_t * p_map = this->get_rank_map(geo);
00196     if (p_map == NULL) return false;
00197     typename rank_map_t::iterator
00198       the_pair = p_map->find(new_rank);
00199     if (the_pair == p_map->end()) return false;
00200     return (the_pair->second.is_dummy);
00201   }
00202 
00214   template <class GEO>
00215   void merge_global_pointer(int type,
00216                             unsigned long global_idx,
00217                             GEO *& p_geo) {
00218     std::map<unsigned long, void *>::iterator
00219     the_pair = _global_pointer_to_merge.find(global_idx);
00220     if (type == 2) {
00221       if (the_pair == _global_pointer_to_merge.end()) {
00222         _global_pointer_to_merge.insert(std::pair<unsigned long,void*>(global_idx, p_geo));
00223 
00227         std::map<unsigned long, std::list<void *> >::iterator
00228           the_entry = _global_pointer_to_merge_later.find(global_idx);
00229         if (the_entry != _global_pointer_to_merge_later.end()) {
00230           std::list<void *>::iterator
00231             the_ptr = the_entry->second.begin(),
00232             end_ptr = the_entry->second.end();
00233           for (;the_ptr != end_ptr;++ the_ptr) {
00234             GEO ** geo_ptr_ptr = (GEO **)(*the_ptr);
00235             (*geo_ptr_ptr) = p_geo;
00236           }
00237           _global_pointer_to_merge_later.erase(the_entry);
00238         }
00239       } else {
00240         assert (the_pair->second == p_geo);
00241       }
00242     } else {
00243       assert (type == 4);
00244       if (the_pair != _global_pointer_to_merge.end()) {
00245         p_geo = (GEO *)(the_pair->second);
00246       } else {
00247         _global_pointer_to_merge_later[global_idx].push_back((void *)(&p_geo));
00248       }
00249     }
00250   }
00251 
00260   template <class GEO>
00261   void share_global_pointer(int rank, 
00262                             unsigned long global_idx,
00263                             GEO *& p_geo) {
00264     _global_pointer_to_share[rank][global_idx] = 
00265       std::pair<int,void *>(p_geo->dimension, (void *)(p_geo));
00266   }
00267 
00268   private:
00272   void share_global_pointer() {
00273     std::cerr << "Exchanging shared global pointers ..." << std::endl;
00274 
00275     typedef std::map<int, tuple_map_t> map_t;
00276 
00277     int n = 0;
00278     std::list<int> target;
00279     std::list<BinaryBuffer<> > out_buf, in_buf;
00280     typename map_t::iterator
00281     the_pair = _global_pointer_to_share.begin(),
00282     end_pair = _global_pointer_to_share.end();
00283     for (;the_pair != end_pair;++ the_pair, ++ n) {
00284       target.push_back(the_pair->first);
00285 
00286       out_buf.push_back(BinaryBuffer<>());
00287       AFEPack::ostream<> os(out_buf.back());
00288       
00289       in_buf.push_back(BinaryBuffer<>());
00290 
00291       u_int n_item = the_pair->second.size();
00292       os << n_item;
00293       std::cerr << "sending " << the_pair->second.size()
00294                 << " items from " << _forest->rank()
00295                 << " to " << the_pair->first << std::endl;
00296       typename tuple_map_t::iterator
00297         the_tuple = the_pair->second.begin(),
00298         end_tuple = the_pair->second.end();
00299       for (;the_tuple != end_tuple;++ the_tuple) {
00300         const unsigned long& global_idx = the_tuple->first;
00301         int& dimension = the_tuple->second.first;
00302         void *& p_obj = the_tuple->second.second;
00303         os << global_idx << dimension << p_obj;
00304       }
00305     }
00306 
00307     MPI_Barrier(_forest->communicator());
00308     sendrecv_data(_forest->communicator(), n, out_buf.begin(), 
00309                   in_buf.begin(), target.begin());
00310 
00311     typename std::list<int>::iterator 
00312     the_rank = target.begin(),
00313     end_rank = target.end();
00314     typename std::list<BinaryBuffer<> >::iterator 
00315     the_buf = in_buf.begin();
00316     for (;the_rank != end_rank;++ the_rank, ++ the_buf) {
00317       AFEPack::istream<> is(*the_buf);
00318       u_int n_item;
00319       is >> n_item;
00320       std::cerr << "received " << n_item
00321                 << " items from " << *the_rank
00322                 << " to " << _forest->rank() << std::endl;
00323       for (u_int i = 0;i < n_item;++ i) {
00324         unsigned long global_idx;
00325         int dimension;
00326         void * remote_obj;
00327         is >> global_idx >> dimension >> remote_obj;
00328         std::pair<int,void *>& the_pair = 
00329           _global_pointer_to_share[*the_rank][global_idx];
00330         assert ((dimension == the_pair.first) && 
00331                 (dimension >= 0) && 
00332                 (dimension <= 3));
00333 
00334         if (dimension == 0) {
00335 #define GDIM 0
00336 #define GEO HGeometry<GDIM,dow>
00337 #define OBJ Shared_object<GEO>
00338           GEO * p_geo = (GEO *)(the_pair.second);
00339           OBJ * p_info = _forest->get_shared_info(*p_geo);
00340           if (p_info == NULL) p_info = _forest->new_shared_info(*p_geo);
00341           p_info->add_clone(*the_rank, (GEO *)remote_obj);
00342 #undef OBJ
00343 #undef GEO
00344 #undef GDIM
00345         } else if (dimension == 1) {
00346 #define GDIM 1
00347 #define GEO HGeometry<GDIM,dow>
00348 #define OBJ Shared_object<GEO>
00349           GEO * p_geo = (GEO *)(the_pair.second);
00350           OBJ * p_info = _forest->get_shared_info(*p_geo);
00351           if (p_info == NULL) p_info = _forest->new_shared_info(*p_geo);
00352           p_info->add_clone(*the_rank, (GEO *)remote_obj);
00353 #undef OBJ
00354 #undef GEO
00355 #undef GDIM
00356         } else if (dimension == 2) {
00357 #define GDIM 2
00358 #define GEO HGeometry<GDIM,dow>
00359 #define OBJ Shared_object<GEO>
00360           GEO * p_geo = (GEO *)(the_pair.second);
00361           OBJ * p_info = _forest->get_shared_info(*p_geo);
00362           if (p_info == NULL) p_info = _forest->new_shared_info(*p_geo);
00363           p_info->add_clone(*the_rank, (GEO *)remote_obj);
00364 #undef OBJ
00365 #undef GEO
00366 #undef GDIM
00367         } else if (dimension == 3) {
00368 #define GDIM 3
00369 #define GEO HGeometry<GDIM,dow>
00370 #define OBJ Shared_object<GEO>
00371           GEO * p_geo = (GEO *)(the_pair.second);
00372           OBJ * p_info = _forest->get_shared_info(*p_geo);
00373           if (p_info == NULL) p_info = _forest->new_shared_info(*p_geo);
00374           p_info->add_clone(*the_rank, (GEO *)remote_obj);
00375 #undef OBJ
00376 #undef GEO
00377 #undef GDIM
00378         }
00379       }
00380     }
00381 
00382 #if 1 
00383 
00386     the_pair = _global_pointer_to_share.begin();
00387     for (;the_pair != end_pair;++ the_pair) {
00388       typename tuple_map_t::iterator
00389         the_tuple = the_pair->second.begin(),
00390         end_tuple = the_pair->second.end();
00391       for (;the_tuple != end_tuple;++ the_tuple) {
00392         void *& p_obj = the_tuple->second.second;
00393         if (dimension == 0) {
00394 #define GDIM 0
00395 #define GEO HGeometry<GDIM,dow>
00396           GEO * p_geo = (GEO *)p_obj;
00397           assert (_forest->get_shared_info(*p_geo) != NULL);
00398 #undef GEO
00399 #undef GDIM
00400         } else if (dimension == 1) {
00401 #define GDIM 1
00402 #define GEO HGeometry<GDIM,dow>
00403           GEO * p_geo = (GEO *)p_obj;
00404           assert (_forest->get_shared_info(*p_geo) != NULL);
00405 #undef GEO
00406 #undef GDIM
00407         } else if (dimension == 2) {
00408 #define GDIM 2
00409 #define GEO HGeometry<GDIM,dow>
00410           GEO * p_geo = (GEO *)p_obj;
00411           assert (_forest->get_shared_info(*p_geo) != NULL);
00412 #undef GEO
00413 #undef GDIM
00414         } else if (dimension == 3) {
00415 #define GDIM 3
00416 #define GEO HGeometry<GDIM,dow>
00417           GEO * p_geo = (GEO *)p_obj;
00418           assert (_forest->get_shared_info(*p_geo) != NULL);
00419 #undef GEO
00420 #undef GDIM
00421         }
00422       }
00423     }
00424 #endif
00425   }
00426 
00428   public:
00434   template <class LOADER>
00435   void config(birdview_t& ir_mesh,
00436               LOADER& loader,
00437               u_int (LOADER::*value)(GeometryBM&)) {
00438 
00439     if (&(ir_mesh.getForest()) != _forest) {
00440       std::cerr << "The mesh should be on the same forest of the HLoadBalance." 
00441                 << std::endl;
00442       abort();
00443     }
00444 
00445     RegularMesh<dim,dow>& mesh = ir_mesh.regularMesh();
00446     new_property_id(_pid_loading); 
00447     u_int n_ele = mesh.n_geometry(dim);
00448     for (u_int i = 0;i < n_ele;++ i) {
00449       HGeometry<dim,dow> * p_geo = mesh.template h_geometry<dim>(i);
00450       u_int * p_loading = p_geo->get_property(_pid_loading);
00451       if (p_loading == NULL) {
00452         p_loading = p_geo->new_property(_pid_loading);
00453       }
00454       (*p_loading) = (loader.*value)(mesh.geometry(dim,i));
00455     }
00456   }
00457 
00458   void config(birdview_t& ir_mesh,
00459               u_int (*value)(GeometryBM&) = &_default_element_loading) {
00460     if (&(ir_mesh.getForest()) != _forest) {
00461       std::cerr << "The mesh should be on the same forest of the HLoadBalance." 
00462                 << std::endl;
00463       abort();
00464     }
00465 
00466     RegularMesh<dim,dow>& mesh = ir_mesh.regularMesh();
00467     new_property_id(_pid_loading); 
00468     u_int n_ele = mesh.n_geometry(dim);
00469     for (u_int i = 0;i < n_ele;++ i) {
00470       const HGeometry<dim,dow> * p_geo = mesh.template h_geometry<dim>(i);
00471       u_int * p_loading = p_geo->get_property(_pid_loading);
00472       if (p_loading == NULL) {
00473         p_loading = p_geo->new_property(_pid_loading);
00474       }
00475       (*p_loading) = (*value)(mesh.geometry(dim,i));
00476     }
00477   }
00478 
00479   static u_int _default_element_loading(GeometryBM&) { return 1; }
00481 
00483   public:
00491   void partition(u_int n_new_rank = 0,
00492                  double tol_percent = 0.05,
00493                  bool is_renumerate_root = false,
00494                  void (*f)(double,double,double,
00495                            double&,double&,double&) = NULL) {
00496     int rank =  _forest->rank();
00497     int n_rank = _forest->n_rank();
00498 
00499     u_int loading = this->lump_loading();
00500     u_int total_loading, partial_loading;
00501     MPI_Comm comm = _forest->communicator();
00502     MPI_Scan(&loading, &partial_loading, 1, MPI_UNSIGNED, MPI_SUM, comm);
00503 
00504     if (rank == n_rank - 1) {
00505       total_loading = partial_loading;
00506     }
00507     if (n_new_rank == 0) n_new_rank = n_rank; 
00508 
00509     MPI_Bcast(&total_loading, 1, MPI_UNSIGNED, n_rank - 1, comm);
00510     u_int mean_loading = total_loading/n_new_rank;
00511 
00515     this->refine_root_element(mean_loading*tol_percent, is_renumerate_root, f);
00516 
00517     _cut_point.clear();
00518     _new_rank.clear();
00519 
00520     u_int idx = 0;
00521     _cut_point.push_back(idx); 
00522 
00523     loading  = partial_loading - loading;
00524     u_int current_rank = loading/mean_loading;
00525     _new_rank.push_back(current_rank);
00526 
00527     typename forest_t::RootIterator
00528     the_ele = _forest->beginRootElement(),
00529     end_ele = _forest->endRootElement();
00530     for (;the_ele != end_ele;++ the_ele) {
00531       idx += 1;
00532       loading += this->get_loading(*the_ele);
00533       u_int the_rank = loading/mean_loading;
00534       the_rank = std::min(the_rank, n_new_rank - 1); 
00535       if (the_rank > current_rank) {
00536         _cut_point.push_back(idx);
00537         _new_rank.push_back(++ current_rank);
00538       }
00539     }
00540     if (_cut_point.back() != idx) {
00541       _cut_point.push_back(idx);
00542     } else {
00543       _new_rank.pop_back();
00544     }
00545 
00546     free_property_id(_pid_loading); 
00547   }
00548 
00549   private:
00556   u_int lump_loading() {
00557     u_int loading = 0;
00558     typename forest_t::RootIterator
00559     the_ele = _forest->beginRootElement(),
00560     end_ele = _forest->endRootElement();
00561     for (;the_ele != end_ele;++ the_ele) {
00562       loading += this->get_loading(*the_ele);
00563     }
00564 
00566     MPI_Comm comm = _forest->communicator();
00567     sync_data(comm, _forest->template get_shared_list<dim>(), 
00568               *this, &this_t::pack_loading, &this_t::unpack_loading);
00569     return loading;
00570   }
00571 
00572   public:
00574   void pack_loading(HGeometry<dim,dow> * geo,
00575                     int remote_rank,
00576                     AFEPack::ostream<>& os) {
00577     u_int * p_loading = geo->get_property(_pid_loading);
00578     if (p_loading != NULL) {
00579       os << *p_loading;
00580     } else {
00581       u_int loading = 0;
00582       os << loading;
00583     }
00584   }
00586   void unpack_loading(HGeometry<dim,dow> * geo,
00587                       int remote_rank,
00588                       AFEPack::istream<>& is) {
00589     assert ((_forest->get_shared_info(*geo) != NULL));
00590     u_int remote_loading;
00591     is >> remote_loading;
00592     u_int * p_loading = geo->get_property(_pid_loading);
00593     if (p_loading != NULL) {
00594       (*p_loading) += remote_loading;
00595     }
00596   }
00597 
00598   private:
00599 
00604   template <class GEO> u_int
00605   get_loading(const GEO& geo) const {
00606     if (&geo == NULL) return 0; 
00607     u_int * p_loading = geo.get_property(_pid_loading);
00608     if (p_loading == NULL) {
00609       p_loading = geo.new_property(_pid_loading);
00610       (*p_loading) = 0;
00611       for (u_int i = 0;i < geo.n_child;++ i) {
00612         (*p_loading) += get_loading(*geo.child[i]);
00613       }
00614     }
00615     return (*p_loading);
00616   }
00618 
00620 
00630   void refine_root_element(double tol, bool is_renum_root, 
00631                            void (*f)(double,double,double,
00632                                      double&,double&,double&)) {
00633     _nre.clear();
00634 
00635     typename forest_t::RootIterator
00636     the_ele = _forest->beginRootElement(),
00637     end_ele = _forest->endRootElement();
00638     for (;the_ele != end_ele;++ the_ele) {
00639       this->refine_root_element(tol, *the_ele, _nre);
00640     }
00641     _forest->rootElement().swap(_nre);
00642     if (is_renum_root) {
00643       _forest->renumerateRootElement(f);
00644     }
00645   }
00646 
00647   void refine_root_element(double tol,
00648                            HGeometry<dim,dow>& geo,
00649                            typename forest_t::container_t& nre) const {
00650     u_int * p_loading = geo.get_property(_pid_loading);
00651     if (*p_loading > tol) {
00652       for (u_int i = 0;i < geo.n_child;++ i) {
00653         this->refine_root_element(tol, *geo.child[i], nre);
00654       }
00655     } else {
00656       nre.push_back(&geo);
00657     }
00658   }
00659             
00664   void coarse_root_element() {
00665     property_id_t<bool> pid_is_found;
00666     new_property_id(pid_is_found);
00667 
00668     _nre.clear();
00669     typename forest_t::RootIterator
00670     the_ele = _forest->beginRootElement(),
00671     end_ele = _forest->endRootElement();
00672     for (;the_ele != end_ele;++ the_ele) {
00673       this->coarse_root_element(pid_is_found, *the_ele, _nre);
00674     }
00675     _forest->rootElement().swap(_nre);
00676   }
00677 
00678   void coarse_root_element(const property_id_t<bool>& pid,
00679                            HGeometry<dim,dow>& geo,
00680                            typename forest_t::container_t& nre) const {
00681     if (geo.get_property(pid) != NULL) return;
00682     if ((geo.parent != NULL) &&
00683         (_forest->get_shared_info(*geo.parent) == NULL)) {
00684       this->coarse_root_element(pid, *geo.parent, nre);
00685     } else {
00686       nre.push_back(&geo);
00687       geo.new_property(pid);
00688     }
00689   }
00691 
00692 
00694   private:
00700   void set_new_rank() {
00701     new_property_id(_pid_rank_map);
00702 
00706     typename forest_t::RootIterator
00707     the_ele = _forest->beginRootElement();
00708     u_int n_part = _new_rank.size();
00709     for (u_int i = 0;i < n_part;++ i) {
00710       for (u_int j = _cut_point[i];j < _cut_point[i + 1];++ j, ++ the_ele) {
00711         geometry_set_new_rank(*the_ele, _new_rank[i]);
00712       }
00713     }
00714     this->set_new_rank_up();
00715 
00716     if (_forest->n_rank() <= 1) return;
00717 
00721     Shared_type_filter::only<0> type_filter;
00722     MPI_Comm comm = _forest->communicator();
00723 #define SYNC_DATA(D) \
00724     if (dim >= D) { \
00725       sync_data(comm, _forest->template get_shared_list<D>(), *this, \
00726                 &this_t::template pack_set_new_rank<D>, \
00727                 &this_t::template unpack_set_new_rank<D>, \
00728                 type_filter); \
00729     }
00730     SYNC_DATA(0);
00731     SYNC_DATA(1);
00732     SYNC_DATA(2);
00733     SYNC_DATA(3);
00734 #undef SYNC_DATA
00735   }
00736 
00737   public:
00738   template <int GDIM> void
00739   pack_set_new_rank(HGeometry<GDIM,dow> * geo,
00740                     int remote_rank,
00741                     AFEPack::ostream<>& os) {
00742     rank_map_t * p_map = get_rank_map(*geo);
00743     if (p_map == NULL) p_map = new_rank_map(*geo);
00744 
00745     os << p_map->size();
00746     typename rank_map_t::iterator
00747     the_pair = p_map->begin(),
00748     end_pair = p_map->end();
00749     for (;the_pair != end_pair;++ the_pair) {
00750       const int& new_rank = the_pair->first;
00751       const int& old_rank = the_pair->second.old_rank;
00752       the_pair->second.is_dummy = _forest->is_dummy(*geo);
00753       const bool& is_dummy = the_pair->second.is_dummy;
00754 
00755       os << new_rank << old_rank << is_dummy;
00756     }
00757   }
00758 
00759   template <int GDIM> void
00760   unpack_set_new_rank(HGeometry<GDIM,dow> * geo,
00761                       int remote_rank,
00762                       AFEPack::istream<>& is) {
00763     assert ((_forest->get_shared_info(*geo) != NULL));
00764 
00773     rank_map_t * p_map = get_rank_map(*geo);
00774     if (p_map == NULL) p_map = new_rank_map(*geo);
00775 
00776     int new_rank;
00777     std::size_t n;
00778     is >> n;
00779     for (u_int i = 0;i < n;++ i) {
00780       rank_map_val remote_rank_map;
00781       is >> new_rank 
00782          >> remote_rank_map.old_rank
00783          >> remote_rank_map.is_dummy;
00784       typename rank_map_t::iterator 
00785         the_pair = p_map->find(new_rank);
00786       if (the_pair == p_map->end()) {
00787         (*p_map)[new_rank] = remote_rank_map;
00788       } else {
00789         if (the_pair->second.is_dummy == remote_rank_map.is_dummy) {
00791           if (the_pair->second.old_rank > remote_rank_map.old_rank) {
00792             the_pair->second.old_rank = remote_rank_map.old_rank;
00793           }
00794         } else if (! remote_rank_map.is_dummy) {
00795           the_pair->second = remote_rank_map;
00796         }
00797       }
00798     }
00799   }
00800 
00801   private:
00806   template <class GEO> void
00807     geometry_set_new_rank(const GEO& geo, int new_rank) const {
00808     rank_map_t * p_map = get_rank_map(geo);
00809     if (p_map == NULL) {
00810       p_map = new_rank_map(geo);
00811     } else if (p_map->find(new_rank) != p_map->end()) {
00812       return; 
00813     }
00814 
00815     (*p_map)[new_rank].old_rank = _forest->rank(); 
00816     
00818     for (u_int i = 0;i < geo.n_vertex;++ i) {
00819       geometry_set_new_rank(*geo.vertex[i], new_rank);
00820     }
00821     for (u_int i = 0;i < geo.n_boundary;++ i) {
00822       geometry_set_new_rank(*geo.boundary[i], new_rank);
00823     }
00824     if (geo.isRefined()) {
00825       for (u_int i = 0;i < geo.n_child;++ i) {
00826         geometry_set_new_rank(*geo.child[i], new_rank);
00827       }
00828     }
00829   }
00830 
00835   template <class GEO> void
00836     geometry_set_new_rank_up(const GEO& geo, int new_rank) const {
00837     rank_map_t * p_map = get_rank_map(geo);
00838     if (p_map == NULL) p_map = new_rank_map(geo);
00839 
00840     (*p_map)[new_rank].old_rank = _forest->rank(); 
00841     if (GEO::dim == 0) return;
00842     
00844     for (u_int i = 0;i < geo.n_vertex;++ i) {
00845       geometry_set_new_rank_up(*geo.vertex[i], new_rank);
00846     }
00847     for (u_int i = 0;i < geo.n_boundary;++ i) {
00848       geometry_set_new_rank_up(*geo.boundary[i], new_rank);
00849     }
00850     GEO* const& p_parent = geo.parent;
00851     if (p_parent != NULL) {
00852       if (! is_on_this_new_rank(*p_parent, new_rank)) {
00853         geometry_set_new_rank_up(*p_parent, new_rank);
00854       }
00855 
00856       for (u_int i = 0;i < p_parent->n_child;++ i) {
00857         GEO* const& p_sib = p_parent->child[i];
00858         if (p_sib == &geo) continue; 
00859         if (this->is_on_this_new_rank(*p_sib, new_rank)) continue;
00860         geometry_set_new_rank_up(*p_sib, new_rank);
00861       }
00862     }
00863   }
00864 
00868   void set_new_rank_up() {
00869     typename forest_t::RootIterator
00870     the_ele = _forest->beginRootElement(),
00871     end_ele = _forest->endRootElement();
00872     for (;the_ele != end_ele;++ the_ele) {
00873       rank_map_t * p_map = get_rank_map(*the_ele);
00874       assert (p_map != NULL);
00875       typename rank_map_t::iterator
00876         the_pair = p_map->begin(),
00877         end_pair = p_map->end();
00878       for (;the_pair != end_pair;++ the_pair) {
00879         geometry_set_new_rank_up(*the_ele, the_pair->first);
00880       }
00881     }
00882   }
00884 
00886   private:
00902   void global_index() {
00906     new_property_id(_pid_global_idx);
00907     unsigned long idx = 0;
00908     typename forest_t::RootIterator
00909     the_ele = _forest->beginRootElement(),
00910     end_ele = _forest->endRootElement();
00911     for (;the_ele != end_ele;++ the_ele) {
00912       HGeometry<dim,dow> * p_geo = &*the_ele;
00913       do {
00914         if (p_geo->parent != NULL) {
00915           p_geo = p_geo->parent;
00916         } else break;
00917       } while (true);
00918       geometry_global_index(*p_geo, idx);
00919     }
00920     free_property_id(_pid_global_idx); 
00921 
00925     MPI_Comm comm = _forest->communicator();
00926     unsigned long global_idx = idx;
00927     MPI_Scan(&idx, &global_idx, 1, MPI_UNSIGNED_LONG, MPI_SUM, comm);
00928     idx = global_idx - idx;
00929 
00933     new_property_id(_pid_global_idx);
00934     the_ele = _forest->beginRootElement();
00935     for (;the_ele != end_ele;++ the_ele) {
00936       HGeometry<dim,dow> * p_geo = &*the_ele;
00937       do {
00938         if (p_geo->parent != NULL) {
00939           p_geo = p_geo->parent;
00940         } else break;
00941       } while (true);
00942       geometry_global_index(*p_geo, idx);
00943     }
00944     
00945     if (_forest->n_rank() <= 1) return;
00950     Shared_type_filter::only<0> type_filter;
00951 #define SYNC_DATA(D) \
00952     if (dim >= D) { \
00953       sync_data(comm, _forest->template get_shared_list<D>(), *this, \
00954                 &this_t::template pack_global_index<D>, \
00955                 &this_t::template unpack_global_index<D>, \
00956                 type_filter); \
00957     }
00958     SYNC_DATA(0);
00959     SYNC_DATA(1);
00960     SYNC_DATA(2);
00961     SYNC_DATA(3);
00962 #undef SYNC_DATA
00963   }
00964 
00965   public:
00966   template <int GDIM> void
00967   pack_global_index(HGeometry<GDIM,dow> * geo,
00968                     int remote_rank,
00969                     AFEPack::ostream<>& os) {
00970     unsigned long * p_idx = get_global_idx(*geo);
00971     assert (p_idx != NULL);
00972 
00973     os << *p_idx; 
00974   }
00975 
00981   template <int GDIM> void
00982   unpack_global_index(HGeometry<GDIM,dow> * geo,
00983                       int remote_rank,
00984                       AFEPack::istream<>& is) {
00985     assert ((_forest->get_shared_info(*geo) != NULL));
00986 
00987     unsigned long * p_idx = get_global_idx(*geo);
00988     assert (p_idx != NULL);
00989 
00990     unsigned long remote_idx;
00991     is >> remote_idx;
00992     if (*p_idx > remote_idx) {
00993       *p_idx = remote_idx; 
00994     }
00995   }
00996 
00997   private:
01001   template <class GEO> void
01002   geometry_global_index(GEO& geo, 
01003                         unsigned long& idx) const {
01004     unsigned long * p_idx = get_global_idx(geo);
01005     if (p_idx != NULL) return; 
01006 
01007     rank_map_t * p_map = get_rank_map(geo);
01008     if (_forest->get_shared_info(geo) != NULL || 
01009         (p_map != NULL && p_map->size() > 1)) { 
01010       p_idx = new_global_idx(geo);
01011       *p_idx = idx ++;
01012     }
01013 
01015     for (u_int i = 0;i < geo.n_vertex;++ i) {
01016       geometry_global_index(*geo.vertex[i], idx);
01017     }
01018     for (u_int i = 0;i < geo.n_boundary;++ i) {
01019       geometry_global_index(*geo.boundary[i], idx);
01020     }
01021     if (geo.isRefined()) {
01022       for (u_int i = 0;i < geo.n_child;++ i) {
01023         geometry_global_index(*geo.child[i], idx);
01024       }
01025     }
01026   }
01028 
01030   public:
01031   void write_config_file(const std::string& dirname) {
01032     char filename[1024];
01033     sprintf(filename, "%s/.config", dirname.c_str());
01034     std::ofstream os(filename);
01035     os << "old-rank=" << _forest->n_rank() << std::endl;
01036     os.close();
01037     Migration::save_config(dirname);
01038   }
01039 
01040   private:
01041   void export_birdview(birdview_t& ir_mesh, 
01042                        Migration::data_id_t data_id, 
01043                        u_int idx) {
01044     typename birdview_t::ActiveIterator
01045     the_ele = ir_mesh.beginActiveElement(),
01046     end_ele = ir_mesh.endActiveElement();
01047     for (;the_ele != end_ele;++ the_ele) {
01048       HGeometry<dim,dow> * p_geo = the_ele->h_element;
01049       AFEPack::ostream<> os(p_geo->buffer[data_id]);
01050       os << idx;
01051     }
01052   }
01053 
01054   public:
01055   void save_data(const std::string& dirname, 
01056                  birdview_set_t& bvs) {
01057     set_new_rank();
01058     global_index();
01059 
01060     char command[1024], *filename = command;
01061 
01062     Migration::data_id_t id = Migration::name_to_id("__internal_birdviewflag__"); 
01063     if (! Migration::is_valid(id)) {
01064       id = Migration::register_data_name("__internal_birdviewflag__");
01065     }
01066     typename birdview_set_t::iterator
01067     the_bv = bvs.begin(), end_bv = bvs.end();
01068     for (u_int idx = 0;the_bv != end_bv;++ the_bv) {
01069       export_birdview(*the_bv, id, idx ++);
01070     }
01071 
01072     typedef boost::archive::HGeometry_oarchive<this_t> archive_t;
01073     typename forest_t::RootIterator
01074     the_ele = _forest->beginRootElement();
01075     u_int n_part = _new_rank.size();
01076     for (u_int i = 0;i < n_part;++ i) {
01077       sprintf(command, "mkdir -p %s && mkdir -p %s/%d", 
01078               dirname.c_str(), dirname.c_str(), _new_rank[i]);
01079       system(command);
01080       sprintf(filename, "%s/%d/%d.dat", dirname.c_str(), 
01081               _new_rank[i], _forest->rank());
01082       std::ofstream os(filename, std::ios::binary);
01083 
01084       {
01085         archive_t oa(*this, _new_rank[i], os);
01086 
01087         u_int n_ele = _cut_point[i + 1] - _cut_point[i];
01088         oa & boost::serialization::make_binary_object(&n_ele, sizeof(u_int));
01089         std::cerr << "saving data in " << filename 
01090                   << ", # macro element = " << n_ele << std::endl;
01091 
01092         for (u_int j = _cut_point[i];j < _cut_point[i + 1];++ j) {
01093           HGeometry<dim,dow> * p_ele = *(the_ele ++);
01094           oa & p_ele;
01095         }
01096       }
01097 
01098       os.close();
01099     }
01100 
01101     if (_forest->rank() == 0) write_config_file(dirname);
01102     _forest->rootElement().swap(_nre); 
01103     _nre.clear();
01104     MPI_Barrier(_forest->communicator()); 
01105   }
01107 
01109   public:
01110   int load_config_file(const std::string& dirname) {
01111     namespace po = boost::program_options;
01112     char filename[1024];
01113     sprintf(filename, "%s/.config", dirname.c_str());
01114     Migration::load_config(dirname);
01115 
01116     po::options_description desc("Hidden options");
01117     desc.add_options()("old-rank", po::value<int>(), "old number of rank");
01118     po::variables_map vm;
01119     std::ifstream is(filename);
01120     po::store(po::parse_config_file(is, desc), vm);
01121     po::notify(vm);
01122     return vm["old-rank"].as<int>();
01123   }
01124 
01125   private:
01126   void reconstruct_birdview(HElement<dim,dow>& ele,
01127                             Migration::data_id_t data_id,
01128                             u_int idx) {
01129     HGeometry<dim,dow> * p_geo = ele.h_element;
01130     typename Migration::buffer_t::iterator it = p_geo->buffer.find(data_id);
01131     bool is_active = true;
01132     ele.value = 0;
01133     if (it == p_geo->buffer.end()) {
01134       is_active = false;
01135     } else {
01136       BinaryBuffer<>& buf = it->second;
01137       int n = buf.size()/sizeof(u_int), i;
01138       u_int idx1;
01139       AFEPack::istream<> is(buf);
01140       for (i = 0;i < n;++ i) {
01141         is >> idx1;
01142         if (idx1 == idx) break;
01143       }
01144       if (i == n) is_active = false;
01145     }
01146     if (! is_active) {
01147       ele.value = 1;
01148       ele.refine();
01149       for (int i = 0;i < ele.n_child;++ i) {
01150         reconstruct_birdview(*ele.child[i], data_id, idx);
01151       }
01152     }
01153   }
01154 
01155   void reconstruct_birdview(birdview_t& ir_mesh,
01156                             Migration::data_id_t data_id,
01157                             u_int idx) {
01158     typename birdview_t::RootIterator
01159     the_ele = ir_mesh.beginRootElement(),
01160     end_ele = ir_mesh.endRootElement();
01161     for (;the_ele != end_ele;++ the_ele) {
01162       reconstruct_birdview(*the_ele, data_id, idx);
01163     }
01164   }
01165 
01171   template <class GEO>
01172     void set_shared_info_sent(GEO& geo) const {
01173     if ((_forest->get_shared_info(geo) != NULL) &
01174         (! _forest->is_shared_info_sent(geo))) {
01175       _forest->set_shared_info_sent(geo);
01176     }
01177 
01178     for (u_int i = 0;i < geo.n_vertex;++ i) {
01179       if (! _forest->is_shared_info_sent(*geo.vertex[i])) {
01180         _forest->set_shared_info_sent(*geo.vertex[i]);
01181       }
01182     }
01183     for (u_int i = 0;i < geo.n_boundary;++ i) {
01184       this->set_shared_info_sent(*geo.boundary[i]);
01185     }
01186     if (geo.isRefined()) {
01187       for (u_int i = 0;i < geo.n_child;++ i) {
01188         this->set_shared_info_sent(*geo.child[i]);
01189       }
01190     }
01191   }
01192 
01196   void set_shared_info_sent() const {
01197     typename forest_t::RootIterator
01198       the_ele = _forest->beginRootElement(),
01199       end_ele = _forest->endRootElement();
01200     for (;the_ele != end_ele;++ the_ele) {
01201       const HGeometry<dim,dow> * p_geo = &(*the_ele);
01202       do {
01203         if (p_geo->parent != NULL) {
01204           p_geo = p_geo->parent;
01205         } else break;
01206       } while (true);
01207       set_shared_info_sent(*p_geo);
01208     }
01209   }
01210 
01215   template <class GEO>
01216     void set_dummy_flag(GEO& geo) const {
01217     if ((_forest->get_shared_info(geo) != NULL) &&
01218         (! _forest->is_dummy(geo))) {
01219       _forest->dummy(geo);
01220     }
01221 
01222     for (u_int i = 0;i < geo.n_boundary;++ i) {
01223       this->set_dummy_flag(*geo.boundary[i]);
01224     }
01225     if (geo.isRefined()) {
01226       for (u_int i = 0;i < geo.n_child;++ i) {
01227         this->set_dummy_flag(*geo.child[i]);
01228       }
01229     }
01230   }
01231 
01235   template <class GEO>
01236     void clear_dummy_flag(GEO& geo) const {
01237     if (_forest->is_dummy(geo)) {
01238       _forest->undummy(geo);
01239     }
01240 
01241     for (u_int i = 0;i < geo.n_boundary;++ i) {
01242       this->clear_dummy_flag(*geo.boundary[i]);
01243     }
01244     if (geo.isRefined()) {
01245       for (u_int i = 0;i < geo.n_child;++ i) {
01246         this->clear_dummy_flag(*geo.child[i]);
01247       }
01248     }
01249   }
01250 
01261   void set_dummy_flag() {
01262     typename forest_t::RootIterator
01263       the_ele = _forest->beginRootElement(),
01264       end_ele = _forest->endRootElement();
01265     for (;the_ele != end_ele;++ the_ele) {
01266       const HGeometry<dim,dow> * p_geo = &(*the_ele);
01267       do {
01268         if (p_geo->parent != NULL) {
01269           p_geo = p_geo->parent;
01270         } else break;
01271       } while (true);
01272       set_dummy_flag(*p_geo);
01273     }
01274 
01275     the_ele = _forest->beginRootElement();
01276     for (;the_ele != end_ele;++ the_ele) {
01277       clear_dummy_flag(*the_ele);
01278     }
01279   }
01280 
01281   public:
01282   void load_data(const std::string& dirname,
01283                  birdview_set_t& bvs) {
01284     clear();
01285 
01286     int n_old_rank = load_config_file(dirname);
01287 
01289     MPI_Barrier(_forest->communicator()); 
01290 
01292     char filename[1024];
01293 
01294     typedef boost::archive::HGeometry_iarchive<this_t> archive_t;
01295 
01296     int rank = 0;
01297     do {
01298       std::ifstream is;
01299       do {
01300         sprintf(filename, "%s/%d/%d.dat", dirname.c_str(), 
01301                 _forest->rank(), rank ++);
01302         if (rank > n_old_rank) {
01303           if (! _global_pointer_to_merge_later.empty()) {
01304             std::cerr << "Rank " << _forest->rank() << ": ";
01305             std::map<unsigned long, std::list<void *> >::iterator
01306               the_entry = _global_pointer_to_merge_later.begin(),
01307               end_entry = _global_pointer_to_merge_later.end();
01308             for (;the_entry != end_entry;++ the_entry) {
01309               std::cerr << "(" << the_entry->first 
01310                         << "->" << the_entry->second.size()
01311                 << ")";
01312             }
01313             std::cerr << std::endl;
01314             assert (false);
01315           }
01316 
01317           this->share_global_pointer();
01318           this->coarse_root_element();
01319           this->set_shared_info_sent();
01320           this->set_dummy_flag();
01321 
01323           Migration::data_id_t id = Migration::name_to_id("__internal_birdviewflag__"); 
01324           typename birdview_set_t::iterator
01325             the_bv = bvs.begin(), end_bv = bvs.end();
01326           for (u_int idx = 0;the_bv != end_bv;++ the_bv) {
01327             the_bv->reinit(*_forest);
01328             reconstruct_birdview(*the_bv, id, idx ++);
01329           }
01330           return;
01331         }
01332         is.open(filename, std::ios::binary); 
01333         if (is.good()) break; 
01334       } while (1);
01335 
01336       {
01337         u_int n_ele;
01338         std::cerr << "loading data from " << filename;
01339         archive_t ia(*this, _forest->rank(), is); 
01340         ia & boost::serialization::make_binary_object(&n_ele, sizeof(u_int));
01341         std::cerr << ", # macro element = " << n_ele << std::endl;
01342 
01343         for (u_int i = 0;i < n_ele;++ i) {
01344           HGeometry<dim,dow> * p_ele;
01345           ia & p_ele;
01346           _forest->rootElement().push_back(p_ele);
01347         }
01348       }
01349 
01350       is.close();
01351     } while (1);
01352 
01353   }
01354 
01355   };
01356 
01357   template <class FOREST>
01358     void load_forest(const std::string& dirname,
01359                      FOREST& forest) {
01360     HLoadBalance<FOREST> hlb(forest);
01361     BirdViewSet<FOREST> bvs;
01362     hlb.load_data(dirname, bvs);
01363   }
01364 
01365   template <class FOREST>
01366     void load_mesh(const std::string& dirname,
01367                    FOREST& forest,
01368                    BirdView<FOREST>& mesh) {
01369     HLoadBalance<FOREST> hlb(forest);
01370     BirdViewSet<FOREST> bvs;
01371     bvs.add(mesh);
01372     hlb.load_data(dirname, bvs);
01373   }
01374 
01375   template <class FOREST>
01376     void load_mesh(const std::string& dirname,
01377                    FOREST& forest,
01378                    u_int n_mesh, ...) {
01379     HLoadBalance<FOREST> hlb(forest);
01380     typedef BirdView<FOREST> * mesh_ptr_t;
01381 
01382     BirdViewSet<FOREST> bvs;
01383     va_list ap;
01384     va_start(ap, n_mesh);
01385     for (u_int i = 0;i < n_mesh;++ i) {
01386       mesh_ptr_t p_mesh = va_arg(ap, mesh_ptr_t);
01387       bvs.add(*p_mesh);
01388     }
01389     va_end(ap);
01390 
01391     hlb.load_data(dirname, bvs);
01392   }
01393 
01394   template <class FOREST>
01395     void load_mesh_set(const std::string& dirname,
01396                        FOREST& forest,
01397                        BirdViewSet<FOREST>& bvs) {
01398     HLoadBalance<FOREST> hlb(forest);
01399     hlb.load_data(dirname, bvs);
01400   }
01401 
01409   void lb_collect_local_data_dir(MPI_Comm comm,
01410                                  const std::string& src_dir,
01411                                  const std::string& dst_dir);
01417   void lb_sync_local_data_dir(MPI_Comm comm,
01418                               const std::string& src_dir,
01419                               const std::string& dst_dir);
01420 }
01421 
01422 #endif // __MPI_ULoadBalance_h__
01423