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]; } }
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); }
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]; } }
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)); }
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)); }
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; }
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. }
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); }
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]; } }
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; }