//// adapt /////////////////////////////////////////////////////////////////////////////////////////
bool HcurlOrthoHP::adapt(double thr, int strat, int adapt_type, bool iso_only, int regularize, int max_order)
{
  if (!have_errors)
    error("Element errors have to be calculated first, see calc_error().");

  int i, j;
  Mesh* mesh[10];
  for (j = 0; j < num; j++) {
    mesh[j] = spaces[j]->get_mesh();
    rsln[j]->set_quad_2d(&g_quad_2d_std);
    rsln[j]->enable_transform(false);
  }

  bool h_only = adapt_type == 1 ? true : false;
  double err0 = 1000.0;
  double processed_error = 0.0;
  int successfully_refined = 0;
  for (i = 0; i < nact; i++)
  {
    int comp = esort[i][1];
    int id = esort[i][0];
    double err = errors[comp][id];

    // first refinement strategy:
    // refine elements until prescribed amount of error is processed
    // if more elements have similar error refine all to keep the mesh symmetric
    if ((strat == 0) && (processed_error > sqrt(thr) * total_err) && fabs((err - err0)/err0) > 1e-2) break;

    // second refinement strategy:
    // refine all elements whose error is bigger than some portion of maximal error
    if ((strat == 1) && (err < thr * errors[esort[0][1]][esort[0][0]])) break;

    Element* e;
    e = mesh[comp]->get_element(id);
    int split = 0;
    int p[4];
    int current = spaces[comp]->get_element_order(id);


    // p-adaptivity
    if (adapt_type == 2)
    {
      split = -1;
      p[0] = std::min(9, get_h_order(current) + 1);
      if (get_h_order(current) < p[0]) successfully_refined++;
    }
    // h-adaptivity
    else if ((adapt_type == 1 && iso_only) || (adapt_type == 1 && e->is_triangle()))
    {
      p[0] = p[1] = p[2] = p[3] = current;
    }
    // hp-adaptivity
    else
    {
      get_optimal_refinement(e, current, rsln[comp], split, p, h_only, iso_only, max_order);
      successfully_refined++;
    }

    if (split < 0)
      spaces[comp]->set_element_order(id, p[0]);
    else if (split == 0) {
      mesh[comp]->refine_element(id);
      for (j = 0; j < 4; j++)
        spaces[comp]->set_element_order(e->sons[j]->id, p[j]);
    }
    else {
      mesh[comp]->refine_element(id, split);
      for (j = 0; j < 2; j++)
        spaces[comp]->set_element_order(e->sons[ (split == 1) ? j : j+2 ]->id, p[j]);
    }

    err0 = err;
    processed_error += err;
  }

  bool done = false;
  if (successfully_refined == 0)
  {
    warn("\nNone of the elements selected for refinement could be refined.\nAdaptivity step not successful, returning 'true'.");
    done = true;
  }

  // mesh regularization
  if (regularize >= 0)
  {
    if (regularize == 0)
    {
      regularize = 1;
      warn("Total mesh regularization is not supported in adaptivity. 1-irregular mesh is used instead.");
    }
    for (i = 0; i < num; i++)
    {
      int* parents;
      parents = mesh[i]->regularize(regularize);
      spaces[i]->distribute_orders(mesh[i], parents);
      delete [] parents;
    }
  }

  for (j = 0; j < num; j++)
    rsln[j]->enable_transform(true);

  verbose("Refined %d elements.", successfully_refined);
  have_errors = false;

  return done;
}
Exemplo n.º 2
0
void L2OrthoHP::adapt(double thr, int strat, bool h_only, bool iso_only, double conv_exp, int max_order)
{

  if (!have_errors)
    error("Element errors have to be calculated first, see calc_error().");


  int i, j;
  Mesh* mesh[10];
  for (j = 0; j < num; j++) {
    mesh[j] = spaces[j]->get_mesh();
    rsln[j]->set_quad_2d(&g_quad_2d_std);
    rsln[j]->enable_transform(false);
  }

  double err0 = 1000.0;
  double processed_error = 0.0;
  for (i = 0; i < nact; i++)
  {
    int comp = esort[i][1];
    int id = esort[i][0];
    double err = errors[comp][id];

    // first refinement strategy:
    // refine elements until prescribed amount of error is processed
    // if more elements have similar error refine all to keep the mesh symmetric
    if ((strat == 0) && (processed_error > sqrt(thr) * total_err) && fabs((err - err0)/err0) > 1e-3) break;

    // second refinement strategy:
    // refine all elements whose error is bigger than some portion of maximal error
    if ((strat == 1) && (err < thr * errors[esort[0][1]][esort[0][0]])) break;

    Element* e;
    e = mesh[comp]->get_element(id);
    int split = 0;
    int p[4];
    int current = spaces[comp]->get_element_order(id);

    //verbose("Refining element #%d, Component #%d, Error %g%%", e_id, comp, errors[comp][e_id]);

    if (h_only && iso_only)
      p[0] = p[1] = p[2] = p[3] = current;
    else
      get_optimal_refinement(e, current, rsln[comp], split, p, h_only, iso_only, conv_exp, max_order);

    //apply found division
    if (split < 0) {
      spaces[comp]->set_element_order_internal(id, p[0]);
    }
    else if (split == 0) {
      mesh[comp]->refine_element_id(id);
      for (j = 0; j < 4; j++)
        spaces[comp]->set_element_order_internal(e->sons[j]->id, p[j]);
    }
    else {
      mesh[comp]->refine_element_id(id, split);
      for (j = 0; j < 2; j++)
        spaces[comp]->set_element_order_internal(e->sons[ (split == 1) ? j : j+2 ]->id, p[j]);
    }

    err0 = err;
    processed_error += err;
  }

  for (j = 0; j < num; j++)
    rsln[j]->enable_transform(true);


  verbose("Refined %d elements.", i);
  have_errors = false;
}