16 #include "neighbor_search.h"
23 template<
typename Scalar>
25 supported_shapes(nullptr),
30 central_transformations_size(0),
31 neighbor_transformations_size(0),
32 central_transformations_alloc_size(H2D_INITIAL_NEIGHBOR_NUMBER_GUESS),
33 neighbor_transformations_alloc_size(H2D_INITIAL_NEIGHBOR_NUMBER_GUESS)
36 throw Exceptions::Exception(
"You must pass an active element to the NeighborSearch constructor.");
38 neighbor_edges.reserve(2);
45 neighborhood_type = H2D_DG_NOT_INITIALIZED;
49 template<
typename Scalar>
51 supported_shapes(nullptr),
53 central_el(ns.central_el),
55 neighbor_edge(ns.neighbor_edge),
56 active_segment(ns.active_segment)
59 neighbor_edges.reserve(2);
61 central_transformations = calloc_with_check<NeighborSearch<Scalar>, Transformations*>(ns.central_transformations_alloc_size,
this);
62 neighbor_transformations = calloc_with_check<NeighborSearch<Scalar>, Transformations*>(ns.neighbor_transformations_alloc_size,
this);
64 for (
unsigned int j = 0; j < ns.central_transformations_alloc_size; j++)
70 this->central_transformations_size = ns.central_transformations_size;
71 this->central_transformations_alloc_size = ns.central_transformations_alloc_size;
73 for (
unsigned int j = 0; j < ns.neighbor_transformations_alloc_size; j++)
79 this->neighbor_transformations_size = ns.neighbor_transformations_size;
80 this->neighbor_transformations_alloc_size = ns.neighbor_transformations_alloc_size;
83 throw Exceptions::Exception(
"You must pass an active element to the NeighborSearch constructor.");
85 for (
unsigned int i = 0; i < ns.neighbors.size(); i++)
86 this->neighbors.push_back(ns.neighbors[i]);
87 for (
unsigned int i = 0; i < ns.neighbor_edges.size(); i++)
88 this->neighbor_edges.push_back(ns.neighbor_edges[i]);
91 n_neighbors = ns.n_neighbors;
92 neighborhood_type = ns.neighborhood_type;
94 quad = (&g_quad_2d_std);
95 active_edge = ns.active_edge;
98 template<
typename Scalar>
104 template<
typename Scalar>
107 neighbor_edges.clear();
109 clear_supported_shapes();
111 for (
unsigned int i = 0; i < central_transformations_alloc_size; i++)
112 if (this->central_transformations[i])
113 delete this->central_transformations[i];
114 free_with_check(this->central_transformations);
115 for (
unsigned int i = 0; i < neighbor_transformations_alloc_size; i++)
116 if (this->neighbor_transformations[i])
117 delete this->neighbor_transformations[i];
118 free_with_check(this->neighbor_transformations);
121 template<
typename Scalar>
127 template<
typename Scalar>
133 template<
typename Scalar>
136 if (supported_shapes !=
nullptr)
137 delete supported_shapes;
138 supported_shapes =
nullptr;
141 template<
typename Scalar>
144 this->ignore_errors = value;
147 template<
typename Scalar>
151 for (
unsigned int i = 0; i < this->central_transformations_alloc_size; i++)
153 if (this->central_transformations[i])
154 this->central_transformations[i]->reset();
156 for (
unsigned int i = 0; i < this->neighbor_transformations_alloc_size; i++)
158 if (this->neighbor_transformations[i])
159 this->neighbor_transformations[i]->reset();
166 neighbor_edge.local_num_of_edge = 0;
169 neighbor_edges.clear();
173 neighborhood_type = H2D_DG_NOT_INITIALIZED;
176 template<
typename Scalar>
182 if (!this->ignore_errors && central_el->en[active_edge]->bnd == 1)
183 throw Hermes::Exceptions::Exception(
"The given edge isn't inner");
186 neighb_el = central_el->get_neighbor(active_edge);
189 if (neighb_el !=
nullptr)
194 for (
unsigned int j = 0; j < neighb_el->get_nvert(); j++)
196 if (central_el->en[active_edge] == neighb_el->en[j])
198 neighbor_edge.local_num_of_edge = j;
207 int p1 = central_el->vn[active_edge]->id;
208 int p2 = central_el->vn[(active_edge + 1) % central_el->get_nvert()]->id;
209 local_edge_info.
orientation = neighbor_edge_orientation(p1, p2,
false);
211 neighbor_edges.push_back(local_edge_info);
215 neighbors.push_back(neighb_el);
218 neighborhood_type = H2D_DG_NO_TRANSF;
223 Node* vertex = mesh->peek_vertex_node(central_el->en[active_edge]->p1, central_el->en[active_edge]->p2);
226 int orig_vertex_id[2];
227 orig_vertex_id[0] = central_el->vn[active_edge]->
id;
228 orig_vertex_id[1] = central_el->vn[(active_edge + 1) % central_el->get_nvert()]->id;
230 if (vertex ==
nullptr)
232 neighborhood_type = H2D_DG_GO_UP;
237 Node** par_mid_vertices = malloc_with_check<NeighborSearch<Scalar>,
Node*>(Transformations::max_level,
this);
241 for (
unsigned int j = 0; j < (unsigned)Transformations::max_level; j++)
242 par_mid_vertices[j] =
nullptr;
244 find_act_elem_up(parent, orig_vertex_id, par_mid_vertices, n_parents);
246 free_with_check(par_mid_vertices);
250 neighborhood_type = H2D_DG_GO_DOWN;
253 int sons[Transformations::max_level];
258 find_act_elem_down(vertex, orig_vertex_id, sons, n_sons + 1);
266 template<
typename Scalar>
269 std::vector<unsigned int> transformations = get_transforms(original_central_el_transform);
271 if (is_inter_edge(edge, transformations))
273 set_active_edge(edge);
274 update_according_to_sub_idx(transformations);
280 neighb_el = central_el;
282 assert(!neighbor_transformations[0]);
283 this->add_neighbor_transformations(
new Transformations(transformations), 0);
285 neighbor_edge.local_num_of_edge = active_edge = edge;
290 neighbor_edges.push_back(local_edge_info);
293 neighbors.push_back(neighb_el);
294 neighborhood_type = H2D_DG_NO_TRANSF;
299 template<
typename Scalar>
302 std::vector<unsigned int> transformations_backwards;
305 transformations_backwards.push_back((sub_idx - 1) & 7);
306 sub_idx = (sub_idx - 1) >> 3;
308 std::vector<unsigned int> transformations;
309 for (
unsigned int i = 0; i < transformations_backwards.size(); i++)
310 transformations.push_back(transformations_backwards[transformations_backwards.size() - 1 - i]);
312 return transformations;
315 template<
typename Scalar>
319 if (transformations.size() == 0)
323 for (
unsigned int i = 0; i < transformations.size(); i++)
324 if (central_el->get_mode() == HERMES_MODE_TRIANGLE)
326 if ((edge == 0 && (transformations[i] == 2 || transformations[i] == 3)) ||
327 (edge == 1 && (transformations[i] == 0 || transformations[i] == 3)) ||
328 (edge == 2 && (transformations[i] == 1 || transformations[i] == 3)))
334 if ((edge == 0 && (transformations[i] == 2 || transformations[i] == 3 || transformations[i] == 5)) ||
335 (edge == 1 && (transformations[i] == 0 || transformations[i] == 3 || transformations[i] == 6)) ||
336 (edge == 2 && (transformations[i] == 0 || transformations[i] == 1 || transformations[i] == 4)) ||
337 (edge == 3 && (transformations[i] == 1 || transformations[i] == 2 || transformations[i] == 7)))
343 template<
typename Scalar>
346 if (position >= this->central_transformations_alloc_size)
348 int new_alloc_size = std::min(position + 1, (
int)(position * 1.5));
349 this->central_transformations = (Transformations**)realloc(this->central_transformations, new_alloc_size *
sizeof(Transformations*));
350 memset(this->central_transformations + this->central_transformations_alloc_size, 0,
sizeof(Transformations*)* (new_alloc_size - this->central_transformations_alloc_size));
351 this->central_transformations_alloc_size = new_alloc_size;
354 if (this->central_transformations[position])
358 delete this->central_transformations[position];
359 this->central_transformations[position] = to_add;
364 this->central_transformations[position] = to_add;
365 this->central_transformations_size++;
369 template<
typename Scalar>
370 void NeighborSearch<Scalar>::add_neighbor_transformations(Transformations* to_add,
int position,
bool replace)
372 if (position >= this->neighbor_transformations_alloc_size)
374 int new_alloc_size = std::min(position + 1, (
int)(position * 1.5));
375 this->neighbor_transformations = (Transformations**)realloc(this->neighbor_transformations, new_alloc_size *
sizeof(Transformations*));
376 memset(this->neighbor_transformations + this->neighbor_transformations_alloc_size, 0,
sizeof(Transformations*)* (new_alloc_size - this->neighbor_transformations_alloc_size));
377 this->neighbor_transformations_alloc_size = new_alloc_size;
380 if (this->neighbor_transformations[position])
384 delete this->neighbor_transformations[position];
385 this->neighbor_transformations[position] = to_add;
390 this->neighbor_transformations[position] = to_add;
391 this->neighbor_transformations_size++;
395 template<
typename Scalar>
398 if (neighborhood_type == H2D_DG_NO_TRANSF && transformations.size() == 0)
401 if (neighborhood_type == H2D_DG_NO_TRANSF || neighborhood_type == H2D_DG_GO_UP)
403 if (!neighbor_transformations[0])
405 this->add_neighbor_transformations(
new Transformations(transformations), 0);
410 for (
unsigned int i = 0; i < transformations.size(); i++)
412 if (central_el->get_mode() == HERMES_MODE_TRIANGLE)
413 if ((active_edge == 0 && transformations[i] == 0) ||
414 (active_edge == 1 && transformations[i] == 1) ||
415 (active_edge == 2 && transformations[i] == 2))
416 tr->
transf[tr->
num_levels++] = (!neighbor_edge.orientation ? neighbor_edge.local_num_of_edge : (neighbor_edge.local_num_of_edge + 1) % 3);
418 tr->
transf[tr->
num_levels++] = (neighbor_edges[0].orientation ? neighbor_edge.local_num_of_edge : (neighbor_edge.local_num_of_edge + 1) % 3);
421 if ((active_edge == 0 && (transformations[i] == 0 || transformations[i] == 6)) ||
422 (active_edge == 1 && (transformations[i] == 1 || transformations[i] == 4)) ||
423 (active_edge == 2 && (transformations[i] == 2 || transformations[i] == 7)) ||
424 (active_edge == 3 && (transformations[i] == 3 || transformations[i] == 5)))
425 tr->
transf[tr->
num_levels++] = (!neighbor_edge.orientation ? neighbor_edge.local_num_of_edge : (neighbor_edge.local_num_of_edge + 1) % 4);
426 else if ((active_edge == 0 && (transformations[i] == 1 || transformations[i] == 7)) ||
427 (active_edge == 1 && (transformations[i] == 2 || transformations[i] == 5)) ||
428 (active_edge == 2 && (transformations[i] == 3 || transformations[i] == 6)) ||
429 (active_edge == 3 && (transformations[i] == 0 || transformations[i] == 4)))
430 tr->
transf[tr->
num_levels++] = (neighbor_edge.orientation ? neighbor_edge.local_num_of_edge : (neighbor_edge.local_num_of_edge + 1) % 4);
432 else handle_sub_idx_way_down(transformations);
435 template<
typename Scalar>
438 std::vector<unsigned int> neighbors_to_be_deleted;
439 std::vector<unsigned int> neighbors_not_to_be_deleted;
441 std::vector<unsigned int> updated_transformations;
442 for (
unsigned short i = 0; i < transformations.size(); i++)
444 if (!((active_edge == 0 && transformations[i] == 4) || (active_edge == 1 && transformations[i] == 7) || (active_edge == 2 && transformations[i] == 5) || (active_edge == 3 && transformations[i] == 6)))
446 if (active_edge == 0 && transformations[i] == 6)
447 updated_transformations.push_back(0);
448 else if (active_edge == 0 && transformations[i] == 7)
449 updated_transformations.push_back(1);
450 else if (active_edge == 1 && transformations[i] == 4)
451 updated_transformations.push_back(1);
452 else if (active_edge == 1 && transformations[i] == 5)
453 updated_transformations.push_back(2);
454 else if (active_edge == 2 && transformations[i] == 6)
455 updated_transformations.push_back(3);
456 else if (active_edge == 2 && transformations[i] == 7)
457 updated_transformations.push_back(2);
458 else if (active_edge == 3 && transformations[i] == 4)
459 updated_transformations.push_back(0);
460 else if (active_edge == 3 && transformations[i] == 5)
461 updated_transformations.push_back(3);
463 updated_transformations.push_back(transformations[i]);
468 for (
unsigned int neighbor_i = 0; neighbor_i < n_neighbors; neighbor_i++)
470 bool deleted =
false;
472 Transformations* current_transforms = central_transformations[neighbor_i];
474 for (
unsigned int level = 0; level < std::min((
unsigned int)updated_transformations.size(), current_transforms->
num_levels); level++)
477 if (!compatible_transformations(current_transforms->
transf[level], updated_transformations[level], active_edge))
503 neighbors_to_be_deleted.push_back(neighbor_i);
505 neighbors_not_to_be_deleted.push_back(neighbor_i);
509 if (neighbors_to_be_deleted.size() > 0)
510 for (
unsigned int neighbors_to_be_deleted_i = neighbors_to_be_deleted.size(); neighbors_to_be_deleted_i >= 1; neighbors_to_be_deleted_i--)
511 delete_neighbor(neighbors_to_be_deleted[neighbors_to_be_deleted_i - 1]);
514 template<
typename Scalar>
521 if ((a == 0 && (b == 6 || b == 4)) ||
522 (a == 1 && (b == 7 || b == 4)))
529 if ((a == 1 && (b == 4 || b == 7)) ||
530 (a == 2 && (b == 5 || b == 7)))
537 if ((a == 2 && (b == 7 || b == 5)) ||
538 (a == 3 && (b == 6 || b == 5)))
545 if ((a == 3 && (b == 5 || b == 6)) ||
546 (a == 0 && (b == 4 || b == 6)))
554 template<
typename Scalar>
557 if (neighborhood_type != H2D_DG_GO_DOWN)
560 std::vector<unsigned int> transformations = get_transforms(original_central_el_transform);
562 std::vector<unsigned int> updated_transformations;
563 for (
unsigned short i = 0; i < transformations.size(); i++)
565 if (!((active_edge == 0 && transformations[i] == 4) || (active_edge == 1 && transformations[i] == 7) || (active_edge == 2 && transformations[i] == 5) || (active_edge == 3 && transformations[i] == 6)))
567 if (active_edge == 0 && transformations[i] == 6)
568 updated_transformations.push_back(0);
569 else if (active_edge == 0 && transformations[i] == 7)
570 updated_transformations.push_back(1);
571 else if (active_edge == 1 && transformations[i] == 4)
572 updated_transformations.push_back(1);
573 else if (active_edge == 1 && transformations[i] == 5)
574 updated_transformations.push_back(2);
575 else if (active_edge == 2 && transformations[i] == 6)
576 updated_transformations.push_back(3);
577 else if (active_edge == 2 && transformations[i] == 7)
578 updated_transformations.push_back(2);
579 else if (active_edge == 3 && transformations[i] == 4)
580 updated_transformations.push_back(0);
581 else if (active_edge == 3 && transformations[i] == 5)
582 updated_transformations.push_back(3);
584 updated_transformations.push_back(transformations[i]);
589 if (updated_transformations.size() == 0)
592 for (
unsigned int i = 0; i < n_neighbors; i++)
600 while (central_transformations[i]->transf[j] == updated_transformations[j])
601 if (++j > updated_transformations.size() - 1)
603 if (j > central_transformations[i]->num_levels)
604 j = central_transformations[i]->num_levels;
606 for (
unsigned int level = central_transformations[i]->num_levels; level < updated_transformations.size(); level++)
608 if ((i >= neighbor_transformations_alloc_size) || !neighbor_transformations[i])
614 if (central_el->get_mode() == HERMES_MODE_TRIANGLE)
615 if ((active_edge == 0 && updated_transformations[level] == 0) ||
616 (active_edge == 1 && updated_transformations[level] == 1) ||
617 (active_edge == 2 && updated_transformations[level] == 2))
618 neighbor_transforms->
transf[neighbor_transforms->
num_levels++] = (!neighbor_edge.orientation ? neighbor_edge.local_num_of_edge : (neighbor_edge.local_num_of_edge + 1) % 3);
620 neighbor_transforms->
transf[neighbor_transforms->
num_levels++] = (neighbor_edge.orientation ? neighbor_edge.local_num_of_edge : (neighbor_edge.local_num_of_edge + 1) % 3);
623 if ((active_edge == 0 && (updated_transformations[level] == 0 || updated_transformations[level] == 6)) ||
624 (active_edge == 1 && (updated_transformations[level] == 1 || updated_transformations[level] == 4)) ||
625 (active_edge == 2 && (updated_transformations[level] == 2 || updated_transformations[level] == 7)) ||
626 (active_edge == 3 && (updated_transformations[level] == 3 || updated_transformations[level] == 5)))
627 neighbor_transforms->
transf[neighbor_transforms->
num_levels++] = (!neighbor_edge.orientation ? neighbor_edge.local_num_of_edge : (neighbor_edge.local_num_of_edge + 1) % 4);
628 else if ((active_edge == 0 && (updated_transformations[level] == 1 || updated_transformations[level] == 7)) ||
629 (active_edge == 1 && (updated_transformations[level] == 2 || updated_transformations[level] == 5)) ||
630 (active_edge == 2 && (updated_transformations[level] == 3 || updated_transformations[level] == 6)) ||
631 (active_edge == 3 && (updated_transformations[level] == 0 || updated_transformations[level] == 4)))
632 neighbor_transforms->
transf[neighbor_transforms->
num_levels++] = (neighbor_edge.orientation ? neighbor_edge.local_num_of_edge : (neighbor_edge.local_num_of_edge + 1) % 4);
635 central_transformations[i]->strip_initial_transformations(j);
639 template<
typename Scalar>
644 memset(shifted_trfs, 0,
max_level *
sizeof(
unsigned int));
646 for (
unsigned int k = number_of_stripped; k <
num_levels; k++)
647 shifted_trfs[k - number_of_stripped] =
transf[k];
651 num_levels -= number_of_stripped;
654 template<
typename Scalar>
657 for (
unsigned int i = position; i < n_neighbors - 1; i++)
658 if (i + 1 < this->central_transformations_alloc_size)
664 for (
unsigned int i = position; i < n_neighbors - 1; i++)
666 if ((i + 1 < this->neighbor_transformations_alloc_size) && neighbor_transformations[i + 1])
668 if (!neighbor_transformations[i])
671 neighbor_transformations[i]->copy_from(neighbor_transformations[i + 1]);
674 if ((n_neighbors - 1 < this->neighbor_transformations_alloc_size) && neighbor_transformations[n_neighbors - 1])
675 neighbor_transformations[n_neighbors - 1]->reset();
677 neighbor_edges.erase(neighbor_edges.begin() + position);
678 neighbors.erase(neighbors.begin() + position);
682 template<
typename Scalar>
685 Node* edge =
nullptr;
686 Node* vertex =
nullptr;
691 int p1 = elem->
vn[active_edge]->
id;
692 int p2 = elem->
vn[(active_edge + 1) % elem->get_nvert()]->
id;
694 int id_of_par_orient_1 = p1;
695 int id_of_par_orient_2 = p2;
698 edge = mesh->peek_edge_node(p1, p2);
702 vertex = mesh->peek_vertex_node(p1, p2);
703 if (vertex !=
nullptr)
706 par_mid_vertices[n_parents++] = vertex;
709 throw Hermes::Exceptions::Exception(
"Maximum number of intermediate parents exceeded in NeighborSearch<Scalar>::finding_act_elem_up");
711 if (par_mid_vertices[n_parents - 1]->
id != vertex->
id)
712 par_mid_vertices[n_parents++] = vertex;
718 find_act_elem_up(elem->
parent, orig_vertex_id, par_mid_vertices, n_parents);
722 for (
int i = 0; i < 2; i++)
732 for (
unsigned int j = 0; j <
neighb_el->get_nvert(); j++)
738 if (neighbor_edge.
local_num_of_edge == -1)
throw Hermes::Exceptions::Exception(
"Neighbor edge wasn't found");
742 assert(n_neighbors == 0);
744 if (n_neighbors >= this->neighbor_transformations_alloc_size || !neighbor_transformations[n_neighbors])
745 this->add_neighbor_transformations(
new Transformations, n_neighbors);
747 Transformations *neighbor_transforms = neighbor_transformations[n_neighbors];
749 neighbor_transforms->num_levels = n_parents;
753 for (
int j = n_parents - 1; j > 0; j--)
755 Node* n = mesh->peek_vertex_node(par_mid_vertices[j]->
id, p1);
758 neighbor_transforms->transf[n_parents - j - 1] = neighbor_edge.
local_num_of_edge;
759 p1 = par_mid_vertices[j]->
id;
763 if (n->id == par_mid_vertices[j - 1]->
id)
766 p2 = par_mid_vertices[j]->
id;
770 neighbor_transforms->transf[n_parents - j - 1] = neighbor_edge.
local_num_of_edge;
771 p1 = par_mid_vertices[j]->
id;
777 if (orig_vertex_id[0] == par_mid_vertices[0]->
id)
782 NeighborEdgeInfo local_edge_info;
786 local_edge_info.orientation = neighbor_edge_orientation(id_of_par_orient_1, id_of_par_orient_2,
false);
788 neighbor_edges.push_back(local_edge_info);
800 template<
typename Scalar>
801 void NeighborSearch<Scalar>::find_act_elem_down(Node* vertex,
int* bounding_verts_id,
int* sons,
unsigned int n_sons)
804 int mid_vert = vertex->id;
806 bnd_verts[0] = bounding_verts_id[0];
807 bnd_verts[1] = bounding_verts_id[1];
811 for (
int i = 0; i < 2; i++)
813 sons[n_sons - 1] = (active_edge + i) %
central_el->get_nvert();
817 Node* edge = mesh->peek_edge_node(mid_vert, bnd_verts[i]);
822 Node * n = mesh->peek_vertex_node(mid_vert, bnd_verts[i]);
824 throw Hermes::Exceptions::Exception(
"wasn't able to find middle vertex");
829 bounding_verts_id[1] = mid_vert;
831 bounding_verts_id[0] = mid_vert;
833 find_act_elem_down(n, bounding_verts_id, sons, n_sons + 1);
835 bounding_verts_id[0] = bnd_verts[0];
836 bounding_verts_id[1] = bnd_verts[1];
841 for (
int j = 0; j < 2; j++)
843 if ((edge->elem[j] !=
nullptr) && (edge->elem[j]->active == 1))
846 neighb_el = mesh->get_element(edge->elem[j]->id);
850 for (
unsigned int k = 0; k <
neighb_el->get_nvert(); k++)
857 if (neighbor_edge.
local_num_of_edge == -1)
throw Hermes::Exceptions::Exception(
"Neighbor edge wasn't found");
860 this->add_central_transformations(
new Transformations, n_neighbors);
865 for (
unsigned int k = 0; k < n_sons; k++)
867 tr->num_levels = n_sons;
869 NeighborEdgeInfo local_edge_info;
872 local_edge_info.orientation = neighbor_edge_orientation(bnd_verts[0], bnd_verts[1], i);
874 neighbor_edges.push_back(local_edge_info);
885 template<
typename Scalar>
886 bool NeighborSearch<Scalar>::neighbor_edge_orientation(
int bounding_vert1,
int bounding_vert2,
int segment)
const
905 template<
typename Scalar>
908 this->central_al =
new AsmList<Scalar>(*other.central_al);
909 this->cnt = other.cnt;
910 this->dof = other.dof;
911 this->neighbor_al =
new AsmList<Scalar>(*other.neighbor_al);
912 this->combine_assembly_lists();
915 template<
typename Scalar>
920 return new_supp_shapes;
923 template<
typename Scalar>
934 template<
typename Scalar>
937 neighb_quad_order = quad->get_edge_points(neighbor_edge.
local_num_of_edge, order, neighbors[active_segment]->get_mode());
938 central_quad_order = quad->get_edge_points(active_edge, order,
central_el->get_mode());
941 template<
typename Scalar>
945 return neighb_quad_order;
947 return central_quad_order;
950 template<
typename Scalar>
953 return this->active_segment;
956 template<
typename Scalar>
959 if (index >= n_neighbors)
960 throw Hermes::Exceptions::Exception(
"NeighborSearch<Scalar>::set_active_segment() called with an incorrect index.");
962 this->active_segment = index;
963 this->
neighb_el = this->neighbors[index];
964 this->neighbor_edge = this->neighbor_edges[index];
967 template<
typename Scalar>
973 template<
typename Scalar>
976 return this->neighbor_edge;
979 template<
typename Scalar>
988 template<
typename Scalar>
992 throw Hermes::Exceptions::Exception(
"Out of bounds of central_transformations.");
994 throw Hermes::Exceptions::Exception(
"Trying to access transformation deeper than allowed.");
998 template<
typename Scalar>
1001 if (neighbor_transformations[index] !=
nullptr)
1002 return this->neighbor_transformations[index]->num_levels;
1007 template<
typename Scalar>
1010 if (neighbor_transformations[index_1] ==
nullptr)
1011 throw Hermes::Exceptions::Exception(
"Out of bounds of neighbor_transformations.");
1013 throw Hermes::Exceptions::Exception(
"Trying to access transformation deeper than allowed.");
1014 return this->neighbor_transformations[index_1]->transf[index_2];
1017 template<
typename Scalar>
1027 if (active_segment < this->neighbor_transformations_alloc_size && neighbor_transformations[active_segment])
1028 neighbor_transformations[active_segment]->apply_on(fu);
1049 template<
typename Scalar>
1051 central_al(central_al)
1058 template<
typename Scalar>
1061 assert(central_al !=
nullptr && neighbor_al !=
nullptr);
1062 cnt = central_al->cnt + neighbor_al->cnt;
1063 dof = malloc_with_check<int>(cnt);
1064 memcpy(dof, central_al->dof,
sizeof(
int)*central_al->cnt);
1065 memcpy(dof + central_al->cnt, neighbor_al->dof,
sizeof(
int)*neighbor_al->cnt);
1068 template<
typename Scalar>
1071 free_with_check(dof);
1075 template<
typename Scalar>
1081 template<
typename Scalar>
1084 free_with_check(this->dof);
1086 combine_assembly_lists();
1089 template<
typename Scalar>
1092 return (index >= central_al->cnt);
1095 template<
typename Scalar>
1100 template<
typename Scalar>
1101 NeighborSearch<Scalar>::Transformations::Transformations(
const Transformations* t)
1106 template<
typename Scalar>
1107 void NeighborSearch<Scalar>::Transformations::operator=(
const Transformations* t)
1112 template<
typename Scalar>
1113 NeighborSearch<Scalar>::Transformations::Transformations(
const std::vector<unsigned int>& t)
1118 template<
typename Scalar>
1119 void NeighborSearch<Scalar>::Transformations::copy_from(
const std::vector<unsigned int>& t)
1121 num_levels = std::min<unsigned int>(t.size(), max_level);
1122 std::copy(t.begin(), t.begin() + num_levels, transf);
1125 template<
typename Scalar>
1126 void NeighborSearch<Scalar>::Transformations::copy_from(
const Transformations* t)
1128 num_levels = t->num_levels;
1129 memcpy(transf, t->transf, max_level *
sizeof(
unsigned int));
1132 template<
typename Scalar>
1133 void NeighborSearch<Scalar>::Transformations::copy_to(std::vector<unsigned int>* t)
1135 t->assign(transf, transf + num_levels);
1138 template<
typename Scalar>
1139 void NeighborSearch<Scalar>::Transformations::reset()
1141 memset(transf, 0, num_levels *
sizeof(
unsigned int));
1145 template<
typename Scalar>
1146 void NeighborSearch<Scalar>::Transformations::apply_on(Transformable* tr)
const
1148 for (
unsigned int i = 0; i < num_levels; i++)
1149 tr->push_transform(transf[i]);
1152 template<
typename Scalar>
1153 void NeighborSearch<Scalar>::Transformations::apply_on(
const std::vector<Transformable*>& tr)
const
1155 for (std::vector<Transformable*>::const_iterator it = tr.begin(); it != tr.end(); ++it)
1156 for (
unsigned int i = 0; i < num_levels; i++)
1157 (*it)->push_transform(transf[i]);
1160 template class HERMES_API NeighborSearch < double > ;
1161 template class HERMES_API NeighborSearch < std::complex<double> > ;
DiscontinuousFunc< Scalar > * init_ext_fn(MeshFunction< Scalar > *fu)
void set_quad_order(int order)
std::vector< unsigned int > get_transforms(uint64_t sub_idx) const
Extract transformations in the correct direction from the provided sub_idx.
void update_according_to_sub_idx(const std::vector< unsigned int > &transformations)
Update according to the subelement mapping of the central element.
ExtendedShapeset * supported_shapes
Object allowing to set/get a particular shape function from the extended.
Stores one element of a mesh.
virtual void set_active_element(Element *e)
Element * elem[2]
elements sharing the edge node
This class represents a function with jump discontinuity on an interface of two elements.
Element * neighb_el
Currently selected neighbor element (on the other side of active segment).
unsigned int get_central_n_trans(unsigned int index) const
Returns the number(depth) of the current central transformation according to the current active segme...
void set_active_segment(unsigned int index)
Sets the active segment, neighbor element, and neighbor edge accordingly.
ExtendedShapeset(NeighborSearch< Scalar > *neighborhood, AsmList< Scalar > *central_al, SpaceSharedPtr< Scalar >space)
Represents a function defined on a mesh.
Element * central_el
Central (currently assembled) element.
Used to pass the instances of Space around.
bool compatible_transformations(unsigned int a, unsigned int b, int edge) const
void set_ignore_errors(bool value)
Function that sets the variable ignore_errors. See the variable description.
NeighborEdgeInfo get_neighbor_edge() const
Returns the current active neighbor edge according to the current active segment. ...
Stores one node of a mesh.
~NeighborSearch()
Destructor.
HERMES_API Func< double > * init_fn(PrecalcShapeset *fu, RefMap *rm, const int order)
Init the shape function for the evaluation of the volumetric/surface integral (transformation of valu...
const std::vector< Element * > * get_neighbors() const
Transformations ** central_transformations
Array of transformations of the central element to each neighbor.
uint64_t original_central_el_transform
Sub-element transformation of any function that comes from the.
void delete_neighbor(unsigned int position)
In case we determine a neighbor is not correct due to a subelement mapping, we delete it...
Element * get_neighb_el() const
Returns the current neighbor element according to the current active segment.
int get_active_segment() const
Returns the current active segment.
virtual void set_transform(uint64_t idx)
Node * en[H2D_MAX_NUMBER_EDGES]
edge node pointers
NeighborSearch(Element *el, MeshSharedPtr mesh)
int local_num_of_edge
Local number of the edge on neighbor element.
int get_num_neighbors() const
~ExtendedShapeset()
Destructor.
void update(NeighborSearch *neighborhood, SpaceSharedPtr< Scalar > space)
int get_quad_eo(bool on_neighbor=false) const
bool is_inter_edge(const int &edge, const std::vector< unsigned int > &transformations) const
Gives an info if edge is an intra- or inter- element edge.
Transformations ** neighbor_transformations
Array of transformations of the neighbor to the central element (go-up).
unsigned int get_neighbor_n_trans(unsigned int index) const
Returns the number(depth) of the current neighbor transformation according to the current active segm...
ExtendedShapeset * create_extended_asmlist(SpaceSharedPtr< Scalar > space, AsmList< Scalar > *al)
void handle_sub_idx_way_down(const std::vector< unsigned int > &transformations)
Special function for handling subelement transformations in the case of more than one neighboring act...
bool set_active_edge_multimesh(const int &edge)
Enhancement of set_active_edge for multimesh assembling.
unsigned int get_neighbor_transformations(unsigned int index_1, unsigned int index_2) const
Returns the current neighbor transformations according to the current active segment.
This class characterizes a neighborhood of a given edge in terms of adjacent elements and provides me...
bool active
0 = active, no sons; 1 = inactive (refined), has sons
AsmList< Scalar > * neighbor_al
Assembly list for the currently assembled edge on the neighbor elem.
void clear_initial_sub_idx()
void clear_supported_shapes()
Frees the memory occupied by the extended shapeset.
void combine_assembly_lists()
Create assembly list for the extended shapeset by joining central and neighbor element's assembly lis...
bool orientation
Relative orientation of the neighbor edge with respect to the active edge.
Element * parent
pointer to the parent element for the current son
Node * vn[H2D_MAX_NUMBER_VERTICES]
vertex node pointers
void set_active_edge(int edge)
Structure containing all the needed information about the active edge from the neighbor's side...
unsigned int get_central_transformations(unsigned int index_1, unsigned int index_2) const
Returns the current central transformations according to the current active segment.