示例#1
0
Geom<double>* NeighborSearch::init_geometry(Geom<double>** ext_cache_e, SurfPos *ep)
{
  ensure_central_pss_rm(this);
  ensure_active_segment(this);
  
  int eo = get_quad_eo();
  
  if (n_neighbors == 1) // go-up or no-transf neighborhood
  {
    // Do the same as if assembling standard (non-DG) surface forms.
    if (ext_cache_e[eo] == NULL)
      ext_cache_e[eo] = new InterfaceGeom<double> (init_geom_surf(central_rm, ep, eo), 
                                                   neighb_el->marker, neighb_el->id, neighb_el->get_diameter());
    return ext_cache_e[eo];
  } 
  else // go-down neighborhood
  {
    // Also take into account the transformations of the central element.
    Key key(eo, active_segment);
    if (cache_e[key] == NULL)
      cache_e[key] = new InterfaceGeom<double> (init_geom_surf(central_rm, ep, eo), 
                                                neighb_el->marker, neighb_el->id, neighb_el->get_diameter());
    return cache_e[key];
  }    
}
    int init_surface_geometry_points(RefMap** reference_mapping, int reference_mapping_count, int& order, int isurf, int marker, Geom<double>*& geometry, double*& jacobian_x_weights)
    {
      RefMap* rep_reference_mapping = nullptr;
      for (int i = 0; i < reference_mapping_count; i++)
      {
        if (reference_mapping[i])
        {
          if (reference_mapping[i]->get_active_element())
          {
            rep_reference_mapping = reference_mapping[i];
            break;
          }
        }
      }

      int eo = rep_reference_mapping->get_quad_2d()->get_edge_points(isurf, order, rep_reference_mapping->get_active_element()->get_mode());
      double3* pt = rep_reference_mapping->get_quad_2d()->get_points(eo, rep_reference_mapping->get_active_element()->get_mode());
      int np = rep_reference_mapping->get_quad_2d()->get_num_points(eo, rep_reference_mapping->get_active_element()->get_mode());

      // Init geometry and jacobian*weights.
      double3* tan;
      geometry = init_geom_surf(rep_reference_mapping, isurf, marker, eo, tan);
      geometry->area = rep_reference_mapping->get_active_element()->get_area();
      geometry->diam = rep_reference_mapping->get_active_element()->get_diameter();
      jacobian_x_weights = new double[np];
      for (int i = 0; i < np; i++)
        jacobian_x_weights[i] = pt[i][2] * tan[i][2];
      order = eo;
      return np;
    }
示例#3
0
double DiscontinuityDetector::calculate_relative_flow_direction(Element* e, int edge_i)
{
  // Set active element to the two solutions (density_vel_x, density_vel_y).
  solutions[1]->set_active_element(e);
  solutions[2]->set_active_element(e);

  // Set Geometry.
  SurfPos surf_pos;
  surf_pos.marker = e->marker;
  surf_pos.surf_num = edge_i;

  int eo = solutions[1]->get_quad_2d()->get_edge_points(surf_pos.surf_num, 5);
  double3* pt = solutions[1]->get_quad_2d()->get_points(eo);
  int np = solutions[1]->get_quad_2d()->get_num_points(eo);

  Geom<double>* geom = init_geom_surf(solutions[1]->get_refmap(), &surf_pos, eo);
  double3* tan = solutions[1]->get_refmap()->get_tangent(surf_pos.surf_num, eo);
  double* jwt = new double[np];
  for(int i = 0; i < np; i++)
      jwt[i] = pt[i][2] * tan[i][2];
 
  // Calculate.
  Func<scalar>* density_vel_x = init_fn(solutions[1], eo);
  Func<scalar>* density_vel_y = init_fn(solutions[2], eo);

  double result = 0.0;
  for(int point_i = 0; point_i < np; point_i++)
    result += jwt[point_i] * density_vel_x->val[point_i] * geom->nx[point_i] + density_vel_y->val[point_i] * geom->ny[point_i];

  return result;
};
示例#4
0
// Actual evaluation of surface linear form (calculates integral)
scalar FeProblem::eval_form(WeakForm::VectorFormSurf *vfs, Tuple<Solution *> u_ext, PrecalcShapeset *fv, RefMap *rv, EdgePos* ep)
{
  // eval the form
  Quad2D* quad = fv->get_quad_2d();
  int eo = quad->get_edge_points(ep->edge);
  double3* pt = quad->get_points(eo);
  int np = quad->get_num_points(eo);

  // init geometry and jacobian*weights
  if (cache_e[eo] == NULL)
  {
    cache_e[eo] = init_geom_surf(rv, ep, eo);
    double3* tan = rv->get_tangent(ep->edge);
    cache_jwt[eo] = new double[np];
    for(int i = 0; i < np; i++)
      cache_jwt[eo][i] = pt[i][2] * tan[i][2];
  }
  Geom<double>* e = cache_e[eo];
  double* jwt = cache_jwt[eo];

  // function values and values of external functions
  AUTOLA_OR(Func<scalar>*, prev, wf->neq);
  for (int i = 0; i < wf->neq; i++) prev[i]  = init_fn(u_ext[i], rv, eo);
  Func<double>* v = get_fn(fv, rv, eo);
  ExtData<scalar>* ext = init_ext_fns(vfs->ext, rv, eo);

  scalar res = vfs->fn(np, jwt, prev, v, e, ext);

  for (int i = 0; i < wf->neq; i++) {  prev[i]->free_fn(); delete prev[i]; }
  ext->free(); delete ext;
  return 0.5 * res;
}
示例#5
0
double KellyTypeAdapt::eval_boundary_estimator(KellyTypeAdapt::ErrorEstimatorForm* err_est_form, RefMap *rm, SurfPos* surf_pos)
{
  // determine the integration order
  int inc = (this->sln[err_est_form->i]->get_num_components() == 2) ? 1 : 0;
  Func<Ord>** oi = new Func<Ord>* [num];
  for (int i = 0; i < num; i++)
    oi[i] = init_fn_ord(this->sln[i]->get_edge_fn_order(surf_pos->surf_num) + inc);

  // Order of additional external functions.
  ExtData<Ord>* fake_ext = dp.init_ext_fns_ord(err_est_form->ext, surf_pos->surf_num);

  double fake_wt = 1.0;
  Geom<Ord>* fake_e = init_geom_ord();
  Ord o = err_est_form->ord(1, &fake_wt, oi, oi[err_est_form->i], fake_e, fake_ext);
  int order = rm->get_inv_ref_order();
  order += o.get_order();

  limit_order(order);

  // Clean up.
  for (int i = 0; i < this->num; i++)
    if (oi[i] != NULL) { oi[i]->free_ord(); delete oi[i]; }
  delete [] oi;
  delete fake_e;
  delete fake_ext;

  // eval the form
  Quad2D* quad = this->sln[err_est_form->i]->get_quad_2d();
  int eo = quad->get_edge_points(surf_pos->surf_num, order);
  double3* pt = quad->get_points(eo);
  int np = quad->get_num_points(eo);

  // init geometry and jacobian*weights
  Geom<double>* e = init_geom_surf(rm, surf_pos, eo);
  double3* tan = rm->get_tangent(surf_pos->surf_num, eo);
  double* jwt = new double[np];
  for(int i = 0; i < np; i++)
    jwt[i] = pt[i][2] * tan[i][2];

  // function values
  Func<scalar>** ui = new Func<scalar>* [num];
  for (int i = 0; i < num; i++)
    ui[i] = init_fn(this->sln[i], eo);
  ExtData<scalar>* ext = dp.init_ext_fns(err_est_form->ext, rm, eo);

  scalar res = boundary_scaling_const *
                err_est_form->value(np, jwt, ui, ui[err_est_form->i], e, ext);

  for (int i = 0; i < this->num; i++)
    if (ui[i] != NULL) { ui[i]->free_fn(); delete ui[i]; }
  delete [] ui;
  if (ext != NULL) { ext->free(); delete ext; }
  e->free(); delete e;
  delete [] jwt;

  return std::abs(0.5*res);   // Edges are parameterized from 0 to 1 while integration weights
                              // are defined in (-1, 1). Thus multiplying with 0.5 to correct
                              // the weights.
}
示例#6
0
double DiscontinuityDetector::calculate_jumps(Element* e, int edge_i)
{
  // Set active element to the solutions.
  solutions[0]->set_active_element(e);
  solutions[1]->set_active_element(e);
  solutions[2]->set_active_element(e);
  solutions[3]->set_active_element(e);

  // Set Geometry.
  SurfPos surf_pos;
  surf_pos.marker = e->marker;
  surf_pos.surf_num = edge_i;

  int eo = solutions[0]->get_quad_2d()->get_edge_points(surf_pos.surf_num, 5);
  double3* pt = solutions[0]->get_quad_2d()->get_points(eo);
  int np = solutions[0]->get_quad_2d()->get_num_points(eo);

  Geom<double>* geom = init_geom_surf(solutions[0]->get_refmap(), &surf_pos, eo);
  double3* tan = solutions[0]->get_refmap()->get_tangent(surf_pos.surf_num, eo);
  double* jwt = new double[np];
  for(int i = 0; i < np; i++)
      jwt[i] = pt[i][2] * tan[i][2];
 
  // Prepare functions on the central element.
  Func<scalar>* density = init_fn(solutions[0], eo);
  Func<scalar>* density_vel_x = init_fn(solutions[1], eo);
  Func<scalar>* density_vel_y = init_fn(solutions[2], eo);
  Func<scalar>* density_energy = init_fn(solutions[3], eo);

  // Set neighbor element to the solutions.
  solutions[0]->set_active_element(e->get_neighbor(edge_i));
  solutions[1]->set_active_element(e->get_neighbor(edge_i));
  solutions[2]->set_active_element(e->get_neighbor(edge_i));
  solutions[3]->set_active_element(e->get_neighbor(edge_i));

  // Prepare functions on the neighbor element.
  Func<scalar>* density_neighbor = init_fn(solutions[0], eo);
  Func<scalar>* density_vel_x_neighbor = init_fn(solutions[1], eo);
  Func<scalar>* density_vel_y_neighbor = init_fn(solutions[2], eo);
  Func<scalar>* density_energy_neighbor = init_fn(solutions[3], eo);

  DiscontinuousFunc<scalar> density_discontinuous(density, density_neighbor, true);
  DiscontinuousFunc<scalar> density_vel_x_discontinuous(density_vel_x, density_vel_x_neighbor, true);
  DiscontinuousFunc<scalar> density_vel_y_discontinuous(density_vel_y, density_vel_y_neighbor, true);
  DiscontinuousFunc<scalar> density_energy_discontinuous(density_energy, density_energy_neighbor, true);

  double result = 0.0;
  for(int point_i = 0; point_i < np; point_i++)
    result += jwt[point_i] * (
    std::pow(density_discontinuous.get_val_central(point_i) - density_discontinuous.get_val_neighbor(point_i), 2) + 
    std::pow(density_vel_x_discontinuous.get_val_central(point_i) - density_vel_x_discontinuous.get_val_neighbor(point_i), 2) + 
    std::pow(density_vel_y_discontinuous.get_val_central(point_i) - density_vel_y_discontinuous.get_val_neighbor(point_i), 2) + 
    std::pow(density_energy_discontinuous.get_val_central(point_i) - density_energy_discontinuous.get_val_neighbor(point_i), 2));

  return std::sqrt(result);
};
示例#7
0
    int init_surface_geometry_points_allocated_jwt(RefMap* rep_reference_mapping, int& order, int isurf, int marker, Geom<double>*& geometry, double* jacobian_x_weights)
    {
      Element* e = rep_reference_mapping->get_active_element();
      int eo = rep_reference_mapping->get_quad_2d()->get_edge_points(isurf, order, e->get_mode());
      double3* pt = rep_reference_mapping->get_quad_2d()->get_points(eo, e->get_mode());
      int np = rep_reference_mapping->get_quad_2d()->get_num_points(eo, e->get_mode());

      // Init geometry and jacobian*weights.
      double3* tan;
      geometry = init_geom_surf(rep_reference_mapping, isurf, marker, eo, tan);
      for (int i = 0; i < np; i++)
        jacobian_x_weights[i] = pt[i][2] * tan[i][2];
      order = eo;
      return np;
    }
示例#8
0
double KellyTypeAdapt::eval_interface_estimator(KellyTypeAdapt::ErrorEstimatorForm* err_est_form,
                                                RefMap *rm, SurfPos* surf_pos,
                                                LightArray<NeighborSearch*>& neighbor_searches, int neighbor_index)
{
  NeighborSearch* nbs = neighbor_searches.get(neighbor_index);
  Hermes::vector<MeshFunction*> slns;
  for (int i = 0; i < num; i++)
    slns.push_back(this->sln[i]);
  
  // Determine integration order.
  ExtData<Ord>* fake_ui = dp.init_ext_fns_ord(slns, neighbor_searches);
  
  // Order of additional external functions.
  // ExtData<Ord>* fake_ext = dp.init_ext_fns_ord(err_est_form->ext, nbs);

  // Order of geometric attributes (eg. for multiplication of a solution with coordinates, normals, etc.).
  Geom<Ord>* fake_e = new InterfaceGeom<Ord>(init_geom_ord(), nbs->neighb_el->marker, nbs->neighb_el->id, nbs->neighb_el->get_diameter());
  double fake_wt = 1.0;
  Ord o = err_est_form->ord(1, &fake_wt, fake_ui->fn, fake_ui->fn[err_est_form->i], fake_e, NULL);

  int order = rm->get_inv_ref_order();
  order += o.get_order();

  limit_order(order);

  // Clean up.
  if (fake_ui != NULL)
  {
    for (int i = 0; i < num; i++)
      delete fake_ui->fn[i];
    fake_ui->free_ord();
    delete fake_ui;
  }
  
  delete fake_e;
  
  //delete fake_ext;
  
  Quad2D* quad = this->sln[err_est_form->i]->get_quad_2d();
  int eo = quad->get_edge_points(surf_pos->surf_num, order);
  int np = quad->get_num_points(eo);
  double3* pt = quad->get_points(eo);
  
  // Init geometry and jacobian*weights (do not use the NeighborSearch caching mechanism).
  double3* tan = rm->get_tangent(surf_pos->surf_num, eo);
  double* jwt = new double[np];
  for(int i = 0; i < np; i++)
    jwt[i] = pt[i][2] * tan[i][2];
  
  Geom<double>* e = new InterfaceGeom<double>(init_geom_surf(rm, surf_pos, eo), 
                                              nbs->neighb_el->marker, 
                                              nbs->neighb_el->id, 
                                              nbs->neighb_el->get_diameter());
    
  // function values
  ExtData<scalar>* ui = dp.init_ext_fns(slns, neighbor_searches, order);
  //ExtData<scalar>* ext = dp.init_ext_fns(err_est_form->ext, nbs);

  scalar res = interface_scaling_const *
                err_est_form->value(np, jwt, ui->fn, ui->fn[err_est_form->i], e, NULL);

  if (ui != NULL) { ui->free(); delete ui; }
  //if (ext != NULL) { ext->free(); delete ext; }
  e->free(); delete e;
  delete [] jwt;

  return std::abs(0.5*res);   // Edges are parameterized from 0 to 1 while integration weights
                              // are defined in (-1, 1). Thus multiplying with 0.5 to correct
                              // the weights.
}
示例#9
0
    void Element::calc_area(bool precise_for_curvature)
    {
      // First some basic arithmetics.
      double ax, ay, bx, by;
      ax = vn[1]->x - vn[0]->x;
      ay = vn[1]->y - vn[0]->y;
      bx = vn[2]->x - vn[0]->x;
      by = vn[2]->y - vn[0]->y;

      this->area = 0.5*(ax*by - ay*bx);
      if (is_quad())
      {
        ax = bx; ay = by;
        bx = vn[3]->x - vn[0]->x;
        by = vn[3]->y - vn[0]->y;

        this->area = area + 0.5*(ax*by - ay*bx);
      }

      // Either the basic approximation is fine.
      if (!this->is_curved() || !precise_for_curvature)
        return;
      // Or we want to capture the curvature precisely.
      else
      {
        // Utility data.
        RefMap refmap_curv;
        RefMap refmap_straight;
        double3* tan;

        double x_center, y_center;
        this->get_center(x_center, y_center);

        for (int isurf = 0; isurf < this->nvert; isurf++)
        {
          // 0 - prepare data structures.
          int eo = g_quad_2d_std.get_edge_points(isurf, this->get_mode() == HERMES_MODE_TRIANGLE ? g_max_tri : g_max_quad, this->get_mode());
          int np = g_quad_2d_std.get_num_points(eo, this->get_mode());
          double* x_curv = new double[np];
          double* y_curv = new double[np];
          double* x_straight = new double[np];
          double* y_straight = new double[np];

          // 1 - get the x,y coordinates for the curved element.
          refmap_curv.set_active_element(this);
          Geom<double>* geometry = init_geom_surf(&refmap_curv, isurf, this->en[isurf]->marker, eo, tan);
          memcpy(x_curv, geometry->x, np*sizeof(double));
          memcpy(y_curv, geometry->y, np*sizeof(double));
          geometry->free();
          delete geometry;

          // 2. - act if there was no curvature
          CurvMap* cm_temp = this->cm;
          this->cm = nullptr;
          refmap_straight.set_active_element(this);
          geometry = init_geom_surf(&refmap_straight, isurf, this->en[isurf]->marker, eo, tan);
          memcpy(x_straight, geometry->x, np*sizeof(double));
          memcpy(y_straight, geometry->y, np*sizeof(double));
          geometry->free();
          delete geometry;

          // 3. - compare the two, get the updated area.
          double previous_distance;
          for (int i = 0; i < np; i++)
          {
            // Distance between the curved and straight edges.
            double distance_i = std::sqrt(std::pow(x_straight[i] - x_curv[i], 2.0) + std::pow(y_straight[i] - y_curv[i], 2.0));

            // Add to- or Subtract from- the area (depends on the curvature and we shall decide based on distance from the element center).
            double distance_from_center_curved = std::pow(x_center - x_curv[i], 2.0) + std::pow(y_center - y_curv[i], 2.0);
            double distance_from_center_straight = std::pow(x_center - x_straight[i], 2.0) + std::pow(y_center - y_straight[i], 2.0);
            bool add = distance_from_center_curved > distance_from_center_straight;

            // Calculate now the area delta.
            // It depends on the integration point number etc.
            double area_delta;
            if (i == 0)
            {
              double distance_along_edge = std::sqrt(std::pow(x_straight[i] - this->vn[isurf]->x, 2.0) + std::pow(y_straight[i] - this->vn[isurf]->y, 2.0));
              area_delta = distance_i * distance_along_edge * 0.5;
            }
            if (i > 0 && i < np - 1)
            {
              double distance_along_edge = std::sqrt(std::pow(x_straight[i] - x_straight[i - 1], 2.0) + std::pow(y_straight[i] - y_straight[i - 1], 2.0));
              area_delta = 0.5*(distance_i + previous_distance) * distance_along_edge;
            }
            if (i == np - 1)
            {
              double distance_along_edge = std::sqrt(std::pow(x_straight[i] - this->vn[(isurf + 1) % this->nvert]->x, 2.0) + std::pow(y_straight[i] - this->vn[(isurf + 1) % this->nvert]->y, 2.0));
              area_delta = distance_i * distance_along_edge * 0.5;
            }

            if (add)
              area += area_delta;
            else
              area -= area_delta;

            previous_distance = distance_i;
          }

          // 4. - re-add the curvature.
          this->cm = cm_temp;

          // clean up
          delete[] x_curv;
          delete[] y_curv;
          delete[] x_straight;
          delete[] y_straight;
        }
      }
    }