Flow123d
mesh.cc
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2007 Technical University of Liberec. All rights reserved.
4  *
5  * Please make a following refer to Flow123d on your project site if you use the program for any purpose,
6  * especially for academic research:
7  * Flow123d, Research Centre: Advanced Remedial Technologies, Technical University of Liberec, Czech Republic
8  *
9  * This program is free software; you can redistribute it and/or modify it under the terms
10  * of the GNU General Public License version 3 as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14  * See the GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along with this program; if not,
17  * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 021110-1307, USA.
18  *
19  *
20  * $Id$
21  * $Revision$
22  * $LastChangedBy$
23  * $LastChangedDate$
24  *
25  * @file
26  * @ingroup mesh
27  * @brief Mesh construction
28  *
29  */
30 
31 #include <unistd.h>
32 #include <set>
33 
34 
35 #include "system/system.hh"
36 #include "system/xio.h"
37 #include "input/json_to_storage.hh"
38 #include "input/input_type.hh"
39 #include "system/sys_profiler.hh"
40 
41 #include <boost/tokenizer.hpp>
42 #include "boost/lexical_cast.hpp"
43 #include <boost/make_shared.hpp>
44 
45 #include "mesh/mesh.h"
46 #include "mesh/ref_element.hh"
47 
48 // think about following dependencies
49 #include "mesh/boundaries.h"
50 #include "mesh/accessors.hh"
51 #include "mesh/partitioning.hh"
52 
53 #include "mesh/bih_tree.hh"
54 
55 
56 //TODO: sources, concentrations, initial condition and similarly boundary conditions should be
57 // instances of a Element valued field
58 // concentrations is in fact reimplemented in transport REMOVE it HERE
59 
60 // After removing non-geometrical things from mesh, this should be part of mash initializing.
61 #include "mesh/msh_reader.h"
62 #include "mesh/msh_gmshreader.h"
63 #include "mesh/region.hh"
64 
65 #define NDEF -1
66 
67 namespace IT = Input::Type;
68 
69 
71  = IT::Record("Mesh","Record with mesh related data." )
73  "Input file with mesh description.")
75  "List of additional region definitions not contained in the mesh.")
77  "List of region set definitions. There are three region sets implicitly defined:\n"
78  "ALL (all regions of the mesh), BOUNDARY (all boundary regions), and BULK (all bulk regions)")
79  .declare_key("partitioning", Partitioning::input_type, IT::Default("any_neighboring"), "Parameters of mesh partitioning algorithms.\n" )
80  .close();
81 
82 
83 
84 const unsigned int Mesh::undef_idx;
85 
86 Mesh::Mesh(const std::string &input_str, MPI_Comm comm)
87 :comm_(comm)
88 {
89 
90  Input::JSONToStorage reader( input_str, Mesh::input_type );
92 
94 }
95 
96 
97 
99 : in_record_(in_record),
100  comm_(com)
101 {
103 }
104 
105 
106 
108 {
109 
110  n_insides = NDEF;
111  n_exsides = NDEF;
112  n_sides_ = NDEF;
113 
114  // number of element of particular dimension
115  n_lines = 0;
116  n_triangles = 0;
117  n_tetrahedras = 0;
118 
119  for (int d=0; d<3; d++) max_edge_sides_[d] = 0;
120 
121  // Initialize numbering of nodes on sides.
122  // This is temporary solution, until class Element is templated
123  // by dimension. Then we can replace Mesh::side_nodes by
124  // RefElement<dim>::side_nodes.
125 
126  // indices of side nodes in element node array
127  // Currently this is made ad libitum
128  // with some ordering here we can get sides with correct orientation.
129  // This speedup normal calculation.
130 
131  side_nodes.resize(3); // three side dimensions
132  for(int i=0; i < 3; i++) {
133  side_nodes[i].resize(i+2); // number of sides
134  for(int j=0; j < i+2; j++)
135  side_nodes[i][j].resize(i+1);
136  }
137 
138  for (unsigned int sid=0; sid<RefElement<1>::n_sides; sid++)
139  for (unsigned int nid=0; nid<RefElement<1>::n_nodes_per_side; nid++)
140  side_nodes[0][sid][nid] = RefElement<1>::side_nodes[sid][nid];
141 
142  for (unsigned int sid=0; sid<RefElement<2>::n_sides; sid++)
143  for (unsigned int nid=0; nid<RefElement<2>::n_nodes_per_side; nid++)
144  side_nodes[1][sid][nid] = RefElement<2>::side_nodes[sid][nid];
145 
146  for (unsigned int sid=0; sid<RefElement<3>::n_sides; sid++)
147  for (unsigned int nid=0; nid<RefElement<3>::n_nodes_per_side; nid++)
148  side_nodes[2][sid][nid] = RefElement<3>::side_nodes[sid][nid];
149 }
150 
151 
152 unsigned int Mesh::n_sides()
153 {
154  if (n_sides_ == NDEF) {
155  n_sides_=0;
156  FOR_ELEMENTS(this, ele) n_sides_ += ele->n_sides();
157  }
158  return n_sides_;
159 }
160 
161 
162 
164  return part_.get();
165 }
166 
167 
168 //=============================================================================
169 // COUNT ELEMENT TYPES
170 //=============================================================================
171 
173  F_ENTRY;
174 
175  FOR_ELEMENTS(this, elm)
176  switch (elm->dim()) {
177  case 1:
178  n_lines++;
179  break;
180  case 2:
181  n_triangles++;
182  break;
183  case 3:
184  n_tetrahedras++;
185  break;
186  }
187 }
188 
189 
190 void Mesh::read_gmsh_from_stream(istream &in) {
191 
192  START_TIMER("Reading mesh - from_stream");
193 
194  GmshMeshReader reader(in);
195  reader.read_mesh(this);
196  setup_topology();
197 }
198 
199 
200 
202  F_ENTRY;
203 
204  START_TIMER("Reading mesh - init_from_input");
205 
206  Input::Array region_list;
207  RegionDB::MapElementIDToRegionID el_to_reg_map;
208 
209  // create regions from our input
210  if (in_record_.opt_val("regions", region_list)) {
211  region_db_.read_regions_from_input(region_list, el_to_reg_map);
212  }
213  // read raw mesh, add regions from GMSH file
214  GmshMeshReader reader( in_record_.val<FilePath>("mesh_file") );
215  reader.read_mesh(this, &el_to_reg_map);
216  // possibly add implicit_boundary region, close region_db_.
217  setup_topology();
218  // create sets
219  Input::Array set_list;
220  if (in_record_.opt_val("sets", set_list)) {
222  }
223 }
224 
225 
226 
227 
229  F_ENTRY;
230 
231  START_TIMER("MESH - setup topology");
232 
234 
235  // check mesh quality
236  FOR_ELEMENTS(this, ele)
237  if (ele->quality_measure_smooth() < 0.001) xprintf(Warn, "Bad quality (<0.001) of the element %u.\n", ele.id());
238 
243 
244  region_db_.close();
245  part_ = boost::make_shared<Partitioning>(this, in_record_.val<Input::Record>("partitioning") );
246 }
247 
248 
249 //
251 {
252 
253  n_insides = 0;
254  n_exsides = 0;
255  //FOR_SIDES(this, sde ) {
256  // DBGMSG( "ele: %d edge: %d\n", sde->element().index(), sde->edge_idx());
257  //}
258  FOR_SIDES(this, sde ) {
259  if (sde->is_external()) n_exsides++;
260  else n_insides++;
261  }
262 }
263 
264 
265 
267  // for each node we make a list of elements that use this node
268  node_elements.resize(node_vector.size());
269 
270  FOR_ELEMENTS( this, e )
271  for (unsigned int n=0; n<e->n_nodes(); n++)
272  node_elements[node_vector.index(e->node[n])].push_back(e->index());
273 
274  for (vector<vector<unsigned int> >::iterator n=node_elements.begin(); n!=node_elements.end(); n++)
275  stable_sort(n->begin(), n->end());
276 }
277 
278 
279 void Mesh::intersect_element_lists(vector<unsigned int> const &nodes_list, vector<unsigned int> &intersection_element_list)
280 {
281  if (nodes_list.size() == 0) {
282  intersection_element_list.clear();
283  } else if (nodes_list.size() == 1) {
284  intersection_element_list = node_elements[ nodes_list[0] ];
285  } else {
286  vector<unsigned int>::const_iterator it1=nodes_list.begin();
288  intersection_element_list.resize( node_elements[*it1].size() ); // make enough space
289 
290  it1=set_intersection(
291  node_elements[*it1].begin(), node_elements[*it1].end(),
292  node_elements[*it2].begin(), node_elements[*it2].end(),
293  intersection_element_list.begin());
294  intersection_element_list.resize(it1-intersection_element_list.begin()); // resize to true size
295 
296  for(;it2<nodes_list.end();++it2) {
297  it1=set_intersection(
298  intersection_element_list.begin(), intersection_element_list.end(),
299  node_elements[*it2].begin(), node_elements[*it2].end(),
300  intersection_element_list.begin());
301  intersection_element_list.resize(it1-intersection_element_list.begin()); // resize to true size
302  }
303  }
304 }
305 
306 
308  unsigned int dim, unsigned int &element_idx) {
309  bool is_neighbour = false;
310 
311  vector<unsigned int>::iterator e_dest=element_list.begin();
312  for( vector<unsigned int>::iterator ele = element_list.begin(); ele!=element_list.end(); ++ele)
313  if (elements[*ele].dim() == dim) { // keep only indexes of elements of same dimension
314  *e_dest=*ele;
315  ++e_dest;
316  } else if (elements[*ele].dim() == dim-1) { // get only first element of lower dimension
317  if (is_neighbour) xprintf(UsrErr, "Too matching elements id: %d and id: %d in the same mesh.\n",
318  elements(*ele).id(), elements(element_idx).id() );
319 
320  is_neighbour = true;
321  element_idx = *ele;
322  }
323  element_list.resize( e_dest - element_list.begin());
324  return is_neighbour;
325 }
326 
327 bool Mesh::same_sides(const SideIter &si, vector<unsigned int> &side_nodes) {
328  // check if nodes lists match (this is slow and will be faster only when we convert whole mesh into hierarchical design like in deal.ii)
329  unsigned int ni=0;
330  while ( ni < si->n_nodes()
331  && find(side_nodes.begin(), side_nodes.end(), node_vector.index( si->node(ni) ) ) != side_nodes.end() ) ni++;
332  return ( ni == si->n_nodes() );
333 }
334 
335 /**
336  * TODO:
337  * - use std::is_any for setting is_neigbour
338  * - possibly make appropriate constructors for Edge and Neighbour
339  * - check side!=-1 when searching neigbouring element
340  * - process bc_elements first, there should be no Neigh, but check it
341  * set Edge and boundary there
342  */
343 
345 {
346  Neighbour neighbour;
347  Edge *edg;
348  unsigned int ngh_element_idx, last_edge_idx;
349 
351 
352  // pointers to created edges
353  //vector<Edge *> tmp_edges;
354  edges.resize(0); // be sure that edges are empty
355 
357  vector<unsigned int> intersection_list; // list of elements in intersection of node element lists
358 
359  for( ElementFullIter bc_ele = bc_elements.begin(); bc_ele != bc_elements.end(); ++bc_ele) {
360  // Find all elements that share this side.
361  side_nodes.resize(bc_ele->n_nodes());
362  for (unsigned n=0; n<bc_ele->n_nodes(); n++) side_nodes[n] = node_vector.index(bc_ele->node[n]);
363  intersect_element_lists(side_nodes, intersection_list);
364  bool is_neighbour = find_lower_dim_element(element, intersection_list, bc_ele->dim() +1, ngh_element_idx);
365  if (is_neighbour) {
366  xprintf(UsrErr, "Boundary element (id: %d) match a regular element (id: %d) of lower dimension.\n",
367  bc_ele.id(), element(ngh_element_idx).id());
368  } else {
369  if (intersection_list.size() == 0) {
370  // no matching dim+1 element found
371  xprintf(Warn, "Lonely boundary element, id: %d, region: %d, dimension %d.\n", bc_ele.id(), bc_ele->region().id(), bc_ele->dim());
372  continue; // skip the boundary element
373  }
374  last_edge_idx=edges.size();
375  edges.resize(last_edge_idx+1);
376  edg = &( edges.back() );
377  edg->n_sides = 0;
378  edg->side_ = new struct SideIter[ intersection_list.size() ];
379 
380  // common boundary object
381  unsigned int bdr_idx=boundary_.size();
382  boundary_.resize(bdr_idx+1);
383  Boundary &bdr=boundary_.back();
384  bdr.bc_ele_idx_ = bc_ele.index();
385  bdr.edge_idx_ = last_edge_idx;
386  bdr.mesh_=this;
387 
388  // for 1d boundaries there can be more then one 1d elements connected to the boundary element
389  // we do not detect this case later in the main search over bulk elements
390  for( vector<unsigned int>::iterator isect = intersection_list.begin(); isect!=intersection_list.end(); ++isect) {
391  Element *elem = &(element[*isect]);
392  for (unsigned int ecs=0; ecs<elem->n_sides(); ecs++) {
393  SideIter si = elem->side(ecs);
394  if ( same_sides( si, side_nodes) ) {
395  edg->side_[ edg->n_sides++ ] = si;
396  elem->edge_idx_[ecs] = last_edge_idx;
397 
398  if (elem->boundary_idx_ == NULL) {
399  elem->boundary_idx_ = new unsigned int [ elem->n_sides() ];
400  std::fill( elem->boundary_idx_, elem->boundary_idx_ + elem->n_sides(), Mesh::undef_idx);
401  }
402  elem->boundary_idx_[ecs] = bdr_idx;
403  break; // next element in intersection list
404  }
405  }
406  }
407 
408  }
409 
410  }
411  // Now we go through all element sides and create edges and neighbours
412  FOR_ELEMENTS( this, e )
413  {
414  for (unsigned int s=0; s<e->n_sides(); s++)
415  {
416  // skip sides that were already found
417  if (e->edge_idx_[s] != Mesh::undef_idx) continue;
418 
419 
420  // Find all elements that share this side.
421  side_nodes.resize(e->side(s)->n_nodes());
422  for (unsigned n=0; n<e->side(s)->n_nodes(); n++) side_nodes[n] = node_vector.index(e->side(s)->node(n));
423  intersect_element_lists(side_nodes, intersection_list);
424 
425  bool is_neighbour = find_lower_dim_element(element, intersection_list, e->dim(), ngh_element_idx);
426 
427  if (is_neighbour) { // edge connects elements of different dimensions
428  neighbour.element_ = &(element[ngh_element_idx]);
429  } else { // edge connects only elements of the same dimension
430  // Allocate the array of sides.
431  last_edge_idx=edges.size();
432  edges.resize(last_edge_idx+1);
433  edg = &( edges.back() );
434  edg->n_sides = 0;
435  edg->side_ = new struct SideIter[ intersection_list.size() ];
436  if (intersection_list.size() > max_edge_sides_[e->dim()-1])
437  max_edge_sides_[e->dim()-1] = intersection_list.size();
438 
439  if (intersection_list.size() == 1) { // outer edge, create boundary object as well
440  edg->n_sides=1;
441  edg->side_[0] = e->side(s);
442  e->edge_idx_[s] = last_edge_idx;
443 
444  if (e->boundary_idx_ == NULL) {
445  e->boundary_idx_ = new unsigned int [ e->n_sides() ];
446  std::fill( e->boundary_idx_, e->boundary_idx_ + e->n_sides(), Mesh::undef_idx);
447  }
448 
449  unsigned int bdr_idx=boundary_.size();
450  boundary_.resize(bdr_idx+1);
451  Boundary &bdr=boundary_.back();
452  e->boundary_idx_[s] = bdr_idx;
453 
454  // fill boundary element
455  ElementFullIter bc_ele = bc_elements.add_item( -bdr_idx ); // use negative bcd index as ID,
456  bc_ele->init(e->dim()-1, this, region_db_.implicit_boundary_region() );
457  for(unsigned int ni = 0; ni< side_nodes.size(); ni++) bc_ele->node[ni] = &( node_vector[side_nodes[ni]] );
458 
459  // fill Boundary object
460  bdr.edge_idx_ = last_edge_idx;
461  bdr.bc_ele_idx_ = bc_ele.index();
462  bdr.mesh_=this;
463 
464  continue; // next side of element e
465  }
466  }
467 
468  // go through the elements connected to the edge or neighbour
469  for( vector<unsigned int>::iterator isect = intersection_list.begin(); isect!=intersection_list.end(); ++isect) {
470  Element *elem = &(element[*isect]);
471  for (unsigned int ecs=0; ecs<elem->n_sides(); ecs++) {
472  if (elem->edge_idx_[ecs] != Mesh::undef_idx) continue;
473  SideIter si = elem->side(ecs);
474  if ( same_sides( si, side_nodes) ) {
475  if (is_neighbour) {
476  // create a new edge and neighbour for this side, and element to the edge
477  last_edge_idx=edges.size();
478  edges.resize(last_edge_idx+1);
479  edg = &( edges.back() );
480  edg->n_sides = 1;
481  edg->side_ = new struct SideIter[1];
482  edg->side_[0] = si;
483  elem->edge_idx_[ecs] = last_edge_idx;
484 
485  neighbour.edge_idx_ = last_edge_idx;
486 
487  vb_neighbours_.push_back(neighbour); // copy neighbour with this edge setting
488  } else {
489  // connect the side to the edge, and side to the edge
490  edg->side_[ edg->n_sides++ ] = si;
491  elem->edge_idx_[ecs] = last_edge_idx;
492  }
493  break; // next element from intersection list
494  }
495  } // search for side of other connected element
496  } // connected elements
497  ASSERT( is_neighbour || ( (unsigned int) edg->n_sides ) == intersection_list.size(), "Some connected sides were not found.\n");
498  } // for element sides
499  } // for elements
500 
501  xprintf( Msg, "Created %d edges and %d neighbours.\n", edges.size(), vb_neighbours_.size() );
502 }
503 
504 
505 
507 {
508  for (EdgeVector::iterator edg=edges.begin(); edg!=edges.end(); edg++)
509  {
510  // side 0 is reference, so its permutation is 0
511  edg->side(0)->element()->permutation_idx_[edg->side(0)->el_idx()] = 0;
512 
513  if (edg->n_sides > 1)
514  {
515  map<const Node*,unsigned int> node_numbers;
516  unsigned int permutation[edg->side(0)->n_nodes()];
517 
518  for (unsigned int i=0; i<edg->side(0)->n_nodes(); i++)
519  node_numbers[edg->side(0)->node(i)] = i;
520 
521  for (int sid=1; sid<edg->n_sides; sid++)
522  {
523  for (unsigned int i=0; i<edg->side(0)->n_nodes(); i++)
524  permutation[node_numbers[edg->side(sid)->node(i)]] = i;
525 
526  switch (edg->side(0)->dim())
527  {
528  case 0:
529  edg->side(sid)->element()->permutation_idx_[edg->side(sid)->el_idx()] = RefElement<1>::permutation_index(permutation);
530  break;
531  case 1:
532  edg->side(sid)->element()->permutation_idx_[edg->side(sid)->el_idx()] = RefElement<2>::permutation_index(permutation);
533  break;
534  case 2:
535  edg->side(sid)->element()->permutation_idx_[edg->side(sid)->el_idx()] = RefElement<3>::permutation_index(permutation);
536  break;
537  }
538  }
539  }
540  }
541 
542  for (vector<Neighbour>::iterator nb=vb_neighbours_.begin(); nb!=vb_neighbours_.end(); nb++)
543  {
544  map<const Node*,unsigned int> node_numbers;
545  unsigned int permutation[nb->element()->n_nodes()];
546 
547  // element of lower dimension is reference, so
548  // we calculate permutation for the adjacent side
549  for (unsigned int i=0; i<nb->element()->n_nodes(); i++)
550  node_numbers[nb->element()->node[i]] = i;
551 
552  for (unsigned int i=0; i<nb->side()->n_nodes(); i++)
553  permutation[node_numbers[nb->side()->node(i)]] = i;
554 
555  switch (nb->side()->dim())
556  {
557  case 0:
558  nb->side()->element()->permutation_idx_[nb->side()->el_idx()] = RefElement<1>::permutation_index(permutation);
559  break;
560  case 1:
561  nb->side()->element()->permutation_idx_[nb->side()->el_idx()] = RefElement<2>::permutation_index(permutation);
562  break;
563  case 2:
564  nb->side()->element()->permutation_idx_[nb->side()->el_idx()] = RefElement<3>::permutation_index(permutation);
565  break;
566  }
567  }
568 }
569 
570 
571 
572 
573 
574 /**
575  * Set Element->boundaries_ for all external sides. (temporary solution)
576  */
578 {
579  /*
580  // set to non zero all pointers including boundary connected to lower dim elements
581  // these have only one side per edge
582  Boundary empty_boundary;
583 
584 
585  FOR_ELEMENTS(this, ele) {
586  // is there any outer side
587  bool outer=false;
588  FOR_ELEMENT_SIDES(ele, si)
589  {
590  if ( ele->side(si)->edge()->n_sides == 1) {
591  outer=true;
592  break;
593  }
594  }
595  if (outer) {
596  // for elements on the boundary set boundaries_
597  FOR_ELEMENT_SIDES(ele,si)
598  if ( ele->side(si)->edge()->n_sides == 1)
599  ele->boundaries_[si] = &empty_boundary;
600  else
601  ele->boundaries_[si] = NULL;
602 
603  } else {
604  // can delete boundaries on internal elements !!
605  delete ele->boundaries_;
606  ele->boundaries_=NULL;
607  }
608  }
609 
610  int count=0;
611  // pass through neighbours and set to NULL internal interfaces
612  FOR_NEIGHBOURS(this, ngh ) {
613  SideIter s = ngh->side();
614  if (s->element()->boundaries_ == NULL) continue;
615  s->element()->boundaries_[ s->el_idx() ] = NULL;
616  }
617 
618  // count remaining
619  unsigned int n_boundaries=0;
620  FOR_ELEMENTS(this, ele) {
621  if (ele->boundaries_ == NULL) continue;
622  FOR_ELEMENT_SIDES(ele, si)
623  if (ele->boundaries_[si]) n_boundaries ++;
624  }
625 
626  // fill boundaries
627  BoundaryFullIter bcd(boundary);
628  unsigned int ni;
629 
630  boundary.reserve(n_boundaries);
631  DBGMSG("bc_elements size after read: %d\n", bc_elements.size());
632  bc_elements.reserve(n_boundaries);
633  FOR_ELEMENTS(this, ele) {
634  if (ele->boundaries_ == NULL) continue;
635  FOR_ELEMENT_SIDES(ele, si)
636  if (ele->boundaries_[si]) {
637  // add boundary object
638  bcd = boundary.add_item();
639 
640 
641  // fill boundary element
642  Element * bc_ele = bc_elements.add_item( -bcd.index() ); // use negative bcd index as ID,
643  bc_ele->dim_ = ele->dim()-1;
644  bc_ele->node = new Node * [bc_ele->n_nodes()];
645  FOR_ELEMENT_NODES(bc_ele, ni) {
646  bc_ele->node[ni] = (Node *)ele->side(si)->node(ni);
647  }
648 
649  // fill Boudary object
650  bcd->side = ele->side(si);
651  bcd->bc_element_ = bc_ele;
652  ele->boundaries_[si] = bcd;
653 
654  }
655  }*/
656 }
657 
658 
659 //=============================================================================
660 //
661 //=============================================================================
663 {
664 
665  xprintf( MsgVerb, " Element to neighbours of vb2 type... ")/*orig verb 5*/;
666 
667  FOR_ELEMENTS(this,ele) ele->n_neighs_vb =0;
668 
669  // count vb neighs per element
670  FOR_NEIGHBOURS(this, ngh ) ngh->element_->n_neighs_vb++;
671 
672  // Allocation of the array per element
673  FOR_ELEMENTS(this, ele )
674  if( ele->n_neighs_vb > 0 ) {
675  ele->neigh_vb = new struct Neighbour* [ele->n_neighs_vb];
676  ele->n_neighs_vb=0;
677  }
678 
679  // fill
680  ElementIter ele;
681  FOR_NEIGHBOURS(this, ngh ) {
682  ele = ngh->element();
683  ele->neigh_vb[ ele->n_neighs_vb++ ] = &( *ngh );
684  }
685 
686  xprintf( MsgVerb, "O.K.\n")/*orig verb 6*/;
687 }
688 
689 
690 
691 
695 
696 
698  /* Algorithm:
699  *
700  * 1) create BIH tree
701  * 2) for every 1D, find list of candidates
702  * 3) compute intersections for 1d, store it to master_elements
703  *
704  */
705  BIHTree bih_tree( this );
706  vector<unsigned int> candidate_list(20);
707  master_elements.resize(n_elements());
708 
709  for(unsigned int i_ele=0; i_ele<n_elements(); i_ele++) {
710  Element &ele = this->element[i_ele];
711 
712  if (ele.dim() == 1) {
713  //bih_tree.find_bounding_box(ele.bounding_box(), candidate_list);
714  //DBGMSG("1d el: %d n_cand: %d\n", ele.index(), candidate_list.size() );
715  //for(int i_elm: candidate_list) {
716  for(unsigned int i_elm=0; i_elm<n_elements(); i_elm++) {
717  ElementFullIter elm = this->element( i_elm );
718  if (elm->dim() == 2) {
719  IntersectionLocal *intersection;
720  GetIntersection( TAbscissa(ele), TTriangle(*elm), intersection);
721  //DBGMSG("2d el: %d %p\n", elm->index(), intersection);
722  if (intersection && intersection->get_type() == IntersectionLocal::line) {
723 
724  master_elements[i_ele].push_back( intersections.size() );
725  intersections.push_back( Intersection(this->element(i_ele), elm, intersection) );
726  //DBGMSG("isec: %d %d %g\n" , ele.index(), elm->index(),
727  // intersections.back().intersection_true_size() );
728  }
729  }
730 
731  }
732  }
733  }
734 
735 }
736 
737 
738 
739 ElementAccessor<3> Mesh::element_accessor(unsigned int idx, bool boundary) {
740  return ElementAccessor<3>(this, idx, boundary);
741 }
742 
743 
744 
745 vector<int> const & Mesh::elements_id_maps( bool boundary_domain) const
746 {
747  if (bulk_elements_id_.size() ==0) {
749  int last_id;
750 
751  bulk_elements_id_.resize(n_elements());
752  map_it = bulk_elements_id_.begin();
753  last_id = -1;
754  for(int idx=0; idx < element.size(); idx++, ++map_it) {
755  int id = element.get_id(idx);
756  if (last_id >= id) xprintf(UsrErr, "Element IDs in non-increasing order, ID: %d\n", id);
757  last_id=*map_it = id;
758 // DBGMSG("bulk map: %d\n", *map_it);
759  }
760 
762  map_it = boundary_elements_id_.begin();
763  last_id = -1;
764  for(int idx=0; idx < bc_elements.size(); idx++, ++map_it) {
765  int id = bc_elements.get_id(idx);
766  // We set ID for boundary elements created by the mesh itself to "-1"
767  // this force gmsh reader to skip all remaining entries in boundary_elements_id_
768  // and thus report error for any remaining data lines
769  if (id < 0) last_id=*map_it=-1;
770  else {
771  if (last_id >= id) xprintf(UsrErr, "Element IDs in non-increasing order, ID: %d\n", id);
772  last_id=*map_it = id;
773  }
774 // DBGMSG("bc map: %d\n", *map_it);
775  }
776  }
777 
778  if (boundary_domain) return boundary_elements_id_;
779  return bulk_elements_id_;
780 }
781 
782 //-----------------------------------------------------------------------------
783 // vim: set cindent: