Flow123d  release_2.2.0-914-gf1a3a4f
inspect_elements_algorithm.cc
Go to the documentation of this file.
1 /*
2  *
3  *
4  * Created on: 29.4.2016
5  * Author: pe
6  */
7 
8 #include <unordered_set>
9 #include <boost/functional/hash.hpp>
10 
13 #include "intersection_aux.hh"
14 #include "intersection_local.hh"
15 #include "compute_intersection.hh"
16 
17 #include "system/sys_profiler.hh"
18 
19 #include "mesh/mesh.h"
20 #include "mesh/ref_element.hh"
21 #include "mesh/bih_tree.hh"
22 
23 
24 
25 template<unsigned int dimA, unsigned int dimB>
27 : mesh(mesh)
28 {}
29 
30 template<unsigned int dimA, unsigned int dimB>
31 template<unsigned int simplex_dim>
33 {
34  ASSERT(simplex_dim == element->dim());
35  arma::vec3 *field_of_points[simplex_dim+1];
36  for(unsigned int i=0; i < simplex_dim+1; i++)
37  field_of_points[i]= &(element->node[i]->point());
38  simplex.set_simplices(field_of_points);
39 }
40 
41 
42 template<unsigned int dim>
44 : IntersectionAlgorithmBase<dim,3>(input_mesh)
45 {
46 }
47 
48 template<unsigned int dim>
50 {}
51 
52 
53 
54 template<unsigned int dim>
56 {
57  START_TIMER("Intersection initialization");
59  closed_elements.assign(mesh->n_elements(), false);
61  n_intersections_ = 0;
62  END_TIMER("Intersection initialization");
63 }
64 
65 template<unsigned int dim>
67 {
68  START_TIMER("Compute bounding boxes");
69  if(elements_bb.size() == 0){
70  elements_bb.resize(mesh->n_elements());
71  bool first_3d_element = true;
72  FOR_ELEMENTS(mesh, elm) {
73 
74  elements_bb[elm->index()] = elm->bounding_box();
75 
76  if (elm->dim() == 3){
77  if(first_3d_element){
78  first_3d_element = false;
79  mesh_3D_bb = elements_bb[elm->index()];
80  }else{
81  mesh_3D_bb.expand(elements_bb[elm->index()].min());
82  mesh_3D_bb.expand(elements_bb[elm->index()].max());
83  }
84  }
85  }
86  }
87  END_TIMER("Compute bounding boxes");
88 }
89 
90 template<unsigned int dim>
91 bool InspectElementsAlgorithm<dim>::compute_initial_CI(unsigned int component_ele_idx,
92  unsigned int bulk_ele_idx)
93 {
94  IntersectionAux<dim,3> is(component_ele_idx, bulk_ele_idx);
95  START_TIMER("Compute intersection");
97  CI.init();
98  CI.compute(is);
99  END_TIMER("Compute intersection");
100 
101  last_slave_for_3D_elements[bulk_ele_idx] = component_ele_idx;
102 
103  if(is.points().size() > 0) {
104  intersection_list_[component_ele_idx].push_back(is);
106  return true;
107  }
108  else return false;
109 }
110 
111 
112 
113 
114 template<unsigned int dim>
115 bool InspectElementsAlgorithm<dim>::intersection_exists(unsigned int component_ele_idx, unsigned int bulk_ele_idx)
116 {
117  START_TIMER("intersection_exists");
118  bool found = false;
119 
120  START_TIMER("cycle");
121  unsigned int i = 0;
122  for(; i < intersection_list_[component_ele_idx].size();i++){
123 
124  if(intersection_list_[component_ele_idx][i].bulk_ele_idx() == bulk_ele_idx){
125  found = true;
126  break;
127  }
128  }
129  ADD_CALLS(i);
130  END_TIMER("cycle");
131  END_TIMER("intersection_exists");
132  return found;
133 }
134 
135 
136 template<unsigned int dim>
138 {
139  //DebugOut() << "######### ALGORITHM: compute_intersections #########\n";
140 
141  init();
142 
143  START_TIMER("Element iteration");
144 
145  FOR_ELEMENTS(mesh, elm) {
146  unsigned int component_ele_idx = elm->index();
147 
148  if (elm->dim() == dim && // is component element
149  !closed_elements[component_ele_idx] && // is not closed yet
150  bih.ele_bounding_box(component_ele_idx).intersect(bih.tree_box())) // its bounding box intersects 3D mesh bounding box
151  {
152  std::vector<unsigned int> searchedElements;
153 
154  START_TIMER("BIHtree find");
155  bih.find_bounding_box(bih.ele_bounding_box(component_ele_idx), searchedElements);
156  END_TIMER("BIHtree find");
157 
158  START_TIMER("Bounding box element iteration");
159 
160  // Go through all element which bounding box intersects the component element bounding box
161  for (std::vector<unsigned int>::iterator it = searchedElements.begin(); it!=searchedElements.end(); it++)
162  {
163  unsigned int bulk_ele_idx = *it;
164  ElementFullIter ele_3D = mesh->element(bulk_ele_idx);
165 
166  // if:
167  // check 3D only
168  // check with the last component element computed for the current 3D element
169  // intersection has not been computed already
170  if (ele_3D->dim() == 3 &&
171  (last_slave_for_3D_elements[bulk_ele_idx] != component_ele_idx &&
172  !intersection_exists(component_ele_idx,bulk_ele_idx) )
173  ) {
174  // check that tetrahedron element is numbered correctly and is not degenerated
175  ASSERT_DBG(ele_3D->tetrahedron_jacobian() > 0).add_value(ele_3D->index(),"element index").error(
176  "Tetrahedron element (%d) has wrong numbering or is degenerated (negative Jacobian).");
177 
178  // - find first intersection
179  // - if found, prolongate and possibly fill both prolongation queues
180  // do-while loop:
181  // - empty prolongation queues:
182  // - empty bulk queue:
183  // - get a candidate from queue and compute CI
184  // - prolongate and possibly push new candidates into queues
185  // - repeat until bulk queue is empty
186  // - the component element is still the same whole time in here
187  //
188  // - the component element might get fully covered by bulk elements
189  // and only then it can be closed
190  //
191  // - pop next candidate from component queue:
192  // - the component element is now changed
193  // - compute CI
194  // - prolongate and possibly push new candidates into queues
195  //
196  // - repeat until both queues are empty
197 
198  this->update_simplex(elm, simplexA); // update component simplex
199  this->update_simplex(ele_3D, simplexB); // update tetrahedron
200  bool found = compute_initial_CI(component_ele_idx,
201  bulk_ele_idx);
202 
203  // keep the index of the current component element that is being investigated
204  unsigned int current_component_element_idx = component_ele_idx;
205 
206  if(found){
207 
208  prolongation_decide(elm, ele_3D, intersection_list_[component_ele_idx].back());
209 
210  START_TIMER("Prolongation algorithm");
211  do{
212  // flag is set false if the component element is not fully covered with tetrahedrons
213  bool element_covered = true;
214 
215  while(!bulk_queue_.empty()){
216  Prolongation pr = bulk_queue_.front();
217  //DebugOut().fmt("Bulk queue: ele_idx {}.\n",pr.elm_3D_idx);
218 
219  if( pr.elm_3D_idx == undefined_elm_idx_)
220  {
221  //DebugOut().fmt("Open intersection component element: {}\n",current_component_element_idx);
222  element_covered = false;
223  }
224  else prolongate(pr);
225 
226  bulk_queue_.pop();
227  }
228 
229  if(! closed_elements[current_component_element_idx])
230  closed_elements[current_component_element_idx] = element_covered;
231 
232 
233  if(!component_queue_.empty()){
234  Prolongation pr = component_queue_.front();
235 
236  // note the component element index
237  current_component_element_idx = pr.component_elm_idx;
238  //DebugOut().fmt("Component queue: ele_idx {}.\n",current_component_element_idx);
239 
240  prolongate(pr);
241  component_queue_.pop();
242  }
243  }
244  while( !(component_queue_.empty() && bulk_queue_.empty()) );
245  END_TIMER("Prolongation algorithm");
246 
247  // if component element is closed, do not check other bounding boxes
248  if(closed_elements[component_ele_idx])
249  break;
250  }
251  }
252  }
253  END_TIMER("Bounding box element iteration");
254  }
255  }
256 
257  END_TIMER("Element iteration");
258 
259  MessageOut().fmt("{}D-3D: number of intersections = {}\n", dim, n_intersections_);
260  // DBG write which elements are closed
261 // FOR_ELEMENTS(mesh, ele) {
262 // DebugOut().fmt("Element[{}] closed: {}\n",ele.index(),(closed_elements[ele.index()] ? 1 : 0));
263 // }
264 }
265 
266 template<unsigned int dim>
268 {
269  DebugOut() << "######### ALGORITHM: compute_intersections_BIHtree #########\n";
270 
271  init();
272 
273  START_TIMER("Element iteration");
274 
275  FOR_ELEMENTS(mesh, elm) {
276  unsigned int component_ele_idx = elm->index();
277 
278  if (elm->dim() == dim && // is component element
279  bih.ele_bounding_box(component_ele_idx).intersect(bih.tree_box())) // its bounding box intersects 3D mesh bounding box
280  {
281  this->update_simplex(elm, simplexA); // update component simplex
282  std::vector<unsigned int> searchedElements;
283 
284  START_TIMER("BIHtree find");
285  bih.find_bounding_box(bih.ele_bounding_box(component_ele_idx), searchedElements);
286  END_TIMER("BIHtree find");
287 
288  START_TIMER("Bounding box element iteration");
289 
290  // Go through all element which bounding box intersects the component element bounding box
291  for (std::vector<unsigned int>::iterator it = searchedElements.begin(); it!=searchedElements.end(); it++)
292  {
293  unsigned int bulk_ele_idx = *it;
294  ElementFullIter ele_3D = mesh->element(bulk_ele_idx);
295 
296  if (ele_3D->dim() == 3
297  ) {
298  // check that tetrahedron element is numbered correctly and is not degenerated
299  ASSERT_DBG(ele_3D->tetrahedron_jacobian() > 0).add_value(ele_3D->index(),"element index").error(
300  "Tetrahedron element (%d) has wrong numbering or is degenerated (negative Jacobian).");
301 
302  this->update_simplex(ele_3D, simplexB); // update tetrahedron
303 
304  IntersectionAux<dim,3> is(component_ele_idx, bulk_ele_idx);
305  START_TIMER("Compute intersection");
307  CI.init();
308  CI.compute(is);
309  END_TIMER("Compute intersection");
310 
311  if(is.points().size() > 0) {
312 
313  intersection_list_[component_ele_idx].push_back(is);
315  // if component element is closed, do not check other bounding boxes
316  closed_elements[component_ele_idx] = true;
317  }
318  }
319  }
320  END_TIMER("Bounding box element iteration");
321  }
322  }
323 
324  END_TIMER("Element iteration");
325 }
326 
327 template<unsigned int dim>
329 {
330  //DebugOut() << "######### ALGORITHM: compute_intersections_BB #########\n";
331  init();
333 
334  START_TIMER("Element iteration");
335 
336 
337  FOR_ELEMENTS(mesh, elm) {
338  unsigned int component_ele_idx = elm->index();
339 
340  if (elm->dim() == dim && // is component element
341  !closed_elements[component_ele_idx] && // is not closed yet
342  elements_bb[component_ele_idx].intersect(mesh_3D_bb)) // its bounding box intersects 3D mesh bounding box
343  {
344 
345  START_TIMER("Bounding box element iteration");
346 
347  // Go through all element which bounding box intersects the component element bounding box
348  FOR_ELEMENTS(mesh, ele_3D)
349  {
350  unsigned int bulk_ele_idx = ele_3D.index();
351 
352  // if:
353  // check 3D only
354  // check with the last component element computed for the current 3D element
355  // check that the bounding boxes intersect
356  // intersection has not been computed already
357  if (ele_3D->dim() == 3 &&
358  (last_slave_for_3D_elements[bulk_ele_idx] != component_ele_idx &&
359  elements_bb[component_ele_idx].intersect(elements_bb[bulk_ele_idx]) &&
360  !intersection_exists(component_ele_idx,bulk_ele_idx) )
361  ){
362  // check that tetrahedron element is numbered correctly and is not degenerated
363  ASSERT_DBG(ele_3D->tetrahedron_jacobian() > 0).add_value(ele_3D->index(),"element index").error(
364  "Tetrahedron element (%d) has wrong numbering or is degenerated (negative Jacobian).");
365 
366  // - find first intersection
367  // - if found, prolongate and possibly fill both prolongation queues
368  // do-while loop:
369  // - empty prolongation queues:
370  // - empty bulk queue:
371  // - get a candidate from queue and compute CI
372  // - prolongate and possibly push new candidates into queues
373  // - repeat until bulk queue is empty
374  // - the component element is still the same whole time in here
375  //
376  // - the component element might get fully covered by bulk elements
377  // and only then it can be closed
378  //
379  // - pop next candidate from component queue:
380  // - the component element is now changed
381  // - compute CI
382  // - prolongate and possibly push new candidates into queues
383  //
384  // - repeat until both queues are empty
385 
386  this->update_simplex(elm, simplexA); // update component simplex
387  this->update_simplex(ele_3D, simplexB); // update tetrahedron
388  bool found = compute_initial_CI(component_ele_idx,
389  bulk_ele_idx);
390 
391  // keep the index of the current component element that is being investigated
392  unsigned int current_component_element_idx = component_ele_idx;
393 
394  if(found){
395  //DebugOut().fmt("start component with elements {} {}\n",component_ele_idx, bulk_ele_idx);
396 
397  prolongation_decide(elm, ele_3D, intersection_list_[component_ele_idx].back());
398 
399  START_TIMER("Prolongation algorithm");
400  do{
401  // flag is set false if the component element is not fully covered with tetrahedrons
402  bool element_covered = true;
403 
404  while(!bulk_queue_.empty()){
405  Prolongation pr = bulk_queue_.front();
406  //DebugOut().fmt("Bulk queue: ele_idx {}.\n",pr.elm_3D_idx);
407 
408  if( pr.elm_3D_idx == undefined_elm_idx_)
409  {
410  //DebugOut().fmt("Open intersection component element: {}\n",current_component_element_idx);
411  element_covered = false;
412  }
413  else prolongate(pr);
414 
415  bulk_queue_.pop();
416  }
417 
418  if(! closed_elements[current_component_element_idx])
419  closed_elements[current_component_element_idx] = element_covered;
420 
421 
422  if(!component_queue_.empty()){
423  Prolongation pr = component_queue_.front();
424 
425  // note the component element index
426  current_component_element_idx = pr.component_elm_idx;
427  //DebugOut().fmt("Component queue: ele_idx {}.\n",current_component_element_idx);
428 
429  prolongate(pr);
430  component_queue_.pop();
431  }
432  }
433  while( !(component_queue_.empty() && bulk_queue_.empty()) );
434  END_TIMER("Prolongation algorithm");
435 
436  // if component element is closed, do not check other bounding boxes
437  if(closed_elements[component_ele_idx])
438  break;
439  }
440 
441  }
442  }
443  END_TIMER("Bounding box element iteration");
444  }
445  }
446 
447  END_TIMER("Element iteration");
448 
449  // DBG write which elements are closed
450 // FOR_ELEMENTS(mesh, ele) {
451 // DebugOut().fmt("Element[{}] closed: {}\n",ele.index(),(closed_elements[ele.index()] ? 1 : 0));
452 // }
453 }
454 
455 
456 
457 template<unsigned int dim>
458 template<unsigned int ele_dim>
460  unsigned int ip_dim,
461  unsigned int ip_obj_idx)
462 {
463  std::vector<Edge*> edges;
464  edges.reserve(ele_dim - ip_dim); // reserve number of possible edges
465 
466  //DebugOut() << "dim " << ele_dim << ": ";
467  switch (ip_dim)
468  {
469  // IP is at a node of tetrahedron; possible edges are from all connected sides (3)
470  case 0: if(ele_dim == 1) {
471  edges.push_back(&(mesh->edges[ele->edge_idx_[ip_obj_idx]]));
472  break;
473  }
474 
475  for(unsigned int j=0; j < RefElement<ele_dim>::n_sides_per_node; j++){
476  unsigned int local_edge = RefElement<ele_dim>::interact(Interaction<ele_dim-1,0>(ip_obj_idx))[j];
477  edges.push_back(&(mesh->edges[ele->edge_idx_[local_edge]]));
478  }
479  //DebugOut() << "prolong (node)\n";
480  break;
481 
482  // IP is on a line of tetrahedron; possible edges are from all connected sides (2)
483  case 1: if(ele_dim == 2) {
484  edges.push_back(&(mesh->edges[ele->edge_idx_[ip_obj_idx]]));
485  break;
486  }
487 
488  ASSERT_DBG(ele_dim == 3);
489  for(unsigned int j=0; j < RefElement<ele_dim>::n_sides_per_line; j++){
490  unsigned int local_edge = RefElement<ele_dim>::interact(Interaction<2,1>(ip_obj_idx))[j];
491  edges.push_back(&(mesh->edges[ele->edge_idx_[local_edge]]));
492  }
493  //DebugOut() << "prolong (edge)\n";
494  break;
495 
496  // IP is on a side of tetrahedron; only possible edge is from the given side (1)
497  case 2: ASSERT_DBG(ele_dim == 3);
498  edges.push_back(&(mesh->edges[ele->edge_idx_[ip_obj_idx]]));
499  //DebugOut() << "prolong (side)\n";
500  break;
501  default: ASSERT_DBG(0);
502  }
503 
504  // get indices of neighboring bulk elements
505  std::vector<unsigned int> elements_idx;
506  elements_idx.reserve(2*edges.size()); // twice the number of edges
507  for(Edge* edg : edges)
508  for(int j=0; j < edg->n_sides;j++) {
509  if (edg->side(j)->element() != ele)
510  elements_idx.push_back(edg->side(j)->element()->index());
511  }
512 
513  return elements_idx;
514 }
515 
516 
517 template<unsigned int dim>
518 unsigned int InspectElementsAlgorithm<dim>::create_prolongation(unsigned int bulk_ele_idx,
519  unsigned int component_ele_idx,
520  std::queue< Prolongation >& queue)
521 {
522 // if(last_slave_for_3D_elements[bulk_ele_idx] == undefined_elm_idx_ ||
523 // (last_slave_for_3D_elements[bulk_ele_idx] != component_ele_idx && !intersection_exists(component_ele_idx,bulk_ele_idx)))
524 // {
525  last_slave_for_3D_elements[bulk_ele_idx] = component_ele_idx;
526 
527  //DebugOut().fmt("prolongation: c {} in b {}\n",component_ele_idx,bulk_ele_idx);
528 
529  // prepare empty intersection object
530  IntersectionAux<dim,3> il_other(component_ele_idx, bulk_ele_idx);
531  intersection_list_[component_ele_idx].push_back(il_other);
532 
533  Prolongation pr = {component_ele_idx, bulk_ele_idx, (unsigned int)intersection_list_[component_ele_idx].size() - 1};
534  queue.push(pr);
535 
536  return 1;
537 // }
538 // return 0;
539 }
540 
541 
542 
543 template<unsigned int dim>
545  const ElementFullIter& bulk_ele,
547 {
548  //DebugOut() << "DECIDE\n";
549  // number of IPs that are at vertices of component element (counter used for closing element)
550  unsigned int n_ip_vertices = 0;
551 
552  for(const IntersectionPointAux<dim,3> &IP : is.points()) {
553 
554  // 1) prolong over component, if IP is at its boundary
555  // 2) prolong over bulk, if IP is at its boundary
556  // both cases are possible, so both prolongations might happen at once..
557 
558  if(IP.dim_A() < dim) { // if IP on the boundary of component element
559  if(IP.dim_A() == 0) n_ip_vertices++;
560  //DebugOut() << "on " << dim << "D boundary, dim = " << IP.dim_A() << "\n";
561 
562  // search for indices of neighboring component elements (including the current one)
563  std::vector<unsigned int> comp_neighbors = get_element_neighbors<dim>(comp_ele,IP.dim_A(), IP.idx_A());
564 
565 // DBGCOUT( << comp_ele->id() << "--" << bulk_ele->id() << ": ");
566 // for(unsigned int& comp_neighbor_idx : comp_neighbors)
567 // cout << mesh->element(comp_neighbor_idx)->id() << " ";
568 // cout << "\n";
569 
570  unsigned int bulk_current = bulk_ele->index();
571 
572  // add all component neighbors with current bulk element into component queue
573  for(unsigned int& comp_neighbor_idx : comp_neighbors) {
574  if(!intersection_exists(comp_neighbor_idx,bulk_current))
575  create_prolongation(bulk_current, comp_neighbor_idx, component_queue_);
576  }
577  }
578 
579  if(IP.dim_B() < 3)
580  {
581  //DebugOut() << "on 3D boundary, dim = " << IP.dim_B() << "\n";
582 
583  // search for indices of neighboring bulk elements (including the current one)
584  std::vector<unsigned int> bulk_neighbors = get_element_neighbors<3>(bulk_ele,IP.dim_B(),IP.idx_B());
585 
586 // DBGCOUT( << comp_ele->id() << "--" << bulk_ele->id() << ": ");
587 // for(unsigned int& bulk_neighbor_idx : bulk_neighbors)
588 // cout << mesh->element(bulk_neighbor_idx)->id() << " ";
589 // cout << "\n";
590 
591  unsigned int comp_current = comp_ele->index();
592  unsigned int n_prolongations = 0;
593  // prolong over current comp element to other bulk elements (into bulk queue) (covering comp ele)
594  for(unsigned int& bulk_neighbor_idx : bulk_neighbors)
595  {
596  if(last_slave_for_3D_elements[bulk_neighbor_idx] == undefined_elm_idx_ ||
597  (last_slave_for_3D_elements[bulk_neighbor_idx] != comp_current &&
598  !intersection_exists(comp_current,bulk_neighbor_idx)))
599  n_prolongations += create_prolongation(bulk_neighbor_idx,
600  comp_current,
601  bulk_queue_);
602  }
603 
604  // if there are no sides of any edge that we can continue to prolongate over,
605  // it means we are at the boundary and cannot prolongate further
606  if(n_prolongations == 0)
607  {
609  bulk_queue_.push(pr);
610  }
611  }
612  }
613 
614  // close component element if it has all vertices inside bulk element
615  if(n_ip_vertices == is.size()) closed_elements[comp_ele->index()] = true;
616 }
617 
618 
619 
620 template<>
621 void InspectElementsAlgorithm<2>::assert_same_intersection(unsigned int comp_ele_idx, unsigned int bulk_ele_idx)
622 {
623  for(unsigned int i=0; i < intersection_list_[comp_ele_idx].size(); i++)
624  {
625  if(intersection_list_[comp_ele_idx][i].bulk_ele_idx() == bulk_ele_idx)
626  {
627  //DebugOut().fmt("intersection comp-bulk: {} {}\n", comp_ele_idx, bulk_ele_idx);
628  ASSERT_DBG(0).add_value(bulk_ele_idx,"bulk_ele_idx").error("Want to add the same intersection!");
629  }
630  }
631 }
632 
633 
634 template<unsigned int dim>
636 {
638  ElementFullIter ele_3D = mesh->element(pr.elm_3D_idx);
639 
640 // DebugOut().fmt("Prolongate: {} in {}.\n", elm->id(), ele_3D->id());
641 
642  //TODO: optimization: this might be called before and not every time
643  //(component element is not changing when emptying bulk queue)
644  this->update_simplex(elm, simplexA);
645  this->update_simplex(ele_3D, simplexB);
646 
648 
649  START_TIMER("Compute intersection");
651  CI.init();
652  CI.compute(is);
653  END_TIMER("Compute intersection");
654 
656 
657  if(is.size() > 0){
658 // for(unsigned int j=0; j < is.size(); j++)
659 // DebugOut() << is[j];
660 // DebugOut().fmt("intersection of elements {} {} [{}--{}] size {}\n",
661 // elm->id(), ele_3D->id(),
662 // elm->region().label(), ele_3D->region().label(),
663 // is.size()
664 // );
665 
666  prolongation_decide(elm, ele_3D,is);
668 // DBGVAR(n_intersections_);
669  }
670  else{
671  // NOTE: we get here, when create_prolongation creates an empty intersection
672  // - it can happen, that the CI will be empty
673  // - currently, we remove it when storing the final intersection objects
674  // - or we can erase it at this point
675 // WarningOut() << "zero is: c " << elm->index() << " b " << ele_3D.index();
676 // auto & v = intersection_list_[pr.component_elm_idx];
677 // v.erase( v.next(v.being(),pr.dictionary_idx) );
678  }
679 }
680 
681 
682 
683 
685 : IntersectionAlgorithmBase<2,2>(input_mesh)
686 {}
687 
688 
691 {
692 // DebugOut() << "Intersections 2d-2d\n";
693  ASSERT(storage.size() == 0);
695 
696  unsigned int ele_idx, eleA_idx, eleB_idx,
697  componentA_idx, componentB_idx,
698  temp_eleA_idx;
699 
700  typedef std::pair<unsigned int, unsigned int> ipair;
701  std::unordered_set<ipair, boost::hash<ipair>> computed_pairs;
702 
703  FOR_ELEMENTS(mesh, ele) {
704  if (ele->dim() == 3)
705  {
706  ele_idx = ele->index();
707  // if there are not at least 2 2D elements intersecting 3D element; continue
708  if(intersection_map[ele_idx].size() < 2) continue;
709 
710  const std::vector<ILpair> &local_map = intersection_map[ele_idx];
711 
712 // DebugOut() << print_var(local_map.size());
713  for(unsigned int i=0; i < local_map.size(); i++)
714  {
715  //TODO: 1] compute all plucker coords at once
716  //TODO: 2] pass plucker coords from 2d-3d
717 
718  eleA_idx = local_map[i].first;
719  ElementFullIter eleA = mesh->element(eleA_idx);
720  if(eleA->dim() !=2 ) continue; //skip other dimension intersection
721  componentA_idx = component_idx_[eleA_idx];
722 
723 // IntersectionLocalBase * ilb = local_map[i].second;
724 // DebugOut().fmt("2d-2d ILB: {} {} {}\n", ilb->bulk_ele_idx(), ilb->component_ele_idx(), componentA_idx);
725 
726  for(unsigned int j=i+1; j < local_map.size(); j++)
727  {
728  eleB_idx = local_map[j].first;
729  componentB_idx = component_idx_[eleB_idx];
730 
731  if(componentA_idx == componentB_idx) continue; //skip elements of the same component
732  // this also skips the compatible connections (it is still a single component in this case)
733 
734  ElementFullIter eleB = mesh->element(eleB_idx);
735  if(eleB->dim() !=2 ) continue; //skip other dimension intersection
736 
737  // set master -- slave order
738  // do not overwrite the original eleA
739  temp_eleA_idx = eleA_idx;
740  ElementFullIter temp_eleA = eleA;
741  if (componentA_idx < componentB_idx){
742  std::swap(temp_eleA_idx, eleB_idx);
743  std::swap(temp_eleA, eleB);
744  }
745 
746  //skip candidates already computed
747  ipair ip = std::make_pair(temp_eleA_idx, eleB_idx);
748  if(computed_pairs.count(ip) == 1){
749 // DBGCOUT(<< "skip: " << eleA_idx << " " << eleB_idx << "\n");
750  continue;
751  }
752  else{
753  compute_single_intersection(temp_eleA, eleB, storage);
754  computed_pairs.emplace(ip);
755  }
756 
757 // bool skip = false;
758 // for(unsigned int k=0; k<intersection_map[eleA_idx].size(); k++)
759 // {
760 // if(intersection_map[eleA_idx][k].first == eleB_idx) {
761 // skip = true;
762 // break;
763 // }
764 // }
765 // if(skip) continue;
766 
767 // DebugOut().fmt("compute intersection 2d-2d: e_{} e_{} c_{} c_{}\n",
768 // eleA.index(), eleB.index(), componentA_idx, componentB_idx);
769 // DebugOut().fmt("compute intersection 2d-2d: e_{} e_{} c_{} c_{}\n",
770 // eleA.id(), eleB.id(), componentA_idx, componentB_idx);
771 
772 // IntersectionAux<2,2> is;
773 // if (componentA_idx < componentB_idx)
774 // compute_single_intersection(eleA, eleB, storage);
775 // else
776 // compute_single_intersection(eleB, eleA, storage);
777  }
778  }
779  }
780  }
781  MessageOut() << "2D-2D: number of intersections = " << storage.size() << "\n";
782 }
783 
784 
786  const ElementFullIter& eleB,
788 {
789  ASSERT_DBG(eleA->dim() == 2);
790  ASSERT_DBG(eleB->dim() == 2);
791  ASSERT_DBG(eleA->index() != eleB->index());
792 
793  update_simplex(eleA, simplexA);
794  update_simplex(eleB, simplexB);
795 
796  IntersectionAux<2,2> is(eleA->index(), eleB->index());
797 
799  CI.init();
800  unsigned int n_local_intersection = CI.compute(is);
801 
802  // do not store point intersections
803  if(n_local_intersection > 1){
804  storage.push_back(IntersectionLocal<2,2>(is));
805  }
806 
807 }
808 
810 {
812  component_counter_ = 0;
813 
814  // prolongation queue in the component mesh.
815  std::queue<unsigned int> queue;
816 
817  FOR_ELEMENTS(mesh, ele) {
818  if (ele->dim() == 2 &&
819  component_idx_[ele->index()] == (unsigned int)-1)
820  {
821  // start component
822  queue.push(ele->index());
823 
824  while(!queue.empty()){
825  unsigned int ele_idx = queue.front();
826  queue.pop();
827  const ElementFullIter& ele = mesh->element(ele_idx);
828  for(unsigned int sid=0; sid < ele->n_sides(); sid++) {
829  Edge* edg = ele->side(sid)->edge();
830 
831  for(int j=0; j < edg->n_sides;j++) {
832  uint neigh_idx = edg->side(j)->element()->index();
833  if (component_idx_[neigh_idx] == (unsigned int)-1) {
834  component_idx_[neigh_idx] = component_counter_;
835  queue.push(neigh_idx);
836  }
837  }
838  }
839  }
841  }
842  }
843 
844  MessageOut() << "2D-2D: number of components = " << component_counter_ << "\n";
845 
846 // DBGCOUT(<< "Component numbering: \n");
847 // FOR_ELEMENTS(mesh, ele) {
848 // if (ele->dim() == 2){
849 // cout << "2d ele " << ele->index() << ": " << component_idx_[ele->index()] << endl;
850 // }
851 // }
852 }
853 
854 
855 
856 
857 
859 : IntersectionAlgorithmBase<1,2>(input_mesh)
860 {}
861 
862 
865 {
866  //DebugOut() << "Intersections 1d-2d\n";
867  ASSERT(storage.size() == 0);
868 
869  FOR_ELEMENTS(mesh, ele) {
870  if (ele->dim() == 3)
871  {
872  unsigned int ele_idx = ele->index();
873  // if there are not at least 2 elements intersecting 3D element; continue
874  if(intersection_map[ele_idx].size() < 2) continue;
875 
876  const std::vector<ILpair> &local_map = intersection_map[ele_idx];
877 
878  //DebugOut() << "more than 2 intersections in tetrahedron found\n";
879  for(unsigned int i=0; i < local_map.size(); i++)
880  {
881  //TODO: 1] compute all plucker coords at once
882  //TODO: 2] pass plucker coords from 1d-3d
883 
884  unsigned int eleA_idx = local_map[i].first;
885  ElementFullIter eleA = mesh->element(eleA_idx);
886 
887  if(eleA->dim() !=1 ) continue; //skip other dimension intersection
888 
889  for(unsigned int j=0; j < local_map.size(); j++)
890  {
891  unsigned int eleB_idx = local_map[j].first;
892  ElementFullIter eleB = mesh->element(local_map[j].first);
893  if(eleB->dim() !=2 ) continue; //skip other dimension intersection
894 
895  //skip candidates already computed
896  bool skip = false;
897  for(unsigned int i=0; i<intersection_map[eleA_idx].size(); i++)
898  {
899  if(intersection_map[eleA_idx][i].first == eleB_idx) {
900  skip = true;
901  break;
902  }
903  }
904 
905  if(skip) continue;
906 
907  //DebugOut().fmt("compute intersection 1d-2d: {} {}\n",eleA.index(), eleB.index());
908 // compute_single_intersection(eleA,
909 // eleB);
910 
911  update_simplex(eleA, simplexA);
912  update_simplex(eleB, simplexB);
913 
914  IntersectionAux<1,2> is(eleA_idx, eleB_idx);
915 
917  unsigned int n_local_intersection = CI.compute_final(is.points());
918 
919  if(n_local_intersection > 0)
920  {
921  storage.push_back(IntersectionLocal<1,2>(is));
922  intersection_map[eleA_idx].push_back(std::make_pair(
923  eleB_idx,
924  &(storage.back())
925  ));
926  intersection_map[eleB_idx].push_back(std::make_pair(
927  eleA_idx,
928  &(storage.back())
929  ));
930 
931  //DebugOut().fmt("1D-2D intersection [{} - {}]:\n",is.component_ele_idx(), is.bulk_ele_idx());
932  }
933  }
934  }
935  }
936  }
937 
938  MessageOut() << "2D-2D: number of intersections = " << storage.size() << "\n";
939  // just dbg output
940 // for(IntersectionLocal<1,2> &is : storage)
941 // {
942 // DebugOut().fmt("1D-2D intersection [{} - {}]:\n",is.component_ele_idx(), is.bulk_ele_idx());
943 // for(const IntersectionPoint<1,2>& ip : is.points()) {
944 // DebugOut() << ip;
945 // auto p = ip.coords(mesh->element(is.component_ele_idx()));
946 // DebugOut() << "[" << p[0] << " " << p[1] << " " << p[2] << "]\n";
947 // }
948 // }
949 }
950 
951 // void InspectElementsAlgorithm12::compute_single_intersection(const ElementFullIter& eleA,
952 // const ElementFullIter& eleB)
953 // {
954 // ASSERT_DBG(eleA->dim() == 1);
955 // ASSERT_DBG(eleB->dim() == 2);
956 //
957 // this->update_simplex(eleA, simplexA);
958 // this->update_simplex(eleB, simplexB);
959 //
960 // IntersectionAux<1,2> is(eleA->index(), eleB->index(), 0);
961 // // std::vector<unsigned int> prolongation_table;
962 //
963 // ComputeIntersection< Simplex<1>, Simplex<2>> CI(simplexA, simplexB);
964 // unsigned int n_local_intersection = CI.compute_final(is.points());
965 //
966 // if(n_local_intersection > 0)
967 // {
968 // DebugOut().fmt("found: {}\n",n_local_intersection);
969 // intersectionaux_storage12_.push_back(is);
970 // }
971 // }
972 
973 
974 
976 {
977  //DebugOut() << "Intersections 1d-2d (2-bihtree)\n";
978 
979  START_TIMER("Element iteration");
980 
981  FOR_ELEMENTS(mesh, elm) {
982  unsigned int component_ele_idx = elm->index();
983 
984  if (elm->dim() == 1) // is component element
985  //&& elements_bb[component_ele_idx].intersect(mesh_3D_bb)) // its bounding box intersects 3D mesh bounding box
986  {
987  update_simplex(elm, simplexA); // update component simplex
988  std::vector<unsigned int> searchedElements;
989 
990  START_TIMER("BIHtree find");
991  bih.find_bounding_box(bih.ele_bounding_box(component_ele_idx), searchedElements);
992  END_TIMER("BIHtree find");
993 
994  START_TIMER("Bounding box element iteration");
995 
996  // Go through all element which bounding box intersects the component element bounding box
997  for (std::vector<unsigned int>::iterator it = searchedElements.begin(); it!=searchedElements.end(); it++)
998  {
999  unsigned int bulk_ele_idx = *it;
1000  ElementFullIter ele_2D = mesh->element(bulk_ele_idx);
1001 
1002  if (ele_2D->dim() == 2) {
1003  update_simplex(ele_2D, simplexB); // update triangle
1004 
1005  IntersectionAux<1,2> is(component_ele_idx, bulk_ele_idx);
1006  START_TIMER("Compute intersection");
1008  CI.compute_final(is.points());
1009  END_TIMER("Compute intersection");
1010 
1011  if(is.points().size() > 0) {
1012  intersectionaux_storage12_.push_back(is);
1013  }
1014  }
1015  }
1016  END_TIMER("Bounding box element iteration");
1017  }
1018  }
1019 
1020  END_TIMER("Element iteration");
1021 }
1022 
1023 // Declaration of specializations implemented in cpp:
1024 template class IntersectionAlgorithmBase<1,3>;
1025 template class IntersectionAlgorithmBase<2,3>;
1026 template class IntersectionAlgorithmBase<1,2>;
1027 template class IntersectionAlgorithmBase<2,2>;
1028 
1029 template class InspectElementsAlgorithm<1>;
1030 template class InspectElementsAlgorithm<2>;
1031 
1032 
void set_simplices(arma::vec3 **field_of_pointers_to_coordinates)
Creating sub-simplices in lexicografic order.
Definition: simplex.cc:10
unsigned int uint
Classes with algorithms for computation of intersections of meshes.
std::vector< BoundingBox > elements_bb
Elements bounding boxes.
#define FOR_ELEMENTS(_mesh_, __i)
Definition: mesh.h:480
void prolongate(const Prolongation &pr)
Computes the intersection for a candidate in a queue and calls prolongation_decide again...
#define MessageOut()
Macro defining &#39;message&#39; record of log.
Definition: logger.hh:243
void compute_intersections(std::vector< std::vector< ILpair >> &intersection_map, std::vector< IntersectionLocal< 1, 2 >> &storage)
Runs the algorithm (3): compute 1D-2D intersection inside 3D mesh. It directly fills the intersection...
void compute_single_intersection(const ElementFullIter &eleA, const ElementFullIter &eleB, std::vector< IntersectionLocal< 2, 2 >> &storage)
Computes fundamental intersection of two 2D elements.
Fundamental simplicial intersections.
bool intersection_exists(unsigned int component_ele_idx, unsigned int bulk_ele_idx)
A hard way to find whether the intersection of two elements has already been computed, or not.
std::vector< unsigned int > last_slave_for_3D_elements
void expand(const Point &point)
Definition: mesh.h:99
Auxiliary structure for prolongation process.
unsigned int size() const
Returns number of intersection points.
int index() const
Definition: sys_vector.hh:78
int n_sides
Definition: edges.h:36
Definition: edges.h:26
bool intersect(const BoundingBox &b2) const
unsigned int n_intersections_
Counter for intersection among elements.
#define ASSERT(expr)
Allow use shorter versions of macro names if these names is not used with external library...
Definition: asserts.hh:346
#define ADD_CALLS(n_calls)
Increase number of calls in actual timer.
bool compute_initial_CI(unsigned int component_ele_idx, unsigned int bulk_ele_idx)
Computes the first intersection, from which we then prolongate.
std::queue< Prolongation > component_queue_
Prolongation queue in the component mesh.
void compute_intersections_BIHtree(const BIHTree &bih)
Uses only BIHtree to find intersection candidates. (No prolongation).
std::vector< unsigned int > component_idx_
void assert_same_intersection(unsigned int comp_ele_idx, unsigned int bulk_ele_idx)
void compute_intersections(std::vector< std::vector< ILpair >> &intersection_map, std::vector< IntersectionLocal< 2, 2 >> &storage)
Runs the core algorithm for computing 2D-2D intersection in 3D.
unsigned int n_elements() const
Definition: mesh.h:156
std::vector< IntersectionAux< 1, 2 > > intersectionaux_storage12_
Stores temporarily 1D-2D intersections.
void find_bounding_box(const BoundingBox &boundingBox, std::vector< unsigned int > &result_list, bool full_list=false) const
Definition: bih_tree.cc:215
std::vector< std::vector< IntersectionAux< dim, 3 > > > intersection_list_
Resulting vector of intersections.
std::vector< unsigned int > get_element_neighbors(const ElementFullIter &ele, unsigned int ip_dim, unsigned int ip_obj_idx)
void create_component_numbering()
Creates numbering of the 2D components and fills component_idx_ vector.
const BoundingBox & tree_box() const
Definition: bih_tree.cc:210
static const IdxVector< (InDim >OutDim?InDim+1:dim-InDim) > interact(TInteraction< OutDim, InDim > interaction)
#define START_TIMER(tag)
Starts a timer with specified tag.
Class for O(log N) lookup for intersections with a set of bounding boxes.
Definition: bih_tree.hh:36
std::vector< IntersectionPointAux< dimA, dimB > > & points()
Returns intersection points by a reference.
void swap(nlohmann::json &j1, nlohmann::json &j2) noexcept(is_nothrow_move_constructible< nlohmann::json >::value andis_nothrow_move_assignable< nlohmann::json >::value)
exchanges the values of two JSON objects
Definition: json.hpp:8688
Simplex< dimA > simplexA
Objects representing single elements.
ElementFullIter element() const
Definition: side_impl.hh:52
void compute_intersections(const BIHTree &bih)
Uses BIHtree to find the initial candidate of a component and then prolongates the component interset...
std::vector< Edge > edges
Vector of MH edges, this should not be part of the geometrical mesh.
Definition: mesh.h:271
#define ASSERT_DBG(expr)
Definition: asserts.hh:349
BoundingBox mesh_3D_bb
Bounding box of all 3D elements.
void prolongation_decide(const ElementFullIter &comp_ele, const ElementFullIter &bulk_ele, IntersectionAux< dim, 3 > is)
#define END_TIMER(tag)
Ends a timer with specified tag.
void compute_bounding_boxes()
Computes bounding boxes of all elements. Fills elements_bb and mesh_3D_bb.
Internal auxiliary class represents an intersection point of simplex<N> and simplex<M>.
Class RefElement defines numbering of vertices, sides, calculation of normal vectors etc...
void update_simplex(const ElementFullIter &element, Simplex< simplex_dim > &simplex)
Auxiliary function that translates ElementFullIter to Simplex<simplex_dim>.
void compute_intersections_2(const BIHTree &bih)
Runs the algorithm (2): compute 1D-2D intersection in 3D ambient space BIH is used to find intersecti...
Internal auxiliary class representing intersection object of simplex<dimA> and simplex<dimB>.
unsigned int create_prolongation(unsigned int bulk_ele_idx, unsigned int component_ele_idx, std::queue< Prolongation > &queue)
#define DebugOut()
Macro defining &#39;debug&#39; record of log.
Definition: logger.hh:252
Internal class representing intersection point.
std::queue< Prolongation > bulk_queue_
Prolongation queue in the bulk mesh.
SideIter side(const unsigned int i) const
Definition: edges.h:31
const BoundingBox & ele_bounding_box(unsigned int ele_idx) const
Gets bounding box of element of given index ele_index.
Definition: bih_tree.cc:57
ElementVector element
Vector of elements of the mesh.
Definition: mesh.h:260
Internal class representing intersection object.