int main(int argc, char * argv[]) { MPI_Init(&argc, &argv); forest_t forest(MPI_COMM_WORLD); u_int round = 1; if (argc >= 3) { round = atoi(argv[2]); /// 第二个参数是随机加密的轮数 } ir_mesh_t ir_mesh(forest); load_balancer_t hlb(forest); MPI::load_mesh("tmp", forest, ir_mesh); /// 第一个参数是周期描述文件 MPI::Periodic::periodizeForest(forest, argv[1]); for (u_int i = 0;i < round;++ i) { ir_mesh.randomRefine(20.0); /// 加密 5% 的单元 } ir_mesh.semiregularize(); ir_mesh.regularize(false); char filename[256]; int rank; MPI_Comm_rank(MPI_COMM_WORLD, &rank); sprintf(filename, "mesh%d.dx", rank); ir_mesh.regularMesh().writeOpenDXData(filename); MPI_Finalize(); return 0; }
void SCL::load_balance() { /// 首先判断是否需要做负载平衡 RegularMesh<DIM>& mesh = ir_mesh->regularMesh(); int n_ele = mesh.n_geometry(DIM); int n_max_ele; MPI_Allreduce(&n_ele, &n_max_ele, 1, MPI_INT, MPI_MAX, htree.communicator()); int is_rank_load_balance = (0.9*n_max_ele > n_ele)?1:0; /// 单元个数差太多 int is_load_balance; MPI_Allreduce(&is_rank_load_balance, &is_load_balance, 1, MPI_INT, MPI_SUM, htree.communicator()); if (is_load_balance == 0) return; /// 然后对数据进行重新分区存储 MPI::HLoadBalance<SCL::forest_t> hlb(htree); hlb.config(*ir_mesh); /// 使用 ir_mesh 进行负载计算 hlb.partition(htree.n_rank()); /// 重新分区 MPI::BirdViewSet<SCL::forest_t> bvs; bvs.add(*ir_mesh); /// 存储时对 ir_mesh 也进行存储 Migration::clear_data_buffer(htree); /// 清除不用的数据 Migration::data_id_t id = Migration::name_to_id("u_h"); if (Migration::is_valid(id)) { /// 获取数据ID,如果没有则新建一个 id = Migration::register_data_name("u_h"); } Migration::export_fe_func(*u_h, id); /// 将有限元函数放到几何遗传树上 if (htree.rank() == 0) { std::cout << "Rebalance the loading ... " << std::endl; system("rm -rf .hlb.bak; mv .hlb .hlb.bak"); } MPI_Barrier(htree.communicator()); /// 同步以后 hlb.save_data(".hlb", bvs); /// 存储数据 /// 清除内存 delete u_h; /// 有限元函数和有限元空间均会重造 delete fem_space; /// 所以这两个变量都直接删除 ir_mesh->clear(); /// 网格和几何遗传树会重新载入 htree.clear(); /// 因此清除其中的数据空间 /// 最后将数据重新载入 hlb.load_data(".hlb", bvs); /// 载入数据 ir_mesh->semiregularize(); /// 重造正则网格 ir_mesh->regularize(false); build_fe_space(); /// 重建有限元空间 u_h = new fe_func_t(*fem_space); /// 和有限元函数 Migration::import_fe_func(*u_h, id); /// 将有限元函数从几何遗传树上读出 Migration::clear_data_buffer(htree); /// 将几何遗传树上的数据清除 update_edge_cache(*u_h); /// 更新边界上数据缓冲 }
void App::load(const std::string& dir) { if (phi_h != NULL) delete phi_h; phi_h=NULL; if (alpha_h != NULL) delete alpha_h; alpha_h=NULL; if (c_h != NULL) delete c_h; c_h=NULL; if (fem_space != NULL) delete fem_space; fem_space=NULL; if (ir_mesh != NULL) delete ir_mesh; ir_mesh=NULL; if (u_h != NULL) delete u_h; u_h=NULL; if (v_h != NULL) delete v_h; v_h=NULL; if (p_h != NULL) delete p_h; p_h=NULL; if (last_p_h != NULL) delete last_p_h; last_p_h=NULL; htree.clear(); AFEPack::MPI::HLoadBalance<App::forest_t> hlb(htree); AFEPack::MPI::BirdViewSet<App::forest_t> bvs; ir_mesh = new ir_mesh_t(htree); bvs.add(*ir_mesh); if (htree.rank() == 0) { std::cerr << "Loading the data ... " << std::endl; } hlb.load_data(dir, bvs); ir_mesh->semiregularize(); ir_mesh->regularize(false); build_femspace(); std::vector<fe_func_t> *func=new std::vector<fe_func_t> (7,*fem_space); /// Migration::data_id_t id = Migration::name_to_id("func"); if (! Migration::is_valid(id)) { id = Migration::register_data_name("func"); } Migration::import_fe_func(*func, id); Migration::clear_data_buffer(htree); *phi_h = (*func)[0]; *c_h = (*func)[1]; *u_h = (*func)[2]; *v_h = (*func)[3]; *p_h = (*func)[4]; *last_p_h = (*func)[5]; *alpha_h = (*func)[6]; //update_edge_cache(*func); delete func;func=NULL; }
void App::dump(int n_rank, const std::string& dir) //make partition and save data { AFEPack::MPI::HLoadBalance<App::forest_t> hlb(htree); hlb.config(*ir_mesh);//using ir_mesh to do the loading calculation hlb.partition(n_rank); //repartition AFEPack::MPI::BirdViewSet<App::forest_t> bvs; bvs.add(*ir_mesh); //also save ir_mesh std::vector<fe_func_t> *func=new std::vector< fe_func_t> (7,*fem_space); (*func)[0] = *phi_h; (*func)[1] = *c_h; (*func)[2] = *u_h; (*func)[3] = *v_h; (*func)[4] = *p_h; (*func)[5] = *last_p_h; (*func)[6] = *alpha_h; Migration::clear_data_buffer(htree); // clear the useless data Migration::data_id_t id = Migration::name_to_id("func"); if (! Migration::is_valid(id)) { id = Migration::register_data_name("func"); } Migration::export_fe_func(*func, id); //Put the finite element function to the tree if (htree.rank() == 0) { std::cerr << "Dumping the data ... " << std::endl; //char cmd[8192]; //sprintf(cmd, "rm -rf %s", dir.c_str()); //system(cmd); system("rm -rf hlb_backup; mv hlb hlb_backup"); } /* char cmd[8192]; sprintf(cmd, "mv -f %s %s%d", "hlb","hlb",htree.n_rank()); system(cmd); */ MPI_Barrier(htree.communicator()); /* delete_file(dir.c_str()); delete_file(dir.c_str()); MPI_Barrier(htree.communicator()); */ hlb.save_data(dir, bvs);//here save_data is a function of hlb delete func;func=NULL; }
int main(int argc, char * argv[]) { MPI_Init(&argc, &argv); typedef MPI::HGeometryForest<DIM,DOW> forest_t; forest_t forest(MPI_COMM_WORLD); if (argc < 3) { system("head -n 20 ex29.cpp"); MPI_Finalize(); return 1; } u_int global_round = 1; if (argc >= 3) { global_round = atoi(argv[2]); /// 第二个参数是全局加密的轮数 } int n_new_rank = forest.n_rank(); if (argc >= 4) { n_new_rank = atoi(argv[3]); /// 第三个参数是新分区的分区个数 } forest.readMesh(argv[1]); /// 第一个参数是网格文件名 MPI::BirdView<forest_t> ir_mesh(forest); ir_mesh.globalRefine(global_round); ir_mesh.semiregularize(); ir_mesh.regularize(false); /// 移除背景单元 ir_mesh.eraseRootElement(global_round); forest.eraseRootElement(global_round); forest.renumerateRootElement(&map); MPI::HLoadBalance<forest_t> hlb(forest); hlb.config(ir_mesh); hlb.partition(n_new_rank); Migration::initialize(forest.communicator()); MPI::BirdViewSet<forest_t> bvs; bvs.add(ir_mesh); hlb.save_data("tmp", bvs); MPI_Finalize(); return 0; }