Ejemplo n.º 1
0
 OrderPermutator::OrderPermutator(int start_quad_order, int end_quad_order, bool iso_p, int* tgt_quad_order)
   : start_order_h(H2D_GET_H_ORDER(start_quad_order)), start_order_v(H2D_GET_V_ORDER(start_quad_order))
   , end_order_h(H2D_GET_H_ORDER(end_quad_order)), end_order_v(H2D_GET_V_ORDER(end_quad_order))
   , iso_p(iso_p), tgt_quad_order(tgt_quad_order)
 {
   reset();
 }
Ejemplo n.º 2
0
void Space::H2D_CHECK_ORDER(int order)
{
  if (H2D_GET_H_ORDER(order) < 0 || H2D_GET_V_ORDER(order) < 0)
    error("Order cannot be negative.");
  if (H2D_GET_H_ORDER(order) > 10 || H2D_GET_V_ORDER(order) > 10)
    error("Order = %d, maximum is 10.", order);
}
    int DiscreteProblemIntegrationOrderCalculator<Scalar>::calc_order_dg_matrix_form(const Hermes::vector<SpaceSharedPtr<Scalar> >& spaces, Traverse::State* current_state, MatrixFormDG<Scalar>* mfDG, RefMap** current_refmaps, Solution<Scalar>** current_u_ext, bool neighbor_supp_u, bool neighbor_supp_v, NeighborSearch<Scalar>** neighbor_searches)
    {
      NeighborSearch<Scalar>* nbs_u = neighbor_searches[mfDG->j];

      unsigned int prev_size = this->rungeKutta ? this->RK_original_spaces_count : mfDG->wf->get_neq() - mfDG->u_ext_offset;

      // Order to return.
      int order = 0;

      DiscontinuousFunc<Hermes::Ord>** u_ext_ord = current_u_ext == nullptr ? nullptr : new DiscontinuousFunc<Hermes::Ord>*[this->rungeKutta ? this->RK_original_spaces_count : mfDG->wf->get_neq() - mfDG->u_ext_offset];

      if (current_u_ext)
      for (int i = 0; i < prev_size; i++)
      if (current_u_ext[i + mfDG->u_ext_offset])
        u_ext_ord[i] = init_ext_fn_ord(nbs_u, current_u_ext[i + mfDG->u_ext_offset]);
      else
        u_ext_ord[i] = new DiscontinuousFunc<Ord>(init_fn_ord(0), false, false);

      // Order of additional external functions.
      DiscontinuousFunc<Ord>** ext_ord = nullptr;
      Hermes::vector<MeshFunctionSharedPtr<Scalar> > ext_ord_fns = mfDG->ext.size() ? mfDG->ext.size() : mfDG->wf->ext.size();
      if (ext_ord_fns.size() > 0)
        ext_ord = init_ext_fns_ord(ext_ord_fns, neighbor_searches);

      // Order of shape functions.
      int max_order_j = spaces[mfDG->j]->get_element_order(current_state->e[mfDG->j]->id);
      int max_order_i = spaces[mfDG->i]->get_element_order(current_state->e[mfDG->i]->id);
      if (H2D_GET_V_ORDER(max_order_i) > H2D_GET_H_ORDER(max_order_i))
        max_order_i = H2D_GET_V_ORDER(max_order_i);
      else
        max_order_i = H2D_GET_H_ORDER(max_order_i);
      if (H2D_GET_V_ORDER(max_order_j) > H2D_GET_H_ORDER(max_order_j))
        max_order_j = H2D_GET_V_ORDER(max_order_j);
      else
        max_order_j = H2D_GET_H_ORDER(max_order_j);

      // Order of shape functions.
      DiscontinuousFunc<Ord>* ou = new DiscontinuousFunc<Ord>(init_fn_ord(max_order_j), neighbor_supp_u);
      DiscontinuousFunc<Ord>* ov = new DiscontinuousFunc<Ord>(init_fn_ord(max_order_i), neighbor_supp_v);

      // Order of geometric attributes (eg. for multiplication of a solution with coordinates, normals, etc.).
      Geom<Hermes::Ord> tmp;
      double fake_wt = 1.0;

      // Total order of the matrix form.
      Ord o = mfDG->ord(1, &fake_wt, u_ext_ord, ou, ov, &tmp, ext_ord);

      adjust_order_to_refmaps(mfDG, order, &o, current_refmaps);

      // Cleanup.
      deinit_ext_fns_ord(mfDG, u_ext_ord, ext_ord);

      delete ou;
      delete ov;

      return order;
    }
    int DiscreteProblemIntegrationOrderCalculator<Scalar>::calc_order_matrix_form(const Hermes::vector<SpaceSharedPtr<Scalar> >& spaces, MatrixForm<Scalar> *form, RefMap** current_refmaps, Func<Hermes::Ord>** ext, Func<Hermes::Ord>** u_ext)
    {
      int order;

      Func<Hermes::Ord>** local_ext = ext;
      // If the user supplied custom ext functions for this form.
      if (form->ext.size() > 0)
        local_ext = this->init_ext_orders(form->ext, (form->u_ext_fn.size() > 0 ? form->u_ext_fn : form->wf->u_ext_fn), u_ext);

      // Order of shape functions.
      int max_order_j = spaces[form->j]->get_element_order(current_state->e[form->j]->id);
      int max_order_i = spaces[form->i]->get_element_order(current_state->e[form->i]->id);
      if (H2D_GET_V_ORDER(max_order_i) > H2D_GET_H_ORDER(max_order_i))
        max_order_i = H2D_GET_V_ORDER(max_order_i);
      else
        max_order_i = H2D_GET_H_ORDER(max_order_i);
      if (H2D_GET_V_ORDER(max_order_j) > H2D_GET_H_ORDER(max_order_j))
        max_order_j = H2D_GET_V_ORDER(max_order_j);
      else
        max_order_j = H2D_GET_H_ORDER(max_order_j);

      for (unsigned int k = 0; k < current_state->rep->nvert; k++)
      {
        int eo = spaces[form->i]->get_edge_order(current_state->e[form->i], k);
        if (eo > max_order_i)
          max_order_i = eo;
        eo = spaces[form->j]->get_edge_order(current_state->e[form->j], k);
        if (eo > max_order_j)
          max_order_j = eo;
      }

      Func<Hermes::Ord>* ou = init_fn_ord(max_order_j + (spaces[form->j]->get_shapeset()->get_num_components() > 1 ? 1 : 0));
      Func<Hermes::Ord>* ov = init_fn_ord(max_order_i + (spaces[form->i]->get_shapeset()->get_num_components() > 1 ? 1 : 0));

      // Total order of the vector form.
      double fake_wt = 1.0;
      Geom<Hermes::Ord> tmp;
      Hermes::Ord o = form->ord(1, &fake_wt, u_ext, ou, ov, &tmp, local_ext);

      adjust_order_to_refmaps(form, order, &o, current_refmaps);

      // Cleanup.
      if (form->ext.size() > 0)
        this->deinit_ext_orders(form->ext, (form->u_ext_fn.size() > 0 ? form->u_ext_fn : form->wf->u_ext_fn), local_ext);

      delete ou;
      delete ov;

      return order;
    }
Ejemplo n.º 5
0
// using pss and coefficient array
void Solution::set_coeff_vector(Space* space, PrecalcShapeset* pss, scalar* coeffs, bool add_dir_lift)
{
  int o;

  // some sanity checks
  if (space == NULL) error("Space == NULL in Solution::set_coeff_vector().");
  if (space->get_mesh() == NULL) error("Mesh == NULL in Solution::set_coeff_vector().");
  if (pss == NULL) error("PrecalcShapeset == NULL in Solution::set_coeff_vector().");
  if (coeffs == NULL) error("Coefficient vector == NULL in Solution::set_coeff_vector().");
  if (!space->is_up_to_date())
    error("Provided 'space' is not up to date.");
  if (space->get_shapeset() != pss->get_shapeset())
    error("Provided 'space' and 'pss' must have the same shapesets.");
  int ndof = Space::get_num_dofs(space);

  space_type = space->get_type();

  free();

  num_components = pss->get_num_components();
  type = HERMES_SLN;
  num_dofs = Space::get_num_dofs(space);

  // copy the mesh   TODO: share meshes between solutions // WHAT???
  mesh = space->get_mesh();

  // allocate the coefficient arrays
  num_elems = mesh->get_max_element_id();
  if(elem_orders != NULL)
    delete [] elem_orders;
  elem_orders = new int[num_elems];
  memset(elem_orders, 0, sizeof(int) * num_elems);
  for (int l = 0; l < num_components; l++) {
    if(elem_coefs[l] != NULL)
      delete [] elem_coefs[l];
    elem_coefs[l] = new int[num_elems];
    memset(elem_coefs[l], 0, sizeof(int) * num_elems);
  }

  // obtain element orders, allocate mono_coefs
  Element* e;
  num_coefs = 0;
  for_all_active_elements(e, mesh)
  {
    mode = e->get_mode();
    o = space->get_element_order(e->id);
    o = std::max(H2D_GET_H_ORDER(o), H2D_GET_V_ORDER(o));
    for (unsigned int k = 0; k < e->nvert; k++) {
      int eo = space->get_edge_order(e, k);
      if (eo > o) o = eo;
    }

    // Hcurl: actual order of functions is one higher than element order
    if ((space->get_shapeset())->get_num_components() == 2) o++;

    num_coefs += mode ? sqr(o+1) : (o+1)*(o+2)/2;
    elem_orders[e->id] = o;
  }
Ejemplo n.º 6
0
 int L2ShapesetTaylor::get_num_bubbles(int order, ElementMode2D mode) const
 {
   if(mode == HERMES_MODE_QUAD)
   {
     assert(H2D_GET_V_ORDER(order) == H2D_GET_H_ORDER(order));
     return bubble_count[mode][H2D_GET_V_ORDER(order)];
   }
   else
     return Shapeset::get_num_bubbles(order, mode);
 }
Ejemplo n.º 7
0
    void Adapt<Scalar>::homogenize_shared_mesh_orders(Mesh** meshes) 
    {
      Element* e;
      for (int i = 0; i < this->num; i++) 
      {
        for_all_active_elements(e, meshes[i]) 
        {
          int current_quad_order = this->spaces[i]->get_element_order(e->id);
          int current_order_h = H2D_GET_H_ORDER(current_quad_order), current_order_v = H2D_GET_V_ORDER(current_quad_order);

          for (int j = 0; j < this->num; j++)
            if ((j != i) && (meshes[j] == meshes[i])) // components share the mesh
            {
              int quad_order = this->spaces[j]->get_element_order(e->id);
              current_order_h = std::max(current_order_h, H2D_GET_H_ORDER(quad_order));
              current_order_v = std::max(current_order_v, H2D_GET_V_ORDER(quad_order));
            }

            this->spaces[i]->set_element_order_internal(e->id, H2D_MAKE_QUAD_ORDER(current_order_h, current_order_v));
        }
      }
Ejemplo n.º 8
0
double KrivodonovaDiscontinuityDetector::calculate_h(Element* e, int polynomial_order)
{
  double h = std::sqrt(std::pow(e->vn[(0 + 1) % e->get_num_surf()]->x - e->vn[0]->x, 2) + std::pow(e->vn[(0 + 1) % e->get_num_surf()]->y - e->vn[0]->y, 2));
  for(int edge_i = 0; edge_i < e->get_num_surf(); edge_i++) {
    double edge_length = std::sqrt(std::pow(e->vn[(edge_i + 1) % e->get_num_surf()]->x - e->vn[edge_i]->x, 2) + std::pow(e->vn[(edge_i + 1) % e->get_num_surf()]->y - e->vn[edge_i]->y, 2));
    if(edge_length < h)
      h = edge_length;
  }
  return std::pow(h, (0.5 * (H2D_GET_H_ORDER(spaces[0]->get_element_order(e->id)) 
    + 
    H2D_GET_V_ORDER(spaces[0]->get_element_order(e->id)))
    + 1) / 2);
}
Ejemplo n.º 9
0
void Solution::set_fe_solution(Space* space, PrecalcShapeset* pss, scalar* vec, double dir)
{
  int o;

  // some sanity checks
  if (!space->is_up_to_date())
    error("Provided 'space' is not up to date.");
  if (space->get_shapeset() != pss->get_shapeset())
    error("Provided 'space' and 'pss' must have the same shapesets.");

  space_type = space->get_type();

  free();

  num_components = pss->get_num_components();
  type = SLN;
  num_dofs = space->get_num_dofs();

  // copy the mesh   TODO: share meshes between solutions
  mesh = new Mesh;
  mesh->copy(space->get_mesh());
  own_mesh = true;

  // allocate the coefficient arrays
  num_elems = mesh->get_max_element_id();
  elem_orders = new int[num_elems];
  memset(elem_orders, 0, sizeof(int) * num_elems);
  for (int l = 0; l < num_components; l++) {
    elem_coefs[l] = new int[num_elems];
    memset(elem_coefs[l], 0, sizeof(int) * num_elems);
  }

  // obtain element orders, allocate mono_coefs
  Element* e;
  num_coefs = 0;
  for_all_active_elements(e, mesh)
  {
    mode = e->get_mode();
    o = space->get_element_order(e->id);
    o = std::max(H2D_GET_H_ORDER(o), H2D_GET_V_ORDER(o));
    for (unsigned int k = 0; k < e->nvert; k++) {
      int eo = space->get_edge_order(e, k);
      if (eo > o) o = eo;
    } // FIXME: eo tam jeste porad necemu vadi...

    // Hcurl: actual order of functions is one higher than element order
    if ((space->get_shapeset())->get_num_components() == 2) o++;

    num_coefs += mode ? sqr(o+1) : (o+1)*(o+2)/2;
    elem_orders[e->id] = o;
  }
Ejemplo n.º 10
0
void FluxLimiter::limit_according_to_detector(std::set<int>& discontinuous_elements)
{
  // First adjust the solution_vector.
  for(unsigned int space_i = 0; space_i < spaces.size(); space_i++)
    for(std::set<int>::iterator it = discontinuous_elements.begin(); it != discontinuous_elements.end(); it++) {
      AsmList al;
      spaces[space_i]->get_element_assembly_list(spaces[space_i]->get_mesh()->get_element(*it), &al);
      for(unsigned int shape_i = 0; shape_i < al.cnt; shape_i++)
        if(H2D_GET_H_ORDER(spaces[space_i]->get_shapeset()->get_order(al.idx[shape_i])) > 0)
          solution_vector[al.dof[shape_i]] = 0.0;
    }

  // Now adjust the solutions.
  Solution::vector_to_solutions(solution_vector, spaces, solutions);
};
Ejemplo n.º 11
0
std::set<int>& DiscontinuityDetector::get_discontinuous_element_ids(double threshold)
{
  Element* e;
  for_all_active_elements(e, mesh) {
    for(int edge_i = 0; edge_i < e->get_num_surf(); edge_i++)
      if(calculate_relative_flow_direction(e, edge_i) < -1e-3 && !e->en[edge_i]->bnd) {
        double jump = calculate_jumps(e, edge_i);
        double diameter_indicator = std::pow(e->get_diameter(), (H2D_GET_H_ORDER(spaces[0]->get_element_order(e->id)) + 1) / 2);
        double edge_length = std::sqrt(std::pow(e->vn[(edge_i + 1) % 4]->x - e->vn[edge_i]->x, 2) + std::pow(e->vn[(edge_i + 1) % 4]->y - e->vn[edge_i]->y, 2));
        double norm = calculate_norm(e, edge_i);
        double discontinuity_detector = jump / (diameter_indicator * edge_length * norm);
        if(discontinuity_detector > threshold)
          discontinuous_element_ids.insert(e->id);
      }
  }
  return discontinuous_element_ids;
};
Ejemplo n.º 12
0
  Hermes::vector<Cand> create_candidates(Element* e, int quad_order)
  {
    Hermes::vector<Cand> candidates;

    // Get the current order range.
    int current_min_order, current_max_order;
    this->get_current_order_range(e, current_min_order, current_max_order);

    int order_h = H2D_GET_H_ORDER(quad_order), order_v = H2D_GET_V_ORDER(quad_order);

    if(current_max_order < std::max(order_h, order_v))
      current_max_order = std::max(order_h, order_v);

    int last_order_h = std::min(current_max_order, order_h + 1), last_order_v = std::min(current_max_order, order_v + 1);
    int last_order = H2D_MAKE_QUAD_ORDER(last_order_h, last_order_v);

    switch(strategy)
    {
    case(hORpSelectionBasedOnDOFs):
      {
        candidates.push_back(Cand(H2D_REFINEMENT_P, quad_order));
      }
    case(hXORpSelectionBasedOnError):
      {
        candidates.push_back(Cand(H2D_REFINEMENT_P, last_order));
        candidates.push_back(Cand(H2D_REFINEMENT_H, quad_order, quad_order, quad_order, quad_order));
        return candidates;
      }
      break;
    case(isoHPSelectionBasedOnDOFs):
      {
        this->cand_list = H2D_HP_ISO;
        return H1ProjBasedSelector<complex>::create_candidates(e, quad_order);
      }
      break;
    case(anisoHPSelectionBasedOnDOFs):
      {
        this->cand_list = H2D_HP_ANISO;
        return H1ProjBasedSelector<complex>::create_candidates(e, quad_order);
      }
      break;
    }
  }
Ejemplo n.º 13
0
      void Orderizer::load_data(const char* filename)
      {
        FILE* f = fopen(filename, "rb");
        if (f == NULL) error("Could not open %s for reading.", filename);
        lock_data();

        struct { char magic[4]; int ver; } hdr;
        if (fread(&hdr, sizeof(hdr), 1, f) != 1)
          error("Error reading %s", filename);

        if (hdr.magic[0] != 'H' || hdr.magic[1] != '2' || hdr.magic[2] != 'D' || hdr.magic[3] != 'O')
          error("File %s is not a Hermes2D Orderizer<Scalar> file.", filename);
        if (hdr.ver > 1)
          error("File %s -- unsupported file version.", filename);

#define read_array(array, type, n, c, what) \
  if (fread(&n, sizeof(int), 1, f) != 1) \
  error("Error reading the number of " what " from %s", filename); \
  lin_init_array(array, type, c, n); \
  if (fread(array, sizeof(type), n, f) != (unsigned) n) \
  error("Error reading " what " from %s", filename);

        read_array(verts, double3, nv, cv,  "vertices");
        read_array(tris,  int3,    nt, ct,  "triangles");
        read_array(edges, int3,    ne, ce,  "edges");
        read_array(lvert, int,     nl, cl1, "label vertices");

        lin_init_array(lbox, double2, cl3, nl);
        if (fread(lbox, sizeof(double2), nl, f) != (unsigned) nl)
          error("Error reading label bounding boxes from %s", filename);

        int* orders = new int[nl];
        if (fread(orders, sizeof(int), nl, f) != (unsigned) nl)
          error("Error reading element orders from %s", filename);

        lin_init_array(ltext, char*, cl2, nl);
        for (int i = 0; i < nl; i++)
          ltext[i] = labels[H2D_GET_H_ORDER(orders[i])][H2D_GET_V_ORDER(orders[i])];

        find_min_max();
        unlock_data();
        fclose(f);
      }
Ejemplo n.º 14
0
      void VertexBasedLimiter::process()
      {
        // 0. Preparation.
        // Start by creating temporary solutions and states for paralelism.
        Solution<double>::vector_to_solutions(this->solution_vector, this->spaces, this->limited_solutions);

        // 1. Quadratic
        // Prepare the vertex values for the quadratic part.
        prepare_min_max_vertex_values(true);

        // Use those to incorporate the correction factor.
        Element* e;

        // Vector to remember if there was limiting of the second derivatives.
        Hermes::vector<bool> quadratic_correction_done;

        if (this->get_verbose_output())
          std::cout << "Quadratic correction" << std::endl;

        for (int component = 0; component < this->component_count; component++)
        {
          MeshSharedPtr mesh = this->spaces[component]->get_mesh();
          if (this->get_verbose_output() && this->component_count > 1)
            std::cout << "Component: " << component << std::endl;
          for_all_active_elements(e, mesh)
          {
            bool second_order = H2D_GET_H_ORDER(this->spaces[component]->get_element_order(e->id)) >= 2 || H2D_GET_V_ORDER(this->spaces[component]->get_element_order(e->id)) >= 2;
            if (!second_order)
            {
              quadratic_correction_done.push_back(false);
              continue;
            }

            if (this->get_verbose_output())
              std::cout << "Element: " << e->id << std::endl;

            quadratic_correction_done.push_back(this->impose_quadratic_correction_factor(e, component));

            if (this->get_verbose_output())
              std::cout << std::endl;
          }
        }
Ejemplo n.º 15
0
void PrecalcShapeset::set_active_shape(int index)
{
  // Key creation.
  unsigned key = cur_quad | (mode << 3) | ((unsigned) (max_index[mode] - index) << 4);

  if(master_pss == NULL) {
    if(!tables.present(key))
      tables.add(new std::map<uint64_t, LightArray<Node*>*>, key);
    sub_tables = tables.get(key);
  }
  else {
    if(!master_pss->tables.present(key))
      master_pss->tables.add(new std::map<uint64_t, LightArray<Node*>*>, key);
    sub_tables = master_pss->tables.get(key);
  }

  // Update the Node table.
  update_nodes_ptr();

  this->index = index;
  order = std::max(H2D_GET_H_ORDER(shapeset->get_order(index)), H2D_GET_V_ORDER(shapeset->get_order(index)));
}
Ejemplo n.º 16
0
      bool POnlySelector<Scalar>::select_refinement(Element* element, int order, MeshFunction<Scalar>* rsln, ElementToRefine& refinement)
      {
        refinement.split = H2D_REFINEMENT_P;

        //determin max. order
        int max_allowed_order = this->max_order;
        if(this->max_order == H2DRS_DEFAULT_ORDER)
          max_allowed_order = H2DRS_MAX_ORDER;

        //calculate new_ order
        int order_h = H2D_GET_H_ORDER(order), order_v = H2D_GET_V_ORDER(order);
        int new_order_h = std::min(max_allowed_order, order_h + order_h_inc);
        int new_order_v = std::min(max_allowed_order, order_v + order_v_inc);
        if(element->is_triangle())
          refinement.refinement_polynomial_order[0] = refinement.best_refinement_polynomial_order_type[H2D_REFINEMENT_P][0] = new_order_h;
        else
          refinement.refinement_polynomial_order[0] = refinement.best_refinement_polynomial_order_type[H2D_REFINEMENT_P][0] = H2D_MAKE_QUAD_ORDER(new_order_h, new_order_v);

        //decide if successful
        if(new_order_h > order_h || new_order_v > order_v)
          return true;
        else
          return false;
      }
Ejemplo n.º 17
0
void L2OrthoHP::get_optimal_refinement(Element* e, int order, Solution* rsln, int& split, int p[4],
                                       bool h_only, bool iso_only, double conv_exp, int max_order)

{
  int i, j, k, n = 0;
  const int maxcand = 300;

  order = std::max(H2D_GET_H_ORDER(order), H2D_GET_V_ORDER(order));
  bool tri = e->is_triangle();

  // calculate maximal order of elements
  // linear elements = 9
  // curvilinear elements = depends on iro_cache (how curved they are)
  if (max_order == -1)
    max_order = (20 - e->iro_cache)/2 - 2; // default
  else
    max_order = std::min( max_order, (20 - e->iro_cache)/2 - 2); // user specified

  Cand* cand = new Cand[maxcand];

  #define make_p_cand(q) { \
    assert(n < maxcand);   \
    cand[n].split = -1; \
    cand[n].p[1] = cand[n].p[2] = cand[n].p[3] = 0; \
    cand[n++].p[0] = (q); }

  #define make_hp_cand(q0, q1, q2, q3) { \
    assert(n < maxcand);  \
    cand[n].split = 0; \
    cand[n].p[0] = (q0); \
    cand[n].p[1] = (q1); \
    cand[n].p[2] = (q2); \
    cand[n++].p[3] = (q3); }

  #define make_ani_cand(q0, q1, iso) { \
    assert(n < maxcand);  \
    cand[n].split = iso; \
    cand[n].p[2] = cand[n].p[3] = 0; \
    cand[n].p[0] = (q0); \
    cand[n++].p[1] = (q1); }\


  if (h_only)
  {
    make_p_cand(order);
    make_hp_cand(order, order, order, order);
    make_ani_cand(order, order, 1);
    make_ani_cand(order, order, 2);
  }
  else
  {
    // prepare p-candidates
    int p0, p1 = std::min(max_order, order+1);
    for (p0 = order; p0 <= p1; p0++)
      make_p_cand(p0);

    // prepare hp-candidates
    p0 = (order+1) / 2;
    p1 = std::min(p0 + 3, order);
    int q0, q1, q2, q3;
    for (q0 = p0; q0 <= p1; q0++)
      for (q1 = p0; q1 <= p1; q1++)
        for (q2 = p0; q2 <= p1; q2++)
          for (q3 = p0; q3 <= p1; q3++)
            make_hp_cand(q0, q1, q2, q3);

    // prepare anisotropic candidates
    // only for quadrilaterals
    // too distorted (curved) elements cannot have aniso refinement (produces even worse elements)
    if ((!tri) && (e->iro_cache < 8) && !iso_only) {
      p0 = 2 * (order+1) / 3;
      int p_max = std::min(max_order, order+1);
      p1 = std::min(p0 + 3, p_max);
      for (q0 = p0; q0 <= p1; q0++)
        for (q1 = p0; q1 <= p1; q1++) {
          if ((q0 < order+1) || (q1 < order+1)) {
            make_ani_cand(q0, q1, 1);
            make_ani_cand(q0, q1, 2);
          }
        }
    }
  }
  // calculate (partial) projection errors
  double herr[8][11], perr[11];
  calc_projection_errors(e, order, rsln, herr, perr);

  // evaluate candidates (sum partial projection errors, calculate dofs)
  double avg = 0.0;
  double dev = 0.0;
  for (i = k = 0; i < n; i++)
  {
    Cand* c = cand + i;
    if (c->split == 0)
    {
      c->error = 0.0;
      c->dofs = tri ? 6 : 9;
      for (j = 0; j < 4; j++)
      {
        int o = c->p[j];
        c->error += herr[j][o] * 0.25; // spravny vypocet chyby
        if (tri) {
          c->dofs += (o-2)*(o-1)/2;
          if (j < 3) c->dofs +=  std::min(o, c->p[3])-1 + 2*(o-1);
        }
        else {
          c->dofs += sqr(o)-1;
          c->dofs += 2 * std::min(o, c->p[j>0 ? j-1 : 3]) - 1;
        }
      }
    }
    else if (c->split == 1 || c->split == 2)  // aniso splits
    {
      c->dofs  = 6 /* vertex */ + 3*(c->p[0] - 1 + c->p[1] - 1); // edge fns
      c->dofs +=  std::min(c->p[0], c->p[1]) - 1; // common edge
      c->dofs += sqr(c->p[0] - 1) + sqr(c->p[1] - 1); // bubbles
      for (c->error = 0.0, j = 0; j < 2; j++)
        c->error += herr[(c->split == 1) ? j+4 : j+6][c->p[j]] * 0.5;  // spravny vypocet chyby

    }
    else
    {
      int o = c->p[0];
      c->error = perr[o];
      c->dofs  = tri ? (o+1)*(o+2)/2 : sqr(o+1);
    }
    c->error = sqrt(c->error);

    //verbose("Cand #%d: Orders %d %d %d %d, Error %g, Dofs %d", i, c->p[0],c->p[1],c->p[2],c->p[3],c->error, c->dofs);

    if (!i || c->error <= cand[0].error)
    {
      avg += log(c->error);
      dev += sqr(log(c->error));
      k++;
    }
  }
  avg /= k;  // mean
  dev /= k;  // second moment
  dev = sqrt(dev - sqr(avg));  // deviation is square root of variance

  // select an above-average candidate with the steepest error decrease
  int imax = 0;
  double score, maxscore = 0.0;
  for (i = 1; i < n; i++)
  {
    if ((log(cand[i].error) < avg + dev) && (cand[i].dofs > cand[0].dofs))
    {
      score = (log(cand[0].error) - log(cand[i].error)) /
	       //(pow(cand[i].dofs, conv_exp) - pow(cand[0].dofs, conv_exp));
               pow(cand[i].dofs - cand[0].dofs, conv_exp);
      if (score > maxscore) { maxscore = score; imax = i; }
    }
  }

  // return result
  split = cand[imax].split;
  memcpy(p, cand[imax].p, 4*sizeof(int));

  //verbose("Selected Candidate #%d: Orders %d %d %d %d\n", imax, p[0],p[1],p[2],p[3]);

}
Ejemplo n.º 18
0
  void ProjBasedSelector::evaluate_cands_error(Element* e, Solution* rsln, double* avg_error, double* dev_error) {
    bool tri = e->is_triangle();

    // find range of orders
    CandsInfo info_h, info_p, info_aniso;
    update_cands_info(info_h, info_p, info_aniso);

    // calculate squared projection errors of elements of candidates
    CandElemProjError herr[4], anisoerr[4], perr;
    calc_projection_errors(e, info_h, info_p, info_aniso, rsln, herr, perr, anisoerr);

    //evaluate errors and dofs
    double sum_err = 0.0;
    double sum_sqr_err = 0.0;
    int num_processed = 0;
    Cand& unrefined_c = candidates[0];
    for (unsigned i = 0; i < candidates.size(); i++) {
      Cand& c = candidates[i];
      double error_squared = 0.0;
      if (tri) { //triangle
        switch(c.split) {
        case H2D_REFINEMENT_H:
          error_squared = 0.0;
          for (int j = 0; j < H2D_MAX_ELEMENT_SONS; j++) {
            int order = H2D_GET_H_ORDER(c.p[j]);
            error_squared += herr[j][order][order];
          }
          error_squared *= 0.25; //element of a candidate occupies 1/4 of the reference domain defined over a candidate
          break;

        case H2D_REFINEMENT_P:
          {
            int order = H2D_GET_H_ORDER(c.p[0]);
            error_squared = perr[order][order];
          }
          break;

        default:
          error("Unknown split type \"%d\" at candidate %d", c.split, i);
        }
      }
      else { //quad
        switch(c.split) {
        case H2D_REFINEMENT_H:
          error_squared = 0.0;
          for (int j = 0; j < H2D_MAX_ELEMENT_SONS; j++) {
            int order_h = H2D_GET_H_ORDER(c.p[j]), order_v = H2D_GET_V_ORDER(c.p[j]);
            error_squared += herr[j][order_h][order_v];
          }
          error_squared *= 0.25; //element of a candidate occupies 1/4 of the reference domain defined over a candidate
          break;

        case H2D_REFINEMENT_ANISO_H:
        case H2D_REFINEMENT_ANISO_V:
          {
            error_squared = 0.0;
            for (int j = 0; j < 2; j++)
              error_squared += anisoerr[(c.split == H2D_REFINEMENT_ANISO_H) ? j : j+2][H2D_GET_H_ORDER(c.p[j])][H2D_GET_V_ORDER(c.p[j])];
            error_squared *= 0.5;  //element of a candidate occupies 1/2 of the reference domain defined over a candidate
          }
          break;

        case H2D_REFINEMENT_P:
          {
            int order_h = H2D_GET_H_ORDER(c.p[0]), order_v = H2D_GET_V_ORDER(c.p[0]);
            error_squared = perr[order_h][order_v];
          }
          break;

        default:
          error("Unknown split type \"%d\" at candidate %d", c.split, i);
        }
      }

      //calculate error from squared error
      c.error = sqrt(error_squared);

      //apply weights
      switch(c.split) {
      case H2D_REFINEMENT_H: c.error *= error_weight_h; break;
      case H2D_REFINEMENT_ANISO_H:
      case H2D_REFINEMENT_ANISO_V: c.error *= error_weight_aniso; break;
      case H2D_REFINEMENT_P: c.error *= error_weight_p; break;
      default: error("Unknown split type \"%d\" at candidate %d", c.split, i);
      }

      //calculate statistics
      if (i == 0 || c.error <= unrefined_c.error) {
        sum_err += log10(c.error);
        sum_sqr_err += sqr(log10(c.error));
        num_processed++;
      }
    }

    *avg_error = sum_err / num_processed;  // mean
    *dev_error = sqrt(sum_sqr_err/num_processed - sqr(*avg_error)); // deviation is square root of variance
  }
Ejemplo n.º 19
0
  void ProjBasedSelector::calc_error_cand_element(const int mode
    , double3* gip_points, int num_gip_points
    , const int num_sub, Element** sub_domains, Trf** sub_trfs, scalar*** sub_rvals
    , std::vector<TrfShapeExp>** sub_nonortho_svals, std::vector<TrfShapeExp>** sub_ortho_svals
    , const CandsInfo& info
    , CandElemProjError errors_squared
    ) {
    //allocate space
    int max_num_shapes = next_order_shape[mode][current_max_order];
    scalar* right_side = new scalar[max_num_shapes];
    int* shape_inxs = new int[max_num_shapes];
    int* indx = new int[max_num_shapes]; //solver data
    double* d = new double[max_num_shapes]; //solver data
    double** proj_matrix = new_matrix<double>(max_num_shapes, max_num_shapes);
    ProjMatrixCache& proj_matrices = proj_matrix_cache[mode];
    std::vector<ShapeInx>& full_shape_indices = shape_indices[mode];

    //check whether ortho-svals are available
    bool ortho_svals_available = true;
    for(int i = 0; i < num_sub && ortho_svals_available; i++)
      ortho_svals_available &= !sub_ortho_svals[i]->empty();

    //clenup of the cache
    for(int i = 0; i <= max_shape_inx[mode]; i++) {
      nonortho_rhs_cache[i] = ValueCacheItem<scalar>();
      ortho_rhs_cache[i] = ValueCacheItem<scalar>();
    }

    //calculate for all orders
    double sub_area_corr_coef = 1.0 / num_sub;
    OrderPermutator order_perm(info.min_quad_order, info.max_quad_order, mode == HERMES_MODE_TRIANGLE || info.uniform_orders);
    do {
      int quad_order = order_perm.get_quad_order();
      int order_h = H2D_GET_H_ORDER(quad_order), order_v = H2D_GET_V_ORDER(quad_order);

      //build a list of shape indices from the full list
      int num_shapes = 0;
      unsigned int inx_shape = 0;
      while (inx_shape < full_shape_indices.size()) {
        ShapeInx& shape = full_shape_indices[inx_shape];
        if (order_h >= shape.order_h && order_v >= shape.order_v) {
          assert_msg(num_shapes < max_num_shapes, "more shapes than predicted, possible incosistency");
          shape_inxs[num_shapes] = shape.inx;
          num_shapes++;
        }
        inx_shape++;
      }

      //continue only if there are shapes to process
      if (num_shapes > 0) {
        bool use_ortho = ortho_svals_available && order_perm.get_order_h() == order_perm.get_order_v();
        //error_if(!use_ortho, "Non-ortho"); //DEBUG

        //select a cache
        std::vector< ValueCacheItem<scalar> >& rhs_cache = use_ortho ? ortho_rhs_cache : nonortho_rhs_cache;
        std::vector<TrfShapeExp>** sub_svals = use_ortho ? sub_ortho_svals : sub_nonortho_svals;

        //calculate projection matrix iff no ortho is used
        if (!use_ortho) {
          //error_if(!use_ortho, "Non-ortho"); //DEBUG
          if (proj_matrices[order_h][order_v] == NULL)
            proj_matrices[order_h][order_v] = build_projection_matrix(gip_points, num_gip_points, shape_inxs, num_shapes);
          copy_matrix(proj_matrix, proj_matrices[order_h][order_v], num_shapes, num_shapes); //copy projection matrix because original matrix will be modified
        }

        //build right side (fill cache values that are missing)
        for(int inx_sub = 0; inx_sub < num_sub; inx_sub++) {
          Element* this_sub_domain = sub_domains[inx_sub];
          ElemSubTrf this_sub_trf = { sub_trfs[inx_sub], 1 / sub_trfs[inx_sub]->m[0], 1 / sub_trfs[inx_sub]->m[1] };
          ElemGIP this_sub_gip = { gip_points, num_gip_points, sub_rvals[inx_sub] };
          std::vector<TrfShapeExp>& this_sub_svals = *(sub_svals[inx_sub]);

          for(int k = 0; k < num_shapes; k++) {
            int shape_inx = shape_inxs[k];
            ValueCacheItem<scalar>& shape_rhs_cache = rhs_cache[shape_inx];
            if (!shape_rhs_cache.is_valid()) {
              TrfShapeExp empty_sub_vals;
              ElemSubShapeFunc this_sub_shape = { shape_inx, this_sub_svals.empty() ? empty_sub_vals : this_sub_svals[shape_inx] };
              shape_rhs_cache.set(shape_rhs_cache.get() + evaluate_rhs_subdomain(this_sub_domain, this_sub_gip, this_sub_trf, this_sub_shape));
            }
          }
        }

        //copy values from cache and apply area correction coefficient
        for(int k = 0; k < num_shapes; k++) {
          ValueCacheItem<scalar>& rhs_cache_value = rhs_cache[shape_inxs[k]];
          right_side[k] = sub_area_corr_coef * rhs_cache_value.get();
          rhs_cache_value.mark();
        }

        //solve iff no ortho is used
        if (!use_ortho) {
          //error_if(!use_ortho, "Non-ortho"); //DEBUG
          ludcmp(proj_matrix, num_shapes, indx, d);
          lubksb<scalar>(proj_matrix, num_shapes, indx, right_side);
        }

        //calculate error
        double error_squared = 0;
        for(int inx_sub = 0; inx_sub < num_sub; inx_sub++) {
          Element* this_sub_domain = sub_domains[inx_sub];
          ElemSubTrf this_sub_trf = { sub_trfs[inx_sub], 1 / sub_trfs[inx_sub]->m[0], 1 / sub_trfs[inx_sub]->m[1] };
          ElemGIP this_sub_gip = { gip_points, num_gip_points, sub_rvals[inx_sub] };
          ElemProj elem_proj = { shape_inxs, num_shapes, *(sub_svals[inx_sub]), right_side, quad_order };

          error_squared += evaluate_error_squared_subdomain(this_sub_domain, this_sub_gip, this_sub_trf, elem_proj);
        }
        errors_squared[order_h][order_v] = error_squared * sub_area_corr_coef; //apply area correction coefficient
      }
    } while (order_perm.next());

    //clenaup
    delete[] proj_matrix;
    delete[] right_side;
    delete[] shape_inxs;
    delete[] indx;
    delete[] d;
  }
Ejemplo n.º 20
0
  void ProjBasedSelector::calc_projection_errors(Element* e, const CandsInfo& info_h, const CandsInfo& info_p, const CandsInfo& info_aniso, Solution* rsln, CandElemProjError herr[4], CandElemProjError perr, CandElemProjError anisoerr[4]) {
    assert_msg(info_h.is_empty() || (H2D_GET_H_ORDER(info_h.max_quad_order) <= H2DRS_MAX_ORDER && H2D_GET_V_ORDER(info_h.max_quad_order) <= H2DRS_MAX_ORDER), "Maximum allowed order of a son of H-candidate is %d but order (H:%d,V:%d) requested.", H2DRS_MAX_ORDER, H2D_GET_H_ORDER(info_h.max_quad_order), H2D_GET_V_ORDER(info_h.max_quad_order));
    assert_msg(info_p.is_empty() || (H2D_GET_H_ORDER(info_p.max_quad_order) <= H2DRS_MAX_ORDER && H2D_GET_V_ORDER(info_p.max_quad_order) <= H2DRS_MAX_ORDER), "Maximum allowed order of a son of P-candidate is %d but order (H:%d,V:%d) requested.", H2DRS_MAX_ORDER, H2D_GET_H_ORDER(info_p.max_quad_order), H2D_GET_V_ORDER(info_p.max_quad_order));
    assert_msg(info_aniso.is_empty() || (H2D_GET_H_ORDER(info_aniso.max_quad_order) <= H2DRS_MAX_ORDER && H2D_GET_V_ORDER(info_aniso.max_quad_order) <= H2DRS_MAX_ORDER), "Maximum allowed order of a son of ANISO-candidate is %d but order (H:%d,V:%d) requested.", H2DRS_MAX_ORDER, H2D_GET_H_ORDER(info_aniso.max_quad_order), H2D_GET_V_ORDER(info_aniso.max_quad_order));

    int mode = e->get_mode();

    // select quadrature, obtain integration points and weights
    Quad2D* quad = &g_quad_2d_std;
    quad->set_mode(mode);
    rsln->set_quad_2d(quad);
    double3* gip_points = quad->get_points(H2DRS_INTR_GIP_ORDER);
    int num_gip_points = quad->get_num_points(H2DRS_INTR_GIP_ORDER);

    // everything is done on the reference domain
    rsln->enable_transform(false);

    // obtain reference solution values on all four refined sons
    scalar** rval[H2D_MAX_ELEMENT_SONS];
    Element* base_element = rsln->get_mesh()->get_element(e->id);
    assert(!base_element->active);
    for (int son = 0; son < H2D_MAX_ELEMENT_SONS; son++)
    {
      //set element
      Element* e = base_element->sons[son];
      assert(e != NULL);

      //obtain precalculated values
      rval[son] = precalc_ref_solution(son, rsln, e, H2DRS_INTR_GIP_ORDER);
    }

    //retrieve transformations
    Trf* trfs = NULL;
    int num_noni_trfs = 0;
    if (mode == HERMES_MODE_TRIANGLE) {
      trfs = tri_trf;
      num_noni_trfs = H2D_TRF_TRI_NUM;
    }
    else {
      trfs = quad_trf;
      num_noni_trfs = H2D_TRF_QUAD_NUM;
    }

    // precalculate values of shape functions
    TrfShape empty_shape_vals;
    if (!cached_shape_vals_valid[mode]) {
      precalc_ortho_shapes(gip_points, num_gip_points, trfs, num_noni_trfs, shape_indices[mode], max_shape_inx[mode], cached_shape_ortho_vals[mode]);
      precalc_shapes(gip_points, num_gip_points, trfs, num_noni_trfs, shape_indices[mode], max_shape_inx[mode], cached_shape_vals[mode]);
      cached_shape_vals_valid[mode] = true;

      //issue a warning if ortho values are defined and the selected cand_list might benefit from that but it cannot because elements do not have uniform orders
      if (!warn_uniform_orders && mode == HERMES_MODE_QUAD && !cached_shape_ortho_vals[mode][H2D_TRF_IDENTITY].empty()) {
        warn_uniform_orders = true;
        if (cand_list == H2D_H_ISO || cand_list == H2D_H_ANISO || cand_list == H2D_P_ISO || cand_list == H2D_HP_ISO || cand_list == H2D_HP_ANISO_H) {
          warn_if(!info_h.uniform_orders || !info_aniso.uniform_orders || !info_p.uniform_orders, "Possible inefficiency: %s might be more efficient if the input mesh contains elements with uniform orders strictly.", get_cand_list_str(cand_list));
        }
      }
    }
    TrfShape& svals = cached_shape_vals[mode];
    TrfShape& ortho_svals = cached_shape_ortho_vals[mode];

    //H-candidates
    if (!info_h.is_empty()) {
      Trf* p_trf_identity[1] = { &trfs[H2D_TRF_IDENTITY] };
      std::vector<TrfShapeExp>* p_trf_svals[1] = { &svals[H2D_TRF_IDENTITY] };
      std::vector<TrfShapeExp>* p_trf_ortho_svals[1] = { &ortho_svals[H2D_TRF_IDENTITY] };
      for(int son = 0; son < H2D_MAX_ELEMENT_SONS; son++) {
        scalar **sub_rval[1] = { rval[son] };
        calc_error_cand_element(mode, gip_points, num_gip_points
          , 1, &base_element->sons[son], p_trf_identity, sub_rval
          , p_trf_svals, p_trf_ortho_svals
          , info_h, herr[son]);
      }
    }

    //ANISO-candidates
    if (!info_aniso.is_empty()) {
      const int sons[4][2] = { {0,1}, {3,2}, {0,3}, {1,2} }; //indices of sons for sub-areas
      const int tr[4][2]   = { {6,7}, {6,7}, {4,5}, {4,5} }; //indices of ref. domain transformations for sub-areas
      for(int version = 0; version < 4; version++) { // 2 elements for vertical split, 2 elements for horizontal split
        Trf* sub_trfs[2] = { &trfs[tr[version][0]], &trfs[tr[version][1]] };
        Element* sub_domains[2] = { base_element->sons[sons[version][0]], base_element->sons[sons[version][1]] };
        scalar **sub_rval[2] = { rval[sons[version][0]], rval[sons[version][1]] };
        std::vector<TrfShapeExp>* sub_svals[2] = { &svals[tr[version][0]], &svals[tr[version][1]] };
        std::vector<TrfShapeExp>* sub_ortho_svals[2] = { &ortho_svals[tr[version][0]], &ortho_svals[tr[version][1]] };
        calc_error_cand_element(mode, gip_points, num_gip_points
          , 2, sub_domains, sub_trfs, sub_rval
          , sub_svals, sub_ortho_svals
          , info_aniso, anisoerr[version]);
      }
    }

    //P-candidates
    if (!info_p.is_empty()) {
      Trf* sub_trfs[4] = { &trfs[0], &trfs[1], &trfs[2], &trfs[3] };
      scalar **sub_rval[4] = { rval[0], rval[1], rval[2], rval[3] };
      std::vector<TrfShapeExp>* sub_svals[4] = { &svals[0], &svals[1], &svals[2], &svals[3] };
      std::vector<TrfShapeExp>* sub_ortho_svals[4] = { &ortho_svals[0], &ortho_svals[1], &ortho_svals[2], &ortho_svals[3] };

      calc_error_cand_element(mode, gip_points, num_gip_points
        , 4, base_element->sons, sub_trfs, sub_rval
        , sub_svals, sub_ortho_svals
        , info_p, perr);
    }
  }
Ejemplo n.º 21
0
      void Orderizer::process_space(SpaceSharedPtr<Scalar> space, bool show_edge_orders)
      {
        // sanity check
        if (space == nullptr)
          throw Hermes::Exceptions::Exception("Space is nullptr in Orderizer:process_space().");

        if (!space->is_up_to_date())
          throw Hermes::Exceptions::Exception("The space is not up to date.");

        MeshSharedPtr mesh = space->get_mesh();

        // Reallocate.
        this->reallocate(mesh);

        RefMap refmap;

        int oo, o[6];

        // make a mesh illustrating the distribution of polynomial orders over the space
        Element* e;
        for_all_active_elements(e, mesh)
        {
          oo = o[4] = o[5] = space->get_element_order(e->id);
          if (show_edge_orders)
          for (unsigned int k = 0; k < e->get_nvert(); k++)
            o[k] = space->get_edge_order(e, k);
          else if (e->is_curved())
          {
            if (e->is_triangle())
            for (unsigned int k = 0; k < e->get_nvert(); k++)
              o[k] = oo;
            else
            for (unsigned int k = 0; k < e->get_nvert(); k++)
              o[k] = H2D_GET_H_ORDER(oo);
          }

          double3* pt;
          int np;
          double* x;
          double* y;
          if (show_edge_orders || e->is_curved())
          {
            refmap.set_quad_2d(&quad_ord);
            refmap.set_active_element(e);
            x = refmap.get_phys_x(1);
            y = refmap.get_phys_y(1);

            pt = quad_ord.get_points(1, e->get_mode());
            np = quad_ord.get_num_points(1, e->get_mode());
          }
          else
          {
            refmap.set_quad_2d(&quad_ord_simple);
            refmap.set_active_element(e);
            x = refmap.get_phys_x(1);
            y = refmap.get_phys_y(1);

            pt = quad_ord_simple.get_points(1, e->get_mode());
            np = quad_ord_simple.get_num_points(1, e->get_mode());
          }

          int id[80];
          assert(np <= 80);

          int mode = e->get_mode();
          if (e->is_quad())
          {
            o[4] = H2D_GET_H_ORDER(oo);
            o[5] = H2D_GET_V_ORDER(oo);
          }
          if (show_edge_orders || e->is_curved())
          {
            make_vert(lvert[label_count], x[0], y[0], o[4]);

            for (int i = 1; i < np; i++)
              make_vert(id[i - 1], x[i], y[i], o[(int)pt[i][2]]);

            for (int i = 0; i < num_elem[mode][1]; i++)
              this->add_triangle(id[ord_elem[mode][1][i][0]], id[ord_elem[mode][1][i][1]], id[ord_elem[mode][1][i][2]], e->marker);

            for (int i = 0; i < num_edge[mode][1]; i++)
            {
              if (e->en[ord_edge[mode][1][i][2]]->bnd || (y[ord_edge[mode][1][i][0] + 1] < y[ord_edge[mode][1][i][1] + 1]) ||
                ((y[ord_edge[mode][1][i][0] + 1] == y[ord_edge[mode][1][i][1] + 1]) &&
                (x[ord_edge[mode][1][i][0] + 1] < x[ord_edge[mode][1][i][1] + 1])))
              {
                add_edge(id[ord_edge[mode][1][i][0]], id[ord_edge[mode][1][i][1]], e->en[ord_edge[mode][1][i][2]]->marker);
              }
            }
          }
          else
          {
            make_vert(lvert[label_count], x[0], y[0], o[4]);

            for (int i = 1; i < np; i++)
              make_vert(id[i - 1], x[i], y[i], o[(int)pt[i][2]]);

            for (int i = 0; i < num_elem_simple[mode][1]; i++)
              this->add_triangle(id[ord_elem_simple[mode][1][i][0]], id[ord_elem_simple[mode][1][i][1]], id[ord_elem_simple[mode][1][i][2]], e->marker);

            for (int i = 0; i < num_edge_simple[mode][1]; i++)
              add_edge(id[ord_edge_simple[mode][1][i][0]], id[ord_edge_simple[mode][1][i][1]], e->en[ord_edge_simple[mode][1][i][2]]->marker);
          }

          double xmin = 1e100, ymin = 1e100, xmax = -1e100, ymax = -1e100;
          for (unsigned int k = 0; k < e->get_nvert(); k++)
          {
            if (e->vn[k]->x < xmin) xmin = e->vn[k]->x;
            if (e->vn[k]->x > xmax) xmax = e->vn[k]->x;
            if (e->vn[k]->y < ymin) ymin = e->vn[k]->y;
            if (e->vn[k]->y > ymax) ymax = e->vn[k]->y;
          }
          lbox[label_count][0] = xmax - xmin;
          lbox[label_count][1] = ymax - ymin;
          ltext[label_count++] = labels[o[4]][o[5]];
        }
Ejemplo n.º 22
0
  bool select_refinement(Element* element, int order, MeshFunction<complex>* rsln, ElementToRefine& refinement)
  {
    switch(strategy)
    {
    case(noSelectionH):
      {
        refinement.split = H2D_REFINEMENT_H;
        refinement.best_refinement_polynomial_order_type[H2D_REFINEMENT_H][0] = 
          refinement.best_refinement_polynomial_order_type[H2D_REFINEMENT_H][1] = 
          refinement.best_refinement_polynomial_order_type[H2D_REFINEMENT_H][2] = 
          refinement.best_refinement_polynomial_order_type[H2D_REFINEMENT_H][3] = 
          order;
        ElementToRefine::copy_orders(refinement.refinement_polynomial_order, refinement.best_refinement_polynomial_order_type[H2D_REFINEMENT_H]);
        return true;
      }
      break;
    case(noSelectionHP):
      {
        int max_allowed_order = this->max_order;
        if(this->max_order == H2DRS_DEFAULT_ORDER)
          max_allowed_order = H2DRS_MAX_ORDER;
        int order_h = H2D_GET_H_ORDER(order), order_v = H2D_GET_V_ORDER(order);
        int increased_order_h = std::min(max_allowed_order, order_h + 1), increased_order_v = std::min(max_allowed_order, order_v + 1);
        int increased_order;
        if(element->is_triangle())
          increased_order = refinement.best_refinement_polynomial_order_type[H2D_REFINEMENT_H][0] = H2D_MAKE_QUAD_ORDER(increased_order_h, increased_order_h);
        else
          increased_order = refinement.best_refinement_polynomial_order_type[H2D_REFINEMENT_H][0] = H2D_MAKE_QUAD_ORDER(increased_order_h, increased_order_v);

        refinement.split = H2D_REFINEMENT_H;
        refinement.best_refinement_polynomial_order_type[H2D_REFINEMENT_H][0] = 
          refinement.best_refinement_polynomial_order_type[H2D_REFINEMENT_H][1] = 
          refinement.best_refinement_polynomial_order_type[H2D_REFINEMENT_H][2] = 
          refinement.best_refinement_polynomial_order_type[H2D_REFINEMENT_H][3] = 
          increased_order;
        ElementToRefine::copy_orders(refinement.refinement_polynomial_order, refinement.best_refinement_polynomial_order_type[H2D_REFINEMENT_H]);
        return true;
      }
      case(hXORpSelectionBasedOnError):
      {
        //make an uniform order in a case of a triangle
        int order_h = H2D_GET_H_ORDER(order), order_v = H2D_GET_V_ORDER(order);

        int current_min_order, current_max_order;
        this->get_current_order_range(element, current_min_order, current_max_order);

        if(current_max_order < std::max(order_h, order_v))
          current_max_order = std::max(order_h, order_v);

        int last_order_h = std::min(current_max_order, order_h + 1), last_order_v = std::min(current_max_order, order_v + 1);
        int last_order = H2D_MAKE_QUAD_ORDER(last_order_h, last_order_v);

        //build candidates.
        Hermes::vector<Cand> candidates;
        candidates.push_back(Cand(H2D_REFINEMENT_P, last_order));
        candidates.push_back(Cand(H2D_REFINEMENT_H, order, order, order, order));
        
        this->evaluate_cands_error(candidates, element, rsln);
        
        Cand* best_candidate = (candidates[0].error < candidates[1].error) ? &candidates[0] : &candidates[1];
        Cand* best_candidates_specific_type[4];
        best_candidates_specific_type[H2D_REFINEMENT_P] = &candidates[0];
        best_candidates_specific_type[H2D_REFINEMENT_H] = &candidates[1];
        best_candidates_specific_type[2] = NULL;
        best_candidates_specific_type[3] = NULL;

        //copy result to output
        refinement.split = best_candidate->split;
        ElementToRefine::copy_orders(refinement.refinement_polynomial_order, best_candidate->p);
        for(int i = 0; i < 4; i++)
          if(best_candidates_specific_type[i] != NULL)
            ElementToRefine::copy_orders(refinement.best_refinement_polynomial_order_type[i], best_candidates_specific_type[i]->p);

        ElementToRefine::copy_errors(refinement.errors, best_candidate->errors);

        //modify orders in a case of a triangle such that order_v is zero
        if(element->is_triangle())
          for(int i = 0; i < H2D_MAX_ELEMENT_SONS; i++)
            refinement.refinement_polynomial_order[i] = H2D_MAKE_QUAD_ORDER(H2D_GET_H_ORDER(refinement.refinement_polynomial_order[i]), 0);

        return true;
      }
    default:
      H1ProjBasedSelector<complex>::select_refinement(element, order, rsln, refinement);
      return true;
      break;
    }
  }
Ejemplo n.º 23
0
void L2OrthoHP::calc_ortho_base()
{
  int i, j, k, l, m, ii, nb, np, o, r;
  int n, idx[121];

  H1Shapeset shapeset;

  // allocate the orthonormal base tables - these are simply the values of the
  // orthonormal functions in integration points; we store the basic functions
  // plus four son cut-outs of them (i.e. 5 times)
  for (i = 0; i < 9; i++)
  {
    if ((i < 4) || (i >= 8))
      obase[0][i] = new_matrix<double3>(66, 79); // tri
    obase[1][i] = new_matrix<double3>(121, 121); // quad
  }

  // repeat for triangles and quads
  for (m = 0; m <= 1; m++)
  {
    shapeset.set_mode(m);

    // obtain a list of all shape functions up to the order 10, from lowest to highest order
    n = 0;
    int nv = m ? 4 : 3;
    int num_sons = m ? 8 : 4;
    for (i = 0; i < nv; i++)
      idx[n++] = shapeset.get_vertex_index(i);
    basecnt[m][0] = 0;
    basecnt[m][1] = n;

    for (i = 2; i <= 10; i++)
    {
      for (j = 0; j < nv; j++)
        idx[n++] = shapeset.get_edge_index(j, 0, i);

      ii = m ? H2D_MAKE_QUAD_ORDER(i, i) : i;
      nb = shapeset.get_num_bubbles(ii);
      int* bub = shapeset.get_bubble_indices(ii);
      for (j = 0; j < nb; j++)
      {
        o = shapeset.get_order(bub[j]);
        if (H2D_GET_H_ORDER(o) == i || H2D_GET_V_ORDER(o) == i)
          idx[n++] = bub[j];
      }
      basecnt[m][i] = n;
    }

    // obtain their values for integration rule 20
    g_quad_2d_std.set_mode(m);
    np = g_quad_2d_std.get_num_points(20);
    double3* pt = g_quad_2d_std.get_points(20);

    for (i = 0; i < n; i++)
      for (j = 0; j < np; j++)
        for (k = 0; k < 3; k++)
          obase[m][8][i][j][k] = shapeset.get_value(k, idx[i], pt[j][0], pt[j][1], 0);

    for (l = 0; l < num_sons; l++)
    {
      Trf* tr = (m ? quad_trf : tri_trf) + l;
      for (i = 0; i < n; i++)
        for (j = 0; j < np; j++)
        {
          double x = tr->m[0]*pt[j][0] + tr->t[0],
                 y = tr->m[1]*pt[j][1] + tr->t[1];
          for (k = 0; k < 3; k++)
            obase[m][l][i][j][k] = shapeset.get_value(k, idx[i], x, y, 0);
        }
    }

    // orthonormalize the basis functions
    for (i = 0; i < n; i++)
    {
      for (j = 0; j < i; j++)
      {
        double prod = 0.0;
        for (k = 0; k < np; k++) {
          double sum = 0.0;
          for (r = 0; r < 1; r++)
            sum += obase[m][8][i][k][r] * obase[m][8][j][k][r];
          prod += pt[k][2] * sum;
        }

        for (l = 0; l < 9; l++)
          if (m || l < 4 || l >= 8)
            for (k = 0; k < np; k++)
              for (r = 0; r < 1; r++)
                obase[m][l][i][k][r] -= prod * obase[m][l][j][k][r];
      }

      double norm = 0.0;
      for (k = 0; k < np; k++) {
        double sum = 0.0;
        for (r = 0; r < 1; r++)
          sum += sqr(obase[m][8][i][k][r]);
        norm += pt[k][2] * sum;
      }
      norm = sqrt(norm);

      for (l = 0; l < 9; l++)
        if (m || l < 4 || l >= 8)
          for (k = 0; k < np; k++)
            for (r = 0; r < 1; r++)
              obase[m][l][i][k][r] /= norm;
    }

    // check the orthonormal base
/*    if (m) {
    for (i = 0; i < n; i++)
      for (j = 0; j < n; j++)
      {
        double check = 0.0;
        for(int son = 4; son < 6; son++ )
          for (k = 0; k < np; k++)
            check += pt[k][2] * (obase[m][son][i][k][0] * obase[m][son][j][k][0] +
                                 obase[m][son][i][k][1] * obase[m][son][j][k][1] +
                                 obase[m][son][i][k][2] * obase[m][son][j][k][2]);
        check *= 0.5;
        if ((i == j && fabs(check - 1.0) > 1e-8) || (i != j && fabs(check) > 1e-8))
          warn("Not orthonormal: base %d times base %d = %g", i, j , check);
      }
    }*/
  }
  obase_ready = true;
}
Ejemplo n.º 24
0
void RefSystem::global_refinement()
{
    // after this, meshes and spaces are NULL
    this->free_spaces();

    // create new meshes and spaces
    this->meshes = new Mesh*[this->wf->neq];
    this->spaces = new Space*[this->wf->neq];
    this->sp_seq = new int[this->wf->neq];

    int i, j;
    // copy meshes from the coarse problem and refine them
    for (i = 0; i < this->wf->neq; i++)
    {
        Mesh* mesh = base->spaces[i]->get_mesh();

        // check if we already have the same mesh
        for (j = 0; j < i; j++)
            if (mesh->get_seq() == base->spaces[j]->get_mesh()->get_seq())
                break;

        if (j < i) // yes
        {
            meshes[i] = meshes[j];
        }
        else // no, copy and refine the coarse one
        {
            Mesh* rmesh = new Mesh;
            rmesh->copy(mesh);
            if (refinement ==  1) rmesh->refine_all_elements();
            if (refinement == -1) rmesh->unrefine_all_elements();
            this->meshes[i] = rmesh;
        }
    }

    // duplicate spaces from the coarse problem, assign reference orders and dofs
    int ndof = 0;
    for (i = 0; i < this->wf->neq; i++)
    {
        this->spaces[i] = this->base->spaces[i]->dup(this->meshes[i]);

        if (refinement == -1)
        {
            Element* re;
            for_all_active_elements(re, meshes[i])
            {
                Mesh* mesh = this->base->spaces[i]->get_mesh();
                Element* e = mesh->get_element(re->id);
                int max_order_h = 0, max_order_v = 0;
                if (e->active) {
                    int quad_order = base->spaces[i]->get_element_order(e->id);
                    max_order_h = H2D_GET_H_ORDER(quad_order);
                    max_order_v = H2D_GET_V_ORDER(quad_order);
                }
                else
                {   //find maximum order of sons
                    for (int son = 0; son < 4; son++)
                    {
                        if (e->sons[son] != NULL)
                        {
                            int quad_order = base->spaces[i]->get_element_order(e->sons[son]->id);
                            max_order_h = std::max(max_order_h, H2D_GET_H_ORDER(quad_order));
                            max_order_v = std::max(max_order_v, H2D_GET_V_ORDER(quad_order));
                        }
                    }
                }

                //increase order and set it to element
                max_order_h = std::max(1, max_order_h + order_increase);
                if (re->is_triangle())
                    max_order_v = 0;
                else
                    max_order_v = std::max(1, max_order_v + order_increase);
                spaces[i]->set_element_order_internal(re->id, H2D_MAKE_QUAD_ORDER(max_order_h, max_order_v));
            }
        }
Ejemplo n.º 25
0
void Orderizer::process_solution(Space* space)
{
  // sanity check
  if (space == NULL) error("Space is NULL in Orderizer:process_solution().");

  if (!space->is_up_to_date())
    error("The space is not up to date.");

  int type = 1;

  nv = nt = ne = nl = 0;
  del_slot = -1;

  // estimate the required number of vertices and triangles
  Mesh* mesh = space->get_mesh();
  if (mesh == NULL) {
    error("Mesh is NULL in Orderizer:process_solution().");
  }
  int nn = mesh->get_num_active_elements();
  int ev = 77 * nn, et = 64 * nn, ee = 16 * nn, el = nn + 10;

  // reuse or allocate vertex, triangle and edge arrays
  lin_init_array(verts, double3, cv, ev);
  lin_init_array(tris, int3, ct, et);
  lin_init_array(edges, int3, ce, ee);
  lin_init_array(lvert, int, cl1, el);
  lin_init_array(ltext, char*, cl2, el);
  lin_init_array(lbox, double2, cl3, el);
  info = NULL;

  int oo, o[6];

  RefMap refmap;
  refmap.set_quad_2d(&quad_ord);

  // make a mesh illustrating the distribution of polynomial orders over the space
  Element* e;
  for_all_active_elements(e, mesh)
  {
    oo = o[4] = o[5] = space->get_element_order(e->id);
    for (unsigned int k = 0; k < e->nvert; k++)
      o[k] = space->get_edge_order(e, k);

    refmap.set_active_element(e);
    double* x = refmap.get_phys_x(type);
    double* y = refmap.get_phys_y(type);

    double3* pt = quad_ord.get_points(type);
    int np = quad_ord.get_num_points(type);
    int id[80];
    assert(np <= 80);

    #define make_vert(index, x, y, val) \
      { (index) = add_vertex(); \
      verts[index][0] = (x); \
      verts[index][1] = (y); \
      verts[index][2] = (val); }

    int mode = e->get_mode();
    if (e->is_quad())
    {
      o[4] = H2D_GET_H_ORDER(oo);
      o[5] = H2D_GET_V_ORDER(oo);
    }
    make_vert(lvert[nl], x[0], y[0], o[4]);

    for (int i = 1; i < np; i++)
      make_vert(id[i-1], x[i], y[i], o[(int) pt[i][2]]);

    for (int i = 0; i < num_elem[mode][type]; i++)
      add_triangle(id[ord_elem[mode][type][i][0]], id[ord_elem[mode][type][i][1]], id[ord_elem[mode][type][i][2]]);

    for (int i = 0; i < num_edge[mode][type]; i++)
    {
      if (e->en[ord_edge[mode][type][i][2]]->bnd || (y[ord_edge[mode][type][i][0] + 1] < y[ord_edge[mode][type][i][1] + 1]) ||
          ((y[ord_edge[mode][type][i][0] + 1] == y[ord_edge[mode][type][i][1] + 1]) &&
           (x[ord_edge[mode][type][i][0] + 1] <  x[ord_edge[mode][type][i][1] + 1])))
      {
        add_edge(id[ord_edge[mode][type][i][0]], id[ord_edge[mode][type][i][1]], 0);
      }
    }

    double xmin = 1e100, ymin = 1e100, xmax = -1e100, ymax = -1e100;
    for (unsigned int k = 0; k < e->nvert; k++)
    {
      if (e->vn[k]->x < xmin) xmin = e->vn[k]->x;
      if (e->vn[k]->x > xmax) xmax = e->vn[k]->x;
      if (e->vn[k]->y < ymin) ymin = e->vn[k]->y;
      if (e->vn[k]->y > ymax) ymax = e->vn[k]->y;
    }
    lbox[nl][0] = xmax - xmin;
    lbox[nl][1] = ymax - ymin;
    ltext[nl++] = labels[o[4]][o[5]];
  }
Ejemplo n.º 26
0
      void L2ProjBasedSelector<Scalar>::create_candidates(Element* e, int quad_order, int max_ha_quad_order, int max_p_quad_order) 
      {
        int order_h = H2D_GET_H_ORDER(quad_order), order_v = H2D_GET_V_ORDER(quad_order);
        int max_p_order_h = H2D_GET_H_ORDER(max_p_quad_order), max_p_order_v = H2D_GET_V_ORDER(max_p_quad_order);
        int max_ha_order_h = H2D_GET_H_ORDER(max_ha_quad_order), max_ha_order_v = H2D_GET_V_ORDER(max_ha_quad_order);
        bool tri = e->is_triangle();

        //clear list of candidates
        this->candidates.clear();
        if (this->candidates.capacity() < H2DRS_ASSUMED_MAX_CANDS)
          this->candidates.reserve(H2DRS_ASSUMED_MAX_CANDS);

        //generate all P-candidates (start from intention of generating all possible candidates
        //and restrict it according to the given adapt-type)
        bool iso_p = false;
        int start_quad_order = quad_order;
        int last_quad_order = H2D_MAKE_QUAD_ORDER(std::min(max_p_order_h, order_h+H2DRS_MAX_ORDER_INC), std::min(max_p_order_v, order_v+H2DRS_MAX_ORDER_INC));
        switch(this->cand_list) 
        {
        case H2D_H_ISO:
        case H2D_H_ANISO: last_quad_order = start_quad_order; break; //no P-candidates except the original candidate
        case H2D_P_ISO:
        case H2D_HP_ISO:
        case H2D_HP_ANISO_H: iso_p = true; break; //iso change of orders
        }
        this->append_candidates_split(quad_order, last_quad_order, H2D_REFINEMENT_P, tri || iso_p);

        //generate all H-candidates
        iso_p = false;
        int start_order_h = std::max(this->current_min_order, (order_h+1) / 2), start_order_v = std::max(this->current_min_order, (order_v+1) / 2);
        start_quad_order = H2D_MAKE_QUAD_ORDER(start_order_h, start_order_v);
        last_quad_order = H2D_MAKE_QUAD_ORDER(std::min(max_ha_order_h, start_order_h + H2DRS_MAX_ORDER_INC), std::min(max_ha_order_v, start_order_v + H2DRS_MAX_ORDER_INC));
        switch(this->cand_list) 
        {
        case H2D_H_ISO:
        case H2D_H_ANISO:
          last_quad_order = start_quad_order = quad_order; break; //no only one candidate will be created
        case H2D_P_ISO:
        case H2D_P_ANISO: last_quad_order = -1; break; //no H-candidate will be generated
        case H2D_HP_ISO:
        case H2D_HP_ANISO_H: iso_p = true; break; //iso change of orders
        }
        this->append_candidates_split(start_quad_order, last_quad_order, H2D_REFINEMENT_H, tri || iso_p);

        //generate all ANISO-candidates
        if (!tri && e->iro_cache < 8 /** \todo Find and why is iro_cache compared with the number 8. What does the number 8 mean? */
          && (this->cand_list == H2D_H_ANISO || this->cand_list == H2D_HP_ANISO_H || this->cand_list == H2D_HP_ANISO)) 
        {
          iso_p = false;
          int start_quad_order_hz = H2D_MAKE_QUAD_ORDER(order_h, std::max(this->current_min_order, (order_v+1) / 2));
          int last_quad_order_hz = H2D_MAKE_QUAD_ORDER(std::min(max_ha_order_h, order_h+H2DRS_MAX_ORDER_INC), std::min(order_v, H2D_GET_V_ORDER(start_quad_order)+H2DRS_MAX_ORDER_INC));
          int start_quad_order_vt = H2D_MAKE_QUAD_ORDER(std::max(this->current_min_order, (order_h+1) / 2), order_v);
          int last_quad_order_vt = H2D_MAKE_QUAD_ORDER(std::min(order_h, H2D_GET_H_ORDER(start_quad_order)+H2DRS_MAX_ORDER_INC), std::min(max_ha_order_v, order_v+H2DRS_MAX_ORDER_INC));
          switch(this->cand_list) 
          {
          case H2D_H_ANISO:
            last_quad_order_hz = start_quad_order_hz = quad_order;
            last_quad_order_vt = start_quad_order_vt = quad_order;
            break; //only one candidate will be created
          case H2D_HP_ANISO_H: iso_p = true; break; //iso change of orders
          }
          if (iso_p) { //make orders uniform: take mininmum order since nonuniformity is caused by different handling of orders along directions
            int order = std::min(H2D_GET_H_ORDER(start_quad_order_hz), H2D_GET_V_ORDER(start_quad_order_hz));
            start_quad_order_hz = H2D_MAKE_QUAD_ORDER(order, order);
            order = std::min(H2D_GET_H_ORDER(start_quad_order_vt), H2D_GET_V_ORDER(start_quad_order_vt));
            start_quad_order_vt = H2D_MAKE_QUAD_ORDER(order, order);

            order = std::min(H2D_GET_H_ORDER(last_quad_order_hz), H2D_GET_V_ORDER(last_quad_order_hz));
            last_quad_order_hz = H2D_MAKE_QUAD_ORDER(order, order);
            order = std::min(H2D_GET_H_ORDER(last_quad_order_vt), H2D_GET_V_ORDER(last_quad_order_vt));
            last_quad_order_vt = H2D_MAKE_QUAD_ORDER(order, order);
          }
          this->append_candidates_split(start_quad_order_hz, last_quad_order_hz, H2D_REFINEMENT_ANISO_H, iso_p);
          this->append_candidates_split(start_quad_order_vt, last_quad_order_vt, H2D_REFINEMENT_ANISO_V, iso_p);
        }
      }