Example #1
0
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); /// 更新边界缓冲
}
Example #2
0
/**
 *  強度を計算する再帰関数
 *  @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);   // 登録
    }
}