|
AFEPack
|
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
1.7.4