AFEPack
MPI_HGeometry.templates.h
浏览该文件的文档。
00001 
00011 #define TEMPLATE template <int DIM, int DOW, class MATCHER>
00012 #define THIS HGeometryForest<DIM,DOW,MATCHER>
00013 
00014 TEMPLATE void 
00015 THIS::readMesh(const std::string& filename) {
00016 
00020   const int& rank = this->_rank;
00021   const int& n_rank = this->_n_rank;
00022 
00031   char filename_buf[256];
00032   if (n_rank > 1) {
00033     sprintf(filename_buf, "%s%d.mesh", filename.c_str(), rank);
00034   } else {
00035     sprintf(filename_buf, "%s.mesh", filename.c_str());
00036   }
00037   std::cerr << "Reading in mesh data file " 
00038             << filename_buf 
00039             << " as geometry tree root ..." 
00040             << std::endl;
00041   std::ifstream is(filename_buf);
00042 
00044   u_int n_point;
00045   is >> n_point;
00046   std::cerr << "\t# points: " << n_point << std::endl;
00047   std::vector<Point<this_t::dow> > point(n_point);
00048   for (u_int i = 0;i < n_point;i ++) is >> point[i];
00049   is >> n_point;
00050   std::vector<HGeometry<0,this_t::dow> *> geo_0d(n_point, (HGeometry<0,this_t::dow> *)NULL);
00051   for (u_int i = 0;i < n_point;i ++) {
00052     u_int j, k;
00053     is >> j; geo_0d[j] = new HGeometry<0,this_t::dow>();
00054     is >> k >> k; *dynamic_cast<Point<this_t::dow> *>(geo_0d[j]) = point[k];
00055     is >> k >> k >> geo_0d[j]->bmark;
00056   }
00057   point.clear();
00058         
00059 #define GDIM 1
00060   u_int n_geo_1d;
00061   std::vector<HGeometry<GDIM,this_t::dow>*> geo_1d;
00062   if (DIM >= 1) {
00063     is >> n_geo_1d;
00064     std::cerr << "\t# 1D-geometry: " << n_geo_1d << std::endl;
00065     geo_1d.resize(n_geo_1d, NULL);
00066     for (u_int i = 0;i < n_geo_1d;i ++) {
00067       u_int j, k, l;
00068       is >> j >> k; geo_1d[j] = new HGeometry<GDIM,this_t::dow>();
00069       for (k = 0;k < GDIM + 1;k ++) {
00070         is >> l; geo_1d[j]->vertex[k] = geo_0d[l];
00071       }
00072       is >> k;
00073       for (k = 0;k < GDIM + 1;k ++) {
00074         is >> l;
00075       }
00076       is >> geo_1d[j]->bmark;
00077     }
00078   }
00079 #undef GDIM
00080 
00081 #define GDIM 2
00082   u_int n_geo_2d;
00083   std::vector<HGeometry<GDIM,this_t::dow>*> geo_2d;
00084   if (DIM >= 2) {
00085     is >> n_geo_2d;
00086     std::cerr << "\t# 2D-geometry: " << n_geo_2d << std::endl;
00087     geo_2d.resize(n_geo_2d, NULL);
00088     for (u_int i = 0;i < n_geo_2d;i ++) {
00089       u_int j, k, l;
00090       is >> j >> k; geo_2d[j] = new HGeometry<GDIM,this_t::dow>();
00091       for (k = 0;k < GDIM + 1;k ++) {
00092         is >> l; geo_2d[j]->vertex[k] = geo_0d[l];
00093       }
00094       is >> k;
00095       for (k = 0;k < GDIM + 1;k ++) {
00096         is >> l; geo_2d[j]->boundary[k] = geo_1d[l];
00097       }
00098       is >> geo_2d[j]->bmark;
00099     }
00100   }
00101 #undef GDIM
00102 
00103 #define GDIM 3
00104   u_int n_geo_3d;
00105   std::vector<HGeometry<GDIM,this_t::dow>*> geo_3d;
00106   if (DIM >= 3) { 
00107     is >> n_geo_3d;
00108     std::cerr << "\t# 3D-geometry: " << n_geo_3d << std::endl;
00109     geo_3d.resize(n_geo_3d, NULL);
00110     for (u_int i = 0;i < n_geo_3d;i ++) {
00111       u_int j, k, l;
00112       is >> j >> k; geo_3d[j] = new HGeometry<GDIM,this_t::dow>();
00113       for (k = 0;k < GDIM + 1;k ++) {
00114         is >> l; geo_3d[j]->vertex[k] = geo_0d[l];
00115       }
00116       is >> k;
00117       for (k = 0;k < GDIM + 1;k ++) {
00118         is >> l; geo_3d[j]->boundary[k] = geo_2d[l];
00119       }
00120       is >> geo_3d[j]->bmark;
00121     }
00122 #undef GDIM
00123   }
00124   is.close();
00125 
00126   if (DIM == 1) {
00127     for (u_int i = 0;i < n_geo_1d;++ i) {
00128       this->rootElement().push_back((HGeometry<DIM,this_t::dow> *)geo_1d[i]);
00129     }
00130   } else if (DIM == 2) {
00131     for (u_int i = 0;i < n_geo_2d;++ i) {
00132       this->rootElement().push_back((HGeometry<DIM,this_t::dow> *)geo_2d[i]);
00133     }
00134   } else if (DIM == 3) {
00135     for (u_int i = 0;i < n_geo_3d;++ i) {
00136       this->rootElement().push_back((HGeometry<DIM,this_t::dow> *)geo_3d[i]);
00137     }
00138   }
00139 
00145   if (n_rank == 1) return; 
00146 
00147   sprintf(filename_buf, "%s%d.share", filename.c_str(), rank);
00148   is.open(filename_buf); 
00149   std::cerr << "Reading in shared data file " 
00150             << filename_buf
00151             << " as shared information ..." 
00152             << std::endl;
00153 
00155   std::vector<bool> proc_flag(n_rank, false);
00156   std::vector<BinaryBuffer<> > proc_buf_in(n_rank), proc_buf_out(n_rank);
00157   std::vector<AFEPack::ostream<> > proc_os(n_rank);
00158   for (u_int i = 0;i < n_rank;++ i) {
00159     proc_os[i].set_buffer(proc_buf_out[i]);
00160   }
00161 
00163   int n_item;
00164   std::vector<std::pair<std::vector<std::pair<int,int> >, int> > 
00165     shared_geo_0d, shared_geo_1d, shared_geo_2d, shared_geo_3d;        
00166   if (DIM >= 0) {
00167     std::vector<int> n_rank_shared_0d(n_rank, 0);
00168     int n_shared_geo_0d;
00169     is >> n_shared_geo_0d >> n_shared_geo_0d;
00170     std::cerr << "\t# 0d-shared geometry: " << n_shared_geo_0d << std::endl;
00171     shared_geo_0d.resize(n_shared_geo_0d);
00172     for (int i = 0;i < n_shared_geo_0d;++ i) {
00173       is >> n_item; 
00174       shared_geo_0d[i].first.resize(n_item);
00175       for (int j = 0;j < n_item;++ j) {
00176         is >> shared_geo_0d[i].first[j].first   
00177            >> shared_geo_0d[i].first[j].second; 
00178         n_rank_shared_0d[shared_geo_0d[i].first[j].first] += 1;
00179       }
00180       is >> shared_geo_0d[i].second; 
00181     }
00182 
00183     for (int i = 0;i < n_rank;++ i) {
00184       proc_os[i] << n_rank_shared_0d[i];
00185       if (n_rank_shared_0d[i] > 0) {
00186         proc_flag[i] = true;
00187       }
00188     }
00189     for (int i = 0;i < n_shared_geo_0d;++ i) {
00190       n_item = shared_geo_0d[i].first.size();
00191       int local_idx;
00192       for (int j = 0;j < n_item;++ j) {
00193         int rnk = shared_geo_0d[i].first[j].first;
00194         int idx = shared_geo_0d[i].first[j].second;
00195         if (rnk == rank) {
00196           local_idx = idx;
00197           break;
00198         }
00199       }
00200       for (int j = 0;j < n_item;++ j) {
00201         int rnk = shared_geo_0d[i].first[j].first;
00202         int idx = shared_geo_0d[i].first[j].second;
00203         if (rnk != rank) {
00204           proc_os[rnk] << idx << geo_0d[local_idx];
00205         }
00206       }
00207     }
00208   }
00209 
00210   if (DIM >= 1) {
00211     std::vector<int> n_rank_shared_1d(n_rank, 0);
00212     int n_shared_geo_1d;
00213     is >> n_shared_geo_1d >> n_shared_geo_1d;
00214     std::cerr << "\t# 1d-shared geometry: " << n_shared_geo_1d << std::endl;
00215     shared_geo_1d.resize(n_shared_geo_1d);        
00216     for (int i = 0;i < n_shared_geo_1d;++ i) {
00217       is >> n_item; 
00218       shared_geo_1d[i].first.resize(n_item);
00219       for (int j = 0;j < n_item;++ j) {
00220         is >> shared_geo_1d[i].first[j].first   
00221            >> shared_geo_1d[i].first[j].second; 
00222         n_rank_shared_1d[shared_geo_1d[i].first[j].first] += 1;
00223       }
00224       is >> shared_geo_1d[i].second; 
00225     }
00226 
00227     for (int i = 0;i < n_rank;++ i) {
00228       proc_os[i] << n_rank_shared_1d[i];
00229       if (n_rank_shared_1d[i] > 0) {
00230         proc_flag[i] = true;
00231       }
00232     }
00233     for (int i = 0;i < n_shared_geo_1d;++ i) {
00234       n_item = shared_geo_1d[i].first.size();
00235       int local_idx;
00236       for (int j = 0;j < n_item;++ j) {
00237         int rnk = shared_geo_1d[i].first[j].first;
00238         int idx = shared_geo_1d[i].first[j].second;
00239         if (rnk == rank) {
00240           local_idx = idx;
00241           break;
00242         }
00243       }
00244       for (int j = 0;j < n_item;++ j) {
00245         int rnk = shared_geo_1d[i].first[j].first;
00246         int idx = shared_geo_1d[i].first[j].second;
00247         if (rnk != rank) {
00248           proc_os[rnk] << idx << geo_1d[local_idx];
00249         }
00250       }
00251     }
00252   }
00253 
00254   if (DIM >= 2) {
00255     std::vector<int> n_rank_shared_2d(n_rank, 0);
00256     int n_shared_geo_2d;
00257     is >> n_shared_geo_2d >> n_shared_geo_2d;
00258     std::cerr << "\t# 2d-shared geometry: " << n_shared_geo_2d << std::endl;
00259     shared_geo_2d.resize(n_shared_geo_2d);        
00260     for (int i = 0;i < n_shared_geo_2d;++ i) {
00261       is >> n_item; 
00262       shared_geo_2d[i].first.resize(n_item);
00263       for (int j = 0;j < n_item;++ j) {
00264         is >> shared_geo_2d[i].first[j].first   
00265            >> shared_geo_2d[i].first[j].second; 
00266         n_rank_shared_2d[shared_geo_2d[i].first[j].first] += 1;
00267       }
00268       is >> shared_geo_2d[i].second; 
00269     }
00270 
00271     for (int i = 0;i < n_rank;++ i) {
00272       proc_os[i] << n_rank_shared_2d[i];
00273       if (n_rank_shared_2d[i] > 0) {
00274         proc_flag[i] = true;
00275       }
00276     }
00277     for (int i = 0;i < n_shared_geo_2d;++ i) {
00278       n_item = shared_geo_2d[i].first.size();
00279       int local_idx;
00280       for (int j = 0;j < n_item;++ j) {
00281         int rnk = shared_geo_2d[i].first[j].first;
00282         int idx = shared_geo_2d[i].first[j].second;
00283         if (rnk == rank) {
00284           local_idx = idx;
00285           break;
00286         }
00287       }
00288       for (int j = 0;j < n_item;++ j) {
00289         int rnk = shared_geo_2d[i].first[j].first;
00290         int idx = shared_geo_2d[i].first[j].second;
00291         if (rnk != rank) {
00292           proc_os[rnk] << idx << geo_2d[local_idx];
00293         }
00294       }
00295     }
00296   }
00297 
00298   if (DIM >= 3) {
00299     std::vector<int> n_rank_shared_3d(n_rank, 0);
00300     int n_shared_geo_3d;
00301     is >> n_shared_geo_3d >> n_shared_geo_3d;
00302     std::cerr << "\t# 3d-shared geometry: " << n_shared_geo_3d << std::endl;
00303     shared_geo_3d.resize(n_shared_geo_3d);        
00304     for (int i = 0;i < n_shared_geo_3d;++ i) {
00305       is >> n_item; 
00306       shared_geo_3d[i].first.resize(n_item);
00307       for (int j = 0;j < n_item;++ j) {
00308         is >> shared_geo_3d[i].first[j].first   
00309            >> shared_geo_3d[i].first[j].second; 
00310         n_rank_shared_3d[shared_geo_3d[i].first[j].first] += 1;
00311       }
00312       is >> shared_geo_3d[i].second; 
00313     }
00314 
00315     for (int i = 0;i < n_rank;++ i) {
00316       proc_os[i] << n_rank_shared_3d[i];
00317       if (n_rank_shared_3d[i] > 0) {
00318         proc_flag[i] = true;
00319       }
00320     }
00321     for (int i = 0;i < n_shared_geo_3d;++ i) {
00322       n_item = shared_geo_3d[i].first.size();
00323       int local_idx;
00324       for (int j = 0;j < n_item;++ j) {
00325         int rnk = shared_geo_3d[i].first[j].first;
00326         int idx = shared_geo_3d[i].first[j].second;
00327         if (rnk == rank) {
00328           local_idx = idx;
00329           break;
00330         }
00331       }
00332       for (int j = 0;j < n_item;++ j) {
00333         int rnk = shared_geo_3d[i].first[j].first;
00334         int idx = shared_geo_3d[i].first[j].second;
00335         if (rnk != rank) {
00336           proc_os[rnk] << idx << geo_3d[local_idx];
00337         }
00338       }
00339     }
00340   }
00341 
00345   std::cerr << "\ttransfering data ..." << std::endl;
00346   int tag = get_random_tag(_comm), n_req = 0;
00347   proc_flag[rank] = false; 
00348   MPI_Request request[2*n_rank];
00349   MPI_Status status[2*n_rank];
00350   for (int i = 0;i < n_rank;++ i) {
00351     if (proc_flag[i] == false) continue;
00352     MPI_Isend(proc_buf_out[i].start_address(), proc_buf_out[i].size(), MPI_CHAR,
00353               i, tag, _comm, &request[n_req ++]);
00354   }
00355   for (int i = 0;i < n_rank;++ i) {
00356     MPI_Status mpi_status;
00357     if (proc_flag[i] == false) continue;
00358     MPI_Probe(i, tag, _comm, &mpi_status);
00359     int msg_size;
00360     MPI_Get_count(&mpi_status, MPI_CHAR, &msg_size);
00361     proc_buf_in[i].resize(msg_size);
00362     MPI_Irecv(proc_buf_in[i].start_address(), msg_size, MPI_CHAR,
00363               i, tag, _comm, &request[n_req ++]);
00364   }
00365   MPI_Waitall(n_req, request, status);
00366 
00371   std::cerr << "\tdecoding data received ..." << std::endl;
00372   for (int i = 0;i < n_rank;++ i) { 
00373     if (proc_flag[i] == false) continue;
00374     AFEPack::istream<> proc_is(proc_buf_in[i]);
00375     int n_shared_item, local_idx;
00376 
00377     if (DIM >= 0) { 
00378 #define GDIM 0
00379 #define GEO HGeometry<GDIM,this_t::dow>
00380 #define OBJ Shared_object<GEO>
00381       proc_is >> n_shared_item;
00382       for (int j = 0;j < n_shared_item;++ j) {
00383         GEO * remote_obj, * local_obj;
00384         proc_is >> local_idx >> remote_obj;
00385         local_obj = geo_0d[local_idx];
00386         OBJ * p_info = get_shared_info(*local_obj);
00387         if (p_info == NULL) p_info = new_shared_info(*local_obj);
00388         p_info->add_clone(i, remote_obj);
00389       }
00390 #undef OBJ
00391 #undef GEO
00392 #undef GDIM
00393     }
00394 
00395     if (DIM >= 1) {
00396 #define GDIM 1
00397 #define GEO HGeometry<GDIM,this_t::dow>
00398 #define OBJ Shared_object<GEO>
00399       proc_is >> n_shared_item;
00400       for (int j = 0;j < n_shared_item;++ j) {
00401         GEO * remote_obj, * local_obj;
00402         proc_is >> local_idx >> remote_obj;
00403         local_obj = geo_1d[local_idx];
00404         OBJ * p_info = get_shared_info(*local_obj);
00405         if (p_info == NULL) p_info = new_shared_info(*local_obj);
00406         p_info->add_clone(i, remote_obj);
00407       }
00408 #undef OBJ
00409 #undef GEO
00410 #undef GDIM
00411     }
00412 
00413     if (DIM >= 2) {
00414 #define GDIM 2
00415 #define GEO HGeometry<GDIM,this_t::dow>
00416 #define OBJ Shared_object<GEO>
00417       proc_is >> n_shared_item;
00418       for (int j = 0;j < n_shared_item;++ j) {
00419         GEO * remote_obj, * local_obj;
00420         proc_is >> local_idx >> remote_obj;
00421         local_obj = geo_2d[local_idx];
00422         OBJ * p_info = get_shared_info(*local_obj);
00423         if (p_info == NULL) p_info = new_shared_info(*local_obj);
00424         p_info->add_clone(i, remote_obj);
00425       }
00426 #undef OBJ
00427 #undef GEO
00428 #undef GDIM
00429     }
00430 
00431     if (DIM >= 3) {
00432 #define GDIM 3
00433 #define GEO HGeometry<GDIM,this_t::dow>
00434 #define OBJ Shared_object<GEO>
00435       proc_is >> n_shared_item;
00436       for (int j = 0;j < n_shared_item;++ j) {
00437         GEO * remote_obj, * local_obj;
00438         proc_is >> local_idx >> remote_obj;
00439         local_obj = geo_3d[local_idx];
00440         OBJ * p_info = get_shared_info(*local_obj);
00441         if (p_info == NULL) p_info = new_shared_info(*local_obj);
00442         p_info->add_clone(i, remote_obj);
00443       }
00444 #undef OBJ
00445 #undef GEO
00446 #undef GDIM
00447     }
00448   }
00449 }
00450 
00451 TEMPLATE
00452 void THIS::renumerateRootElement(void (*f)(double, double, double,
00453                                            double&,double&,double&))
00454 {
00455   std::cerr << "Renumerating element of the mesh using Hibert space curve filling ..." 
00456             << std::flush;
00457   int n_ele = this->n_rootElement();
00458   std::vector<HGeometry<DIM,this_t::dow>*> tmp_ele(n_ele);
00459   std::vector<double> x(n_ele, 0.0), y(n_ele, 0.0), z(n_ele, 0.0);
00460   typename std::list<HGeometry<DIM,this_t::dow>*>::iterator
00461     the_ele = this->rootElement().begin();
00462   for (int i = 0;i < n_ele;++ i, ++ the_ele) {
00463     tmp_ele[i] = *the_ele;
00464     HGeometry<DIM,this_t::dow>& ele = **the_ele;
00465     const int& n_vtx = ele.n_vertex;
00466     for (int j = 0;j < n_vtx;++ j) {
00467       Point<this_t::dow>& pnt = *ele.vertex[j];
00468       x[i] += pnt[0]; y[i] += pnt[1];
00469       if (this_t::dow == 3) z[i] += pnt[2];
00470     }
00471     x[i] /= n_vtx; y[i] /= n_vtx;
00472     if (this_t::dow == 3) z[i] /= n_vtx;
00473   }
00474   std::vector<int> new_index(n_ele);
00475   hsfc_renumerate(n_ele, &x[0], &y[0], &z[0], &new_index[0], f);
00476 
00477   the_ele = this->rootElement().begin();
00478   for (int i = 0;i < n_ele;++ i, ++ the_ele) {
00479     *the_ele = tmp_ele[new_index[i]];
00480   }
00481   std::cerr << " OK!" << std::endl;
00482 }
00483 
00484 
00485 TEMPLATE
00486 void THIS::eraseRootElement(u_int level) {
00487   for (u_int i = 0;i < level;++ i) {
00488     this->eraseRootElementOneLevel();
00489   }
00490 }
00491 
00492 TEMPLATE
00493 void THIS::eraseRootElementOneLevel() {
00495   std::list<HGeometry<DIM,this_t::dow>*> new_root;
00496   typename std::list<HGeometry<DIM,this_t::dow>*>::iterator
00497     the_ele = this->rootElement().begin(),
00498     end_ele = this->rootElement().end();
00499   for (;the_ele != end_ele;++ the_ele) {
00500     for (u_int i = 0;i < HGeometry<DIM,this_t::dow>::n_child;++ i) {
00501       HGeometry<DIM,this_t::dow> * p_geo = (*the_ele)->child[i];
00502       if (p_geo == NULL) {
00503         std::cerr << "Macro element is not refined. The root elements are not erased!" 
00504                   << std::endl;
00505         abort();
00506       }
00507       new_root.push_back(p_geo);
00508       this->nullParent(*p_geo);
00509     }
00510   }
00511   new_root.swap(this->rootElement());
00512 
00519   property_id_t<bool> pid;
00520   new_property_id(pid);
00521   end_ele = new_root.end();
00522   the_ele = new_root.begin();
00523   for (;the_ele != end_ele;++ the_ele) {
00524     this->tryDeleteGeometry(*the_ele, pid);
00525   }
00526   free_property_id(pid);
00527   the_ele = new_root.begin();
00528   for (;the_ele != end_ele;++ the_ele) {
00529     this->deleteGeometry(*the_ele);
00530   }
00531 }
00532 
00533 #undef THIS
00534 #undef TEMPLATE
00535 
00537 
00538 #define TEMPLATE template <class FOREST>
00539 #define THIS HGeometryMatcher<FOREST>
00540 
00541 TEMPLATE
00542 bool THIS::match_geometry() {
00543   typedef THIS this_t;
00544 
00545   std::cerr << "Rank " << _forest->rank()
00546             << ": Matching h-geometry among partitions ..." << std::endl;
00547   bool is_operated = false;
00548   do {
00549     _is_operated = false;
00550 
00551     if (this_t::dim >= 3)
00552       sync_data(_forest->_comm, _forest->_shared_list_3d, *this, 
00553                 &this_t::template pack_match_geometry<3>,
00554                 &this_t::template unpack_match_geometry<3>,
00555                 &this_t::template is_pack_match_geometry<3>);
00556     if (this_t::dim >= 2)
00557       sync_data(_forest->_comm, _forest->_shared_list_2d, *this,
00558                 &this_t::template pack_match_geometry<2>,
00559                 &this_t::template unpack_match_geometry<2>,
00560                 &this_t::template is_pack_match_geometry<2>);
00561     if (this_t::dim >= 1)
00562       sync_data(_forest->_comm, _forest->_shared_list_1d, *this,
00563                 &this_t::template pack_match_geometry<1>,
00564                 &this_t::template unpack_match_geometry<1>,
00565                 &this_t::template is_pack_match_geometry<1>);
00566 
00567     int src = _is_operated?1:0, dst = 0; 
00568     MPI_Allreduce(&src, &dst, 1, MPI_INT, MPI_SUM, _forest->_comm);
00569     if (_is_operated = (dst > 0)) {
00570       is_operated = true;
00571     }
00572   } while (_is_operated);
00573   return is_operated;
00574 }
00575 
00576 TEMPLATE
00577 template <int GDIM> bool 
00578 THIS::is_pack_match_geometry(HGeometry<GDIM,dow> * geo) const {
00579   u_int n_unsent_vtx = 0;
00580   u_int n_unsent_bnd = 0;
00581   if (GDIM == 1) { 
00585 
00586     u_int n_vertex = geo->n_vertex;
00587     for (u_int i = 0;i < n_vertex;++ i) {
00588       if (! is_shared_info_sent(*geo->vertex[i])) {
00589         n_unsent_vtx += 1;
00590       }
00591     }
00592   } else { 
00595 
00596     u_int n_boundary = geo->n_boundary;
00597     for (u_int i = 0;i < n_boundary;++ i) {
00598       HGeometry<GDIM-1,dow> * bnd = geo->boundary[i];
00599       if (bnd->parent == NULL && 
00600           ! is_shared_info_sent(*bnd)) {
00601         n_unsent_bnd += 1;
00602       }
00603     }
00604   }
00605 
00606   u_int n_child = 0;
00607   if (geo->isRefined() && 
00608       (! _forest->is_shared_info_sent(*geo->child[0]))) {
00609     n_child = geo->n_child;
00610   }
00611   return ((n_unsent_vtx > 0) ||
00612           (n_unsent_bnd > 0) ||
00613           (n_child > 0));
00614 }
00615 
00616 TEMPLATE
00617 template <int GDIM> void 
00618 THIS::pack_match_geometry(HGeometry<GDIM,dow> * geo,
00619                           int remote_rank,
00620                           AFEPack::ostream<>& os) {
00622   Shared_object<HGeometry<GDIM,dow> > * so = get_shared_info(*geo);
00623   Point<dow> grp; 
00624 
00629   bool is_last_entry = (so->rbegin()->first == remote_rank);
00630 
00631   if (GDIM == 1) { 
00635 
00636     u_int n_vertex = geo->n_vertex;
00637     u_int n_unsent_vtx = 0;
00638     for (u_int i = 0;i < n_vertex;++ i) {
00639       if (! is_shared_info_sent(*geo->vertex[i])) {
00640         n_unsent_vtx += 1;
00641       }
00642     }
00643     if (n_unsent_vtx > 0) { 
00644       this->_is_operated = true;
00645     }
00646 
00647     os << n_unsent_vtx; 
00648     for (u_int i = 0;i < n_vertex;++ i) {
00649       HGeometry<0,dow> * vtx = geo->vertex[i];
00650       if (! is_shared_info_sent(*vtx)) {
00651         os << vtx; 
00652         for (u_int n = 0;n < this_t::dow;++ n) {
00653           os << (*vtx)[n]; 
00654         }
00655         if (is_last_entry) { 
00656           set_shared_info_sent(*vtx); 
00657         }
00658       }
00659     }
00660   } else { 
00663 
00664     u_int n_boundary = geo->n_boundary;
00665     u_int n_unsent_bnd = 0;
00666     for (u_int i = 0;i < n_boundary;++ i) {
00667       HGeometry<GDIM-1,dow> * bnd = geo->boundary[i];
00668       if (bnd->parent == NULL && 
00669           ! is_shared_info_sent(*bnd)) {
00670         n_unsent_bnd += 1;
00671       }
00672     }
00673 
00674     if (n_unsent_bnd > 0) { 
00675       this->_is_operated = true;
00676     }
00677 
00678     os << n_unsent_bnd; 
00679     for (u_int i = 0;i < n_boundary;++ i) {
00680       HGeometry<GDIM-1,dow> * bnd = geo->boundary[i];
00681       if (bnd->parent == NULL && 
00682           ! is_shared_info_sent(*bnd)) {
00683         geometry_reference_point(*bnd, grp);
00684         os << bnd << grp;
00685         if (is_last_entry) { 
00686           set_shared_info_sent(*bnd); 
00687         }
00688       }
00689     }
00690   }
00691 
00695   if (geo->isRefined() && 
00696       (! _forest->is_shared_info_sent(*geo->child[0]))) {
00703     u_int n_child = geo->n_child;
00704     os << n_child; 
00705     for (u_int i = 0;i < n_child;++ i) {
00706       HGeometry<GDIM,dow> * chd = geo->child[i]; 
00707       Shared_object<HGeometry<GDIM,dow> > * p_info = get_shared_info(*chd);
00708       if (p_info == NULL) p_info = new_shared_info(*chd); 
00709       geometry_reference_point(*chd, grp); 
00710       os << chd << grp; 
00711       if (is_last_entry) { 
00712         set_shared_info_sent(*chd); 
00713       } 
00714     }
00715 
00716     this->_is_operated = true; 
00717   } else { 
00718     u_int n_child = 0;
00719     os << n_child;
00720   }
00721 }
00722 
00723 TEMPLATE
00724 template <int GDIM> void 
00725 THIS::unpack_match_geometry(HGeometry<GDIM,dow> * geo,
00726                             int remote_rank,
00727                             AFEPack::istream<>& is) {
00729   double h = distance(*geo->vertex[0], *geo->vertex[1]);
00730 
00731   if (GDIM == 1) { 
00735 
00736     u_int n_unsent_vtx = 0;
00737     is >> n_unsent_vtx;
00738     std::vector<HGeometry<0,dow>*> remote_vtx(n_unsent_vtx);
00739     std::vector<Point<dow> > pnt(n_unsent_vtx);
00740     for (u_int i = 0;i < n_unsent_vtx;++ i) {
00741       is >> remote_vtx[i] >> pnt[i];
00742     }
00743 
00745     u_int n_vertex = geo->n_vertex;
00746     for (u_int i = 0;i < n_unsent_vtx;++ i) {
00747       for (u_int j = 0;j < n_vertex;++ j) {
00748         HGeometry<0,dow> * vtx = geo->vertex[j];
00749         int type = matcher().value(pnt[i], *vtx, 1.0e-4*h);
00750         if (type >= 0) {
00751           Shared_object<HGeometry<0,dow> > * 
00752             p_info = get_shared_info(*vtx);
00753           if (p_info == NULL) p_info = new_shared_info(*vtx);
00754           p_info->add_clone(remote_rank, type, remote_vtx[i]);
00755           break;
00756         }
00757       }
00758     }
00759   } else { 
00763 
00764     u_int n_unsent_bnd = 0;
00765     is >> n_unsent_bnd;
00766     std::vector<HGeometry<GDIM-1,dow>*> remote_bnd(n_unsent_bnd);
00767     std::vector<Point<dow> > remote_grp(n_unsent_bnd);
00768     for (u_int i = 0;i < n_unsent_bnd;++ i) {
00769       is >> remote_bnd[i] >> remote_grp[i];
00770     }
00771 
00773     Point<dow> grp;
00774     u_int n_boundary = geo->n_boundary;
00775     for (u_int i = 0;i < n_unsent_bnd;++ i) {
00776       for (u_int j = 0;j < n_boundary;++ j) {
00777         HGeometry<GDIM-1,dow> * bnd = geo->boundary[j];
00778         if (bnd->parent != NULL) continue;
00779         geometry_reference_point(*bnd, grp);
00780         int type = matcher().value(remote_grp[i], grp, 1.0e-4*h);
00781         if (type >= 0) {
00782           Shared_object<HGeometry<GDIM-1,dow> > *
00783             p_info = get_shared_info(*bnd);
00784           if (p_info == NULL) p_info = new_shared_info(*bnd);
00785           p_info->add_clone(remote_rank, type, remote_bnd[i]);
00786           break;
00787         }
00788       }
00789     }
00790   }
00791       
00792   u_int n_child;
00793   is >> n_child;
00794   if (n_child != 0) { 
00795     assert (n_child == geo->n_child); 
00796         
00798     std::vector<HGeometry<GDIM,dow>*> remote_chd(n_child);
00799     std::vector<Point<dow> > remote_grp(n_child);
00800     for (u_int i = 0;i < n_child;++ i) {
00801       is >> remote_chd[i] >> remote_grp[i];
00802     }
00803 
00805     if (_forest->is_dummy(*geo)) return;
00806 
00808     if (! geo->isRefined()) geo->refine();
00809 
00811     Point<dow> grp;
00812     u_int n_matched_child = 0;
00813     for (u_int i = 0;i < n_child;++ i) {
00814       HGeometry<GDIM,dow> * chd = geo->child[i];
00815       geometry_reference_point(*chd, grp);
00816       for (u_int j = 0;j < n_child;++ j) {
00817         if (remote_chd[j] == NULL) continue; 
00818 
00820         int type = matcher().value(grp, remote_grp[j], 1.0e-4*h);
00821         if (type >= 0) {
00822           Shared_object<HGeometry<GDIM,dow> > * p_info = get_shared_info(*chd); 
00823           if (p_info == NULL) p_info = new_shared_info(*chd);
00824           p_info->add_clone(remote_rank, type, remote_chd[j]);
00825           remote_chd[j] = NULL;
00826           n_matched_child += 1;
00827           break;
00828         }
00829       }
00830     }
00831     assert (n_matched_child == n_child);
00832   }
00833 }
00834 
00835 TEMPLATE
00836 bool THIS::sync_is_used() {
00837   typedef THIS this_t;
00838   std::cerr << "Rank " << _forest->rank()
00839             << ": Sync is_used flag ..." << std::endl;
00840   _is_operated = false;
00841   if (this_t::dim >= 1)
00842     sync_data(_forest->_comm, _forest->_shared_list_1d, *this, 
00843               &this_t::template pack_sync_is_used<1>,
00844               &this_t::template unpack_sync_is_used<1>);
00845   if (this_t::dim >= 2)
00846     sync_data(_forest->_comm, _forest->_shared_list_2d, *this, 
00847               &this_t::template pack_sync_is_used<2>,
00848               &this_t::template unpack_sync_is_used<2>);
00849   if (this_t::dim >= 3)
00850     sync_data(_forest->_comm, _forest->_shared_list_3d, *this, 
00851               &this_t::template pack_sync_is_used<3>,
00852               &this_t::template unpack_sync_is_used<3>);
00853 
00854   int src = _is_operated?1:0, dst = 0; 
00855   MPI_Allreduce(&src, &dst, 1, MPI_INT, MPI_SUM, _forest->_comm);
00856   return (dst > 0);
00857 }
00858 
00859 TEMPLATE
00860 template <int GDIM> void 
00861 THIS::pack_sync_is_used(HGeometry<GDIM,dow> * geo,
00862                         int remote_rank,
00863                         AFEPack::ostream<>& os) {
00864   bool is_used = _tools.isGeometryUsed(*geo);
00865   os << is_used;
00866 }
00867 
00868 TEMPLATE
00869 template <int GDIM> void 
00870 THIS::unpack_sync_is_used(HGeometry<GDIM,dow> * geo,
00871                           int remote_rank,
00872                           AFEPack::istream<>& is) {
00873   bool is_used;
00874   is >> is_used;
00875 
00876   if (is_used) {
00877     if (! _tools.isGeometryUsed(*geo)) {
00878       _tools.setGeometryUsed(*geo);
00879       _is_operated = true;
00880     }
00881   }
00882 }
00883 
00884 #undef THIS
00885 
00887 
00888 #define THIS BirdView<FOREST>
00889 
00890 TEMPLATE void 
00891 THIS::semiregularize() {
00892   forest_t& forest = this->getForest();
00893 
00894   if (! forest.lock()) { // 对几何遗传树进行加锁
00895     std::cerr << "The hierarchy geometry tree is locked, aborting ...";
00896     abort();
00897   }
00898 
00899   if (forest.rank() == 0)
00900     std::cerr << "Semiregularizing the mesh ...  " << std::flush;
00901   const char * timer = "-/|\\";
00902   int n_element_refined = 0;
00903   this->prepareSemiregularize();
00904 
00905   int round = 0;
00906   bool is_operated;
00907   HGeometryMatcher<forest_t> matcher(forest);
00908   do {
00909     bool flag;
00910     do {
00911       flag = false;
00912       this->semiregularizeHelper(flag, n_element_refined);
00913     } while (flag);
00914 
00915     if (forest.rank() == 0)
00916       std::cerr << "\b" << timer[round] << std::flush;
00917     round = (round + 1)%4;
00918 
00919     is_operated = false;
00920     if (1) { // forest.n_rank() > 1) {
00921       is_operated |= matcher.match_geometry();
00922       is_operated |= matcher.sync_is_used();
00923     }
00924   } while (is_operated);
00925 
00926   if (forest.rank() == 0) 
00927     std::cerr << "\bOK!\n"
00928               << "\t" << n_element_refined 
00929               << " elements refined in semiregularization."
00930               << std::endl;
00931 }
00932 
00933 TEMPLATE
00934 void THIS::eraseRootElement(u_int level) {
00935   for (u_int i = 0;i < level;++ i) {
00936     this->eraseRootElementOneLevel();
00937   }
00938 }
00939 
00940 TEMPLATE
00941 void THIS::eraseRootElementOneLevel() {
00943   typedef typename base_t::container_t container_t;
00944   typedef typename base_t::element_t element_t;
00945   container_t new_root;
00946   typename container_t::iterator
00947     the_ele = this->rootElement().begin(),
00948     end_ele = this->rootElement().end();
00949   for (;the_ele != end_ele;++ the_ele) {
00950     for (u_int i = 0;i < element_t::n_child;++ i) {
00951       element_t * p_geo = (*the_ele)->child[i];
00952       if (p_geo == NULL) {
00953         std::cerr << "Macro element is not refined. The root elements CAN'T be erased!" 
00954                   << std::endl;
00955         abort();
00956       }
00957       new_root.push_back(p_geo);
00958       p_geo->parent = NULL;
00959     }
00960   }
00961   new_root.swap(this->rootElement());
00962 
00963   the_ele = new_root.begin();
00964   end_ele = new_root.end();
00965   for (;the_ele != end_ele;++ the_ele) {
00966     delete *the_ele;
00967   }
00968 }
00969 
00970 #undef THIS
00971 #undef TEMPLATE
00972