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