Ejemplo n.º 1
0
DiscontinuousFunc<scalar>* NeighborSearch::init_ext_fn(MeshFunction* fu)
{
  ensure_active_segment(this);
  ensure_set_quad_order(central_quad);
  ensure_set_quad_order(neighb_quad);

  if(fu->get_active_element() != central_el) {
    // Just in case - the input function should have the active element set to the central element from get_next_state
    // called in the assembling procedure.
    fu->set_active_element(central_el);
    fu->set_transform(original_central_el_transform);
  }

  if (neighborhood_type == H2D_DG_GO_DOWN)
    // Shrink the bigger central element to match the smaller neighbor (shrinks the active edge to the active segment).
    for(int i = 0; i < n_trans[active_segment]; i++)
      fu->push_transform(transformations[active_segment][i]);

  Func<scalar>* fn_central = init_fn(fu, fu->get_refmap(), get_quad_eo(false));

  // Change the active element of the function. Note that this also resets the transformations on the function.
  fu->set_active_element(neighb_el);

  if (neighborhood_type == H2D_DG_GO_UP)
    // Shrink the bigger neighbor to match the smaller central element.
    for(int i = 0; i < n_trans[active_segment]; i++)
      fu->push_transform(transformations[active_segment][i]);

  Func<scalar>* fn_neighbor = init_fn(fu, fu->get_refmap(), get_quad_eo(true));

  // Restore the original function.
  fu->set_active_element(central_el);
  fu->set_transform(original_central_el_transform);

  return new DiscontinuousFunc<scalar>(fn_central, fn_neighbor, (neighbor_edges[active_segment].orientation == 1));

  //NOTE: This function is not very efficient, since it sets the active elements and possibly pushes transformations
  // for each mesh function in each cycle of the innermost assembly loop. This is neccessary because only in
  // this innermost cycle (in function DiscreteProblem::eval_form), we know the quadrature order (dependent on
  // the actual basis and test function), which is needed for creating the Func<scalar> objects via init_fn.
  // The reason for storing the central and neighbor values of any given function in these objects is that otherwise
  // we would have to have one independent copy of the function for each of the neighboring elements. However, it
  // could unify the way PrecalcShapesets and MeshFunctions are treated in NeighborSearch and maybe these additional
  // deep memory copying, performed only after setting the active edge part (before the nested loops over basis and
  // test functions), would be actually more efficient than this. This would require implementing copy for Filters.
}
Ejemplo n.º 2
0
double* NeighborSearch::init_jwt(double** ext_cache_jwt)
{
  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_jwt[eo] == NULL) {
      int np = get_quad_np();
      double3* pt = get_quad_pt();
      double3* tan = central_rm->get_tangent(active_edge, eo);
      
      ext_cache_jwt[eo] = new double[np];
      for(int i = 0; i < np; i++)
        ext_cache_jwt[eo][i] = pt[i][2] * tan[i][2];
    }
    return ext_cache_jwt[eo];
  }
  else  // go-down neighborhood
  {
    // Also take into account the transformations of the central element.
    Key key(eo, active_segment);
    if (cache_jwt[key] == NULL) {
      int np = get_quad_np();
      double3* pt = get_quad_pt();
      double3* tan = central_rm->get_tangent(active_edge, eo);
      
      cache_jwt[key] = new double[np];
      for(int i = 0; i < np; i++)
        cache_jwt[key][i] = pt[i][2] * tan[i][2];
    }
    return cache_jwt[key];
  }
}