Beispiel #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];
  }    
}
Beispiel #2
0
DiscontinuousFunc<Ord>* NeighborSearch::init_ext_fn_ord(MeshFunction* fu)
{
  ensure_active_segment(this);
  Func<Ord>* fo1 = init_fn_ord(fu->get_edge_fn_order(active_edge));
  Func<Ord>* fo2 = init_fn_ord(fu->get_edge_fn_order(active_edge));
  return new DiscontinuousFunc<Ord>(fo1, fo2);
}
Beispiel #3
0
double* NeighborSearch::init_jwt(double** ext_cache_jwt)
{
  ensure_active_segment(this);
  ensure_central_rm(this);

  int eo = get_quad_eo();

  // Do not use the cache at all.
  if (ext_cache_jwt == NULL)
    return calculate_jwt(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)
      ext_cache_jwt[eo] = calculate_jwt(eo);
    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)
      cache_jwt[key] = calculate_jwt(eo);
    return cache_jwt[key];
  }
}
Beispiel #4
0
DiscontinuousFunc<Ord>* NeighborSearch::init_ext_fn_ord(Solution* fu)
{   
  ensure_active_segment(this);
  int inc = (fu->get_num_components() == 2) ? 1 : 0;
  int central_order = fu->get_edge_fn_order(active_edge) + inc;
  int neighbor_order = fu->get_edge_fn_order(neighbor_edge) + inc;
  return new DiscontinuousFunc<Ord>(init_fn_ord(central_order), init_fn_ord(neighbor_order));
}
Beispiel #5
0
void NeighborSearch::set_quad_order(int order)
{
  ensure_active_segment(this);
  
  quad->set_mode(central_el->get_mode());
  central_quad.init(quad, quad->get_edge_points(active_edge, order));
  quad->set_mode(neighb_el->get_mode());
  neighb_quad.init(quad, quad->get_edge_points(neighbor_edge, order));
}
Beispiel #6
0
int NeighborSearch::create_extended_shapeset(Space *space, AsmList* al)
{
  ensure_central_pss_rm(this);
  ensure_active_segment(this);
    
  if (supported_shapes == NULL) 
    supported_shapes = new ExtendedShapeset(this, al, space);
  else
    supported_shapes->update(this, space);
  
  return supported_shapes->cnt;
}
Beispiel #7
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.
}
Beispiel #8
0
void NeighborSearch::ExtendedShapeset::ExtendedShapeFunction::activate(int index, AsmList* central_al, AsmList* neighb_al)
{
  ensure_active_segment(neibhood);
  ensure_central_pss_rm(neibhood);
  assert_msg(neibhood->neighb_pss != NULL, "Cannot activate extended shape function."
                                           "PrecalcShapeset for neighbor has not been set."  );
  assert_msg(index >= 0, "Wrong shape function index.");
  
  if (index >= central_al->cnt) 
  {
    // Active shape is nonzero on the neighbor element
    support_on_neighbor = true;
    
    active_pss = neibhood->neighb_pss;
    active_rm = neibhood->neighb_rm;
    
    // AsmList entries for the active shape, taken from neighbor.
    int idx_loc = index - central_al->cnt;
    idx = neighb_al->idx[idx_loc];
    dof = neighb_al->dof[idx_loc];
    coef = neighb_al->coef[idx_loc];
  } 
  else
  {
    // Active shape is nonzero on the central element
    support_on_neighbor = false;
    
    active_pss = neibhood->central_pss;
    active_rm = neibhood->central_rm;
    
    // AsmList entries for the active shape, taken from central.
    idx = central_al->idx[index];
    dof = central_al->dof[index];
    coef = central_al->coef[index];
  }
  
  active_pss->set_active_shape(idx);
  reverse_neighbor_side = (neibhood->neighbor_edges[neibhood->active_segment].orientation == 1);
  order = active_pss->get_edge_fn_order(neibhood->active_edge);
}
Beispiel #9
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];
  }
}
Beispiel #10
0
bool NeighborSearch::set_active_segment(int neighbor, bool with_neighbor_pss)
{
  ensure_active_edge(this);
  
  active_segment = neighbor; 
  ensure_active_segment(this);
  
  neighb_el = neighbors[active_segment];
  neighbor_edge = neighbor_edges[active_segment].local_num_of_edge;
  
  // TODO: If two spaces share one mesh, can this cause troubles (if the parameter
  // ignore_visited_segments is forgotten??
  if (neighb_el->visited && ignore_visited_segments)
    return false;
 
  if(central_pss != NULL) {
    ensure_central_pss_rm(this);
    
    // Reset the transformation of the pss on central element.
    if(central_pss->get_transform() != original_central_el_transform)
      central_pss->set_transform(original_central_el_transform);
    
    // Push the central element's transformation to the central pss and refmap.
    if (neighborhood_type == H2D_DG_GO_DOWN)
      for(int i = 0; i < n_trans[active_segment]; i++)
        central_pss->push_transform(transformations[active_segment][i]);
    
    central_rm->force_transform(central_pss->get_transform(), central_pss->get_ctm()); 
  }  
  
  if (with_neighbor_pss) // If the extended shapeset is needed...
  { 
    if (neighb_pss == NULL) // Create the neighbor objects for the first time.
    {
      neighb_pss = new PrecalcShapeset(central_pss->get_shapeset());
      neighb_pss->set_quad_2d(quad);
      neighb_rm = new RefMap();
      neighb_rm->set_quad_2d(quad);
    }
    
    // Set active element for the neighbor objects or update it in the case of a go-down neighborhood.
    neighb_pss->set_active_element(neighb_el);
    neighb_rm->set_active_element(neighb_el);
    // Reset the transformation on the neighbor (this has an effect only when the active edge is changed
    // and the previous one defined a go-up neighborhood).
    neighb_pss->reset_transform();
    neighb_rm->reset_transform();
    neighb_pss->set_active_shape(central_pss->get_active_shape());
    
    // Push the neighbor element's transformations in the case of a go-up neighborhood.
    if (neighborhood_type == H2D_DG_GO_UP) {
      for(int i = 0; i < n_trans[active_segment]; i++)        
        neighb_pss->push_transform(transformations[active_segment][i]);
      neighb_rm->force_transform(neighb_pss->get_transform(), neighb_pss->get_ctm());
    }
  }
  /*
  if (neighb_el->visited)
    debug_log("%d | %d skipped.\n", central_el->id, neighb_el->id);
  */
  return true;
}