void SCL::adapt_mesh() { get_indicator(); /// 计算自适应指示子 double convergence_order = 1.0; double adapt_tolerence = 5.0e-04; double ADAPT_RATIO = 0.03; double rtol = (1.33333*pow(2.0, DIM + 1.0))*adapt_tolerence; double ctol = adapt_tolerence/(1.33333*pow(2.0, DIM + 1.0)); size_t n_ele, n_ele_to_refine, n_ele_to_coarse; n_ele = fem_space->n_element(); n_ele_to_refine = std::count_if(indicator.begin(), indicator.end(), std::bind2nd(std::greater<double>(), rtol)); n_ele_to_coarse = std::count_if(indicator.begin(), indicator.end(), std::bind2nd(std::less<double>(), ctol)); /// 如果需要加密的网格数太少,则不做自适应 int is_rank_adapt = (n_ele_to_refine + n_ele_to_coarse < ADAPT_RATIO*n_ele)?0:1; int is_adapt; /// 是否做自适应需要在所有进程间进行同步 MPI_Allreduce(&is_rank_adapt, &is_adapt, 1, MPI_INT, MPI_SUM, htree.communicator()); if (is_adapt == 0) return; ir_mesh_t * old_ir_mesh = ir_mesh; fe_space_t * old_fem_space = fem_space; fe_func_t * old_u_h = u_h; ir_mesh = new ir_mesh_t(*old_ir_mesh); MeshAdaptor<DIM> mesh_adaptor(*ir_mesh); mesh_adaptor.convergenceOrder() = convergence_order; mesh_adaptor.refineStep() = 1; mesh_adaptor.setIndicator(indicator); mesh_adaptor.tolerence() = adapt_tolerence; mesh_adaptor.adapt(); /**< 正则化自适应后的网格 */ ir_mesh->semiregularize(); ir_mesh->regularize(false); /**< 建立新的有限元空间和将解更新到新的空间 */ build_fe_space(); u_h = new fe_func_t(*fem_space); Operator::L2Project(*old_u_h, *u_h, Operator::LOCAL_LEAST_SQUARE, 3); /**< 释放旧的网格、有限元空间以及解的内存 */ delete old_u_h; delete old_fem_space; delete old_ir_mesh; update_edge_cache(*u_h); /// 更新边界缓冲 }
/** * 強度を計算する再帰関数 * @param ARRARY *first 最初の単語が格納された要素 * @param TREE *conb 2つの単語の要素 * @param int threshold 計算に用いる出現頻度の最小値 * @param double *get_indicator(ARRAY *, ARRAY *, TREE *) 強度を返す関数 */ void calc_indicator_in_tree(ARRAY *first, TREE *conb, int threshold, double (*get_indicator)(ARRAY *, ARRAY *, TREE *)) { double indicator; // 要素が登録されていない if (conb->left == conb || conb->right == conb) return ; if (conb->left != NULL) // 右へ calc_indicator_in_tree(first, conb->left, threshold, get_indicator); if (conb->right != NULL) // 右へ calc_indicator_in_tree(first, conb->right, threshold, get_indicator); // 閾値よりも低い時は計算しない if (words[conb->id]->freq >= threshold) { // 強度の計算 indicator = get_indicator(first, words[conb->id], conb); insert_result(first->word, words[conb->id]->word, indicator); // 登録 } }