Flow123d  intersections_paper-476-gbe68821
mesh.cc
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2015 Technical University of Liberec. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU General Public License version 3 as published by the
7  * Free Software Foundation. (http://www.gnu.org/licenses/gpl-3.0.en.html)
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12  *
13  *
14  * @file mesh.cc
15  * @ingroup mesh
16  * @brief Mesh construction
17  */
18 
19 #include <unistd.h>
20 #include <set>
21 
22 
23 #include "system/system.hh"
24 #include "system/exceptions.hh"
26 #include "input/input_type.hh"
27 #include "input/accessors.hh"
28 #include "system/sys_profiler.hh"
29 #include "la/distribution.hh"
30 
31 #include <boost/tokenizer.hpp>
32 #include "boost/lexical_cast.hpp"
33 
34 
35 #include "mesh/ref_element.hh"
36 
37 // think about following dependencies
38 #include "mesh/boundaries.h"
39 #include "mesh/accessors.hh"
40 #include "mesh/partitioning.hh"
41 
42 
43 #include "mesh/bih_tree.hh"
44 
48 
50 
51 
52 #include "mesh/mesh.h"
53 
54 
55 //TODO: sources, concentrations, initial condition and similarly boundary conditions should be
56 // instances of a Element valued field
57 // concentrations is in fact reimplemented in transport REMOVE it HERE
58 
59 // After removing non-geometrical things from mesh, this should be part of mash initializing.
60 #include "mesh/msh_gmshreader.h"
61 #include "mesh/region.hh"
62 
63 #define NDEF -1
64 
65 namespace IT = Input::Type;
66 
68  return Input::Type::Selection("Types of search algorithm for finding intersection candidates.")
69  .add_value(Mesh::BIHsearch, "BIHsearch",
70  "Use BIH for finding initial candidates, then continue by prolongation.")
71  .add_value(Mesh::BIHonly, "BIHonly",
72  "Use BIH for finding all candidates.")
73  .add_value(Mesh::BBsearch, "BBsearch",
74  "Use bounding boxes for finding initial candidates, then continue by prolongation.")
75  .close();
76 }
77 
79  return IT::Record("Mesh","Record with mesh related data." )
80  .allow_auto_conversion("mesh_file")
82  "Input file with mesh description.")
84  "List of additional region and region set definitions not contained in the mesh. "
85  "There are three region sets implicitly defined:\n\n"
86  "- ALL (all regions of the mesh)\n"
87  "- .BOUNDARY (all boundary regions)\n"
88  "- BULK (all bulk regions)")
89  .declare_key("partitioning", Partitioning::get_input_type(), IT::Default("\"any_neighboring\""), "Parameters of mesh partitioning algorithms.\n" )
90  .declare_key("print_regions", IT::Bool(), IT::Default("true"), "If true, print table of all used regions.")
91  .declare_key("intersection_search", Mesh::get_input_intersection_variant(),
92  IT::Default("\"BIHsearch\""), "Search algorithm for element intersections.")
93  .declare_key("global_observe_search_radius", IT::Double(0.0), IT::Default("1E-3"),
94  "Maximal distance of observe point from Mesh relative to its size (bounding box). "
95  "Value is global and it can be rewrite at arbitrary ObservePoint by setting the key search_radius.")
96  .close();
97 }
98 
99 const unsigned int Mesh::undef_idx;
100 
102 : in_record_(in_record),
103  comm_(com),
104  row_4_el(nullptr),
105  el_4_loc(nullptr),
106  el_ds(nullptr)
107 {
108  // set in_record_, if input accessor is empty
109  if (in_record_.is_empty()) {
110  istringstream is("{mesh_file=\"\"}");
111  Input::ReaderToStorage reader;
112  IT::Record &in_rec = const_cast<IT::Record &>(Mesh::get_input_type());
113  in_rec.finish();
114  reader.read_stream(is, in_rec, Input::FileFormat::format_JSON);
116  }
117 
119 }
120 
122 {
123  return in_record_.val<Mesh::IntersectionSearch>("intersection_search");
124 }
125 
126 
128 {
129 
130  n_insides = NDEF;
131  n_exsides = NDEF;
132  n_sides_ = NDEF;
133 
134  // number of element of particular dimension
135  n_lines = 0;
136  n_triangles = 0;
137  n_tetrahedras = 0;
138 
139  for (int d=0; d<3; d++) max_edge_sides_[d] = 0;
140 
141  // Initialize numbering of nodes on sides.
142  // This is temporary solution, until class Element is templated
143  // by dimension. Then we can replace Mesh::side_nodes by
144  // RefElement<dim>::side_nodes.
145 
146  // indices of side nodes in element node array
147  // Currently this is made ad libitum
148  // with some ordering here we can get sides with correct orientation.
149  // This speedup normal calculation.
150 
151  side_nodes.resize(3); // three side dimensions
152  for(int i=0; i < 3; i++) {
153  side_nodes[i].resize(i+2); // number of sides
154  for(int j=0; j < i+2; j++)
155  side_nodes[i][j].resize(i+1);
156  }
157 
158  for (unsigned int sid=0; sid<RefElement<1>::n_sides; sid++)
159  for (unsigned int nid=0; nid<RefElement<1>::n_nodes_per_side; nid++)
160  side_nodes[0][sid][nid] = RefElement<1>::interact(Interaction<0,0>(sid))[nid];
161 
162  for (unsigned int sid=0; sid<RefElement<2>::n_sides; sid++)
163  for (unsigned int nid=0; nid<RefElement<2>::n_nodes_per_side; nid++)
164  side_nodes[1][sid][nid] = RefElement<2>::interact(Interaction<0,1>(sid))[nid];
165 
166  for (unsigned int sid=0; sid<RefElement<3>::n_sides; sid++)
167  for (unsigned int nid=0; nid<RefElement<3>::n_nodes_per_side; nid++)
168  side_nodes[2][sid][nid] = RefElement<3>::interact(Interaction<0,2>(sid))[nid];
169 }
170 
171 
173  for(Edge &edg : this->edges)
174  if (edg.side_) delete[] edg.side_;
175 
176  FOR_ELEMENTS( this, ele ) {
177  if (ele->node) delete[] ele->node;
178  if (ele->edge_idx_) delete[] ele->edge_idx_;
179  if (ele->permutation_idx_) delete[] ele->permutation_idx_;
180  if (ele->boundary_idx_) delete[] ele->boundary_idx_;
181  if (ele->neigh_vb) delete[] ele->neigh_vb;
182  }
183 
184  for(unsigned int idx=0; idx < this->bc_elements.size(); idx++) {
185  Element *ele=&(bc_elements[idx]);
186  if (ele->node) delete[] ele->node;
187  if (ele->edge_idx_) delete[] ele->edge_idx_;
188  if (ele->permutation_idx_) delete[] ele->permutation_idx_;
189  if (ele->boundary_idx_) delete[] ele->boundary_idx_;
190  }
191 
192  if (row_4_el != nullptr) delete[] row_4_el;
193  if (el_4_loc != nullptr) delete[] el_4_loc;
194  if (el_ds != nullptr) delete el_ds;
195 }
196 
197 
198 unsigned int Mesh::n_sides()
199 {
200  if (n_sides_ == NDEF) {
201  n_sides_=0;
202  FOR_ELEMENTS(this, ele) n_sides_ += ele->n_sides();
203  }
204  return n_sides_;
205 }
206 
207 unsigned int Mesh::n_corners() {
208  unsigned int li, count = 0;
209  FOR_ELEMENTS(this, ele) {
210  FOR_ELEMENT_NODES(ele, li) {
211  count++;
212  }
213  }
214  return count;
215 }
216 
218  return part_.get();
219 }
220 
221 
222 //=============================================================================
223 // COUNT ELEMENT TYPES
224 //=============================================================================
225 
227  FOR_ELEMENTS(this, elm)
228  switch (elm->dim()) {
229  case 1:
230  n_lines++;
231  break;
232  case 2:
233  n_triangles++;
234  break;
235  case 3:
236  n_tetrahedras++;
237  break;
238  }
239 }
240 
241 
242 void Mesh::read_gmsh_from_stream(istream &in) {
243 
244  START_TIMER("Reading mesh - from_stream");
245 
246  GmshMeshReader reader(in);
247  reader.read_physical_names(this);
248  reader.read_mesh(this);
249  setup_topology();
250  //close region_db_.
251  region_db_.close();
252 }
253 
254 
255 
257  START_TIMER("Reading mesh - init_from_input");
258 
259  try {
260  Input::Array region_list;
261  // read raw mesh, add regions from GMSH file
262  GmshMeshReader reader( in_record_.val<FilePath>("mesh_file") );
263  reader.read_physical_names(this);
264  // create regions from input
265  if (in_record_.opt_val("regions", region_list)) {
266  this->read_regions_from_input(region_list);
267  }
268  reader.read_mesh(this);
269  } INPUT_CATCH(FilePath::ExcFileOpen, FilePath::EI_Address_String, in_record_)
270  catch (ExceptionBase const &e) {
271  throw;
272  }
273  // possibly add implicit_boundary region.
274  setup_topology();
275  // finish mesh initialization
276  this->check_and_finish();
277 }
278 
279 
280 
281 
283  for (auto elem_to_region : map) {
284  ElementIter ele = this->element.find_id(elem_to_region.first);
285  ele->region_idx_ = region_db_.get_region( elem_to_region.second, ele->dim() );
287  }
288 }
289 
290 
291 
293  START_TIMER("MESH - setup topology");
294 
296 
297  // check mesh quality
298  FOR_ELEMENTS(this, ele)
299  if (ele->quality_measure_smooth() < 0.001) WarningOut().fmt("Bad quality (<0.001) of the element {}.\n", ele.id());
300 
305 
306  part_ = std::make_shared<Partitioning>(this, in_record_.val<Input::Record>("partitioning") );
307 
308  // create parallel distribution and numbering of elements
309  int *id_4_old = new int[element.size()];
310  int i = 0;
311  FOR_ELEMENTS(this, ele)
312  id_4_old[i++] = ele.index();
313  part_->id_maps(element.size(), id_4_old, el_ds, el_4_loc, row_4_el);
314 
315  delete[] id_4_old;
316 }
317 
318 
319 //
321 {
322 
323  n_insides = 0;
324  n_exsides = 0;
325  FOR_SIDES(this, sde ) {
326  if (sde->is_external()) n_exsides++;
327  else n_insides++;
328  }
329 }
330 
331 
332 
334  // for each node we make a list of elements that use this node
335  node_elements.resize(node_vector.size());
336 
337  FOR_ELEMENTS( this, e )
338  for (unsigned int n=0; n<e->n_nodes(); n++)
339  node_elements[node_vector.index(e->node[n])].push_back(e->index());
340 
341  for (vector<vector<unsigned int> >::iterator n=node_elements.begin(); n!=node_elements.end(); n++)
342  stable_sort(n->begin(), n->end());
343 }
344 
345 
346 void Mesh::intersect_element_lists(vector<unsigned int> const &nodes_list, vector<unsigned int> &intersection_element_list)
347 {
348  if (nodes_list.size() == 0) {
349  intersection_element_list.clear();
350  } else if (nodes_list.size() == 1) {
351  intersection_element_list = node_elements[ nodes_list[0] ];
352  } else {
353  vector<unsigned int>::const_iterator it1=nodes_list.begin();
355  intersection_element_list.resize( node_elements[*it1].size() ); // make enough space
356 
357  it1=set_intersection(
358  node_elements[*it1].begin(), node_elements[*it1].end(),
359  node_elements[*it2].begin(), node_elements[*it2].end(),
360  intersection_element_list.begin());
361  intersection_element_list.resize(it1-intersection_element_list.begin()); // resize to true size
362 
363  for(;it2<nodes_list.end();++it2) {
364  it1=set_intersection(
365  intersection_element_list.begin(), intersection_element_list.end(),
366  node_elements[*it2].begin(), node_elements[*it2].end(),
367  intersection_element_list.begin());
368  intersection_element_list.resize(it1-intersection_element_list.begin()); // resize to true size
369  }
370  }
371 }
372 
373 
375  unsigned int dim, unsigned int &element_idx) {
376  bool is_neighbour = false;
377 
378  vector<unsigned int>::iterator e_dest=element_list.begin();
379  for( vector<unsigned int>::iterator ele = element_list.begin(); ele!=element_list.end(); ++ele)
380  if (elements[*ele].dim() == dim) { // keep only indexes of elements of same dimension
381  *e_dest=*ele;
382  ++e_dest;
383  } else if (elements[*ele].dim() == dim-1) { // get only first element of lower dimension
384  if (is_neighbour) xprintf(UsrErr, "Too matching elements id: %d and id: %d in the same mesh.\n",
385  elements(*ele).id(), elements(element_idx).id() );
386 
387  is_neighbour = true;
388  element_idx = *ele;
389  }
390  element_list.resize( e_dest - element_list.begin());
391  return is_neighbour;
392 }
393 
395  // 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)
396  unsigned int ni=0;
397  while ( ni < si->n_nodes()
398  && find(side_nodes.begin(), side_nodes.end(), node_vector.index( si->node(ni) ) ) != side_nodes.end() ) ni++;
399  return ( ni == si->n_nodes() );
400 }
401 
402 /**
403  * TODO:
404  * - use std::is_any for setting is_neigbour
405  * - possibly make appropriate constructors for Edge and Neighbour
406  * - check side!=-1 when searching neigbouring element
407  * - process bc_elements first, there should be no Neigh, but check it
408  * set Edge and boundary there
409  */
410 
412 {
413  Neighbour neighbour;
414  Edge *edg;
415  unsigned int ngh_element_idx, last_edge_idx;
416 
418 
419  // pointers to created edges
420  //vector<Edge *> tmp_edges;
421  edges.resize(0); // be sure that edges are empty
422 
424  vector<unsigned int> intersection_list; // list of elements in intersection of node element lists
425 
426  for( ElementFullIter bc_ele = bc_elements.begin(); bc_ele != bc_elements.end(); ++bc_ele) {
427  // Find all elements that share this side.
428  side_nodes.resize(bc_ele->n_nodes());
429  for (unsigned n=0; n<bc_ele->n_nodes(); n++) side_nodes[n] = node_vector.index(bc_ele->node[n]);
430  intersect_element_lists(side_nodes, intersection_list);
431  bool is_neighbour = find_lower_dim_element(element, intersection_list, bc_ele->dim() +1, ngh_element_idx);
432  if (is_neighbour) {
433  xprintf(UsrErr, "Boundary element (id: %d) match a regular element (id: %d) of lower dimension.\n",
434  bc_ele.id(), element(ngh_element_idx).id());
435  } else {
436  if (intersection_list.size() == 0) {
437  // no matching dim+1 element found
438  WarningOut().fmt("Lonely boundary element, id: {}, region: {}, dimension {}.\n",
439  bc_ele.id(), bc_ele->region().id(), bc_ele->dim());
440  continue; // skip the boundary element
441  }
442  last_edge_idx=edges.size();
443  edges.resize(last_edge_idx+1);
444  edg = &( edges.back() );
445  edg->n_sides = 0;
446  edg->side_ = new struct SideIter[ intersection_list.size() ];
447 
448  // common boundary object
449  unsigned int bdr_idx=boundary_.size();
450  boundary_.resize(bdr_idx+1);
451  Boundary &bdr=boundary_.back();
452  bdr.bc_ele_idx_ = bc_ele.index();
453  bdr.edge_idx_ = last_edge_idx;
454  bdr.mesh_=this;
455 
456  // for 1d boundaries there can be more then one 1d elements connected to the boundary element
457  // we do not detect this case later in the main search over bulk elements
458  for( vector<unsigned int>::iterator isect = intersection_list.begin(); isect!=intersection_list.end(); ++isect) {
459  Element *elem = &(element[*isect]);
460  for (unsigned int ecs=0; ecs<elem->n_sides(); ecs++) {
461  SideIter si = elem->side(ecs);
462  if ( same_sides( si, side_nodes) ) {
463  if (elem->edge_idx_[ecs] != Mesh::undef_idx) {
464  OLD_ASSERT(elem->boundary_idx_!=nullptr, "Null boundary idx array.\n");
465  int last_bc_ele_idx=this->boundary_[elem->boundary_idx_[ecs]].bc_ele_idx_;
466  int new_bc_ele_idx=bc_ele.index();
467  THROW( ExcDuplicateBoundary()
468  << EI_ElemLast(this->bc_elements.get_id(last_bc_ele_idx))
469  << EI_RegLast(this->bc_elements[last_bc_ele_idx].region().label())
470  << EI_ElemNew(this->bc_elements.get_id(new_bc_ele_idx))
471  << EI_RegNew(this->bc_elements[new_bc_ele_idx].region().label())
472  );
473  }
474  elem->edge_idx_[ecs] = last_edge_idx;
475  edg->side_[ edg->n_sides++ ] = si;
476 
477  if (elem->boundary_idx_ == NULL) {
478  elem->boundary_idx_ = new unsigned int [ elem->n_sides() ];
479  std::fill( elem->boundary_idx_, elem->boundary_idx_ + elem->n_sides(), Mesh::undef_idx);
480  }
481  elem->boundary_idx_[ecs] = bdr_idx;
482  break; // next element in intersection list
483  }
484  }
485  }
486 
487  }
488 
489  }
490  // Now we go through all element sides and create edges and neighbours
491  FOR_ELEMENTS( this, e )
492  {
493  for (unsigned int s=0; s<e->n_sides(); s++)
494  {
495  // skip sides that were already found
496  if (e->edge_idx_[s] != Mesh::undef_idx) continue;
497 
498 
499  // Find all elements that share this side.
500  side_nodes.resize(e->side(s)->n_nodes());
501  for (unsigned n=0; n<e->side(s)->n_nodes(); n++) side_nodes[n] = node_vector.index(e->side(s)->node(n));
502  intersect_element_lists(side_nodes, intersection_list);
503 
504  bool is_neighbour = find_lower_dim_element(element, intersection_list, e->dim(), ngh_element_idx);
505 
506  if (is_neighbour) { // edge connects elements of different dimensions
507  neighbour.element_ = &(element[ngh_element_idx]);
508  } else { // edge connects only elements of the same dimension
509  // Allocate the array of sides.
510  last_edge_idx=edges.size();
511  edges.resize(last_edge_idx+1);
512  edg = &( edges.back() );
513  edg->n_sides = 0;
514  edg->side_ = new struct SideIter[ intersection_list.size() ];
515  if (intersection_list.size() > max_edge_sides_[e->dim()-1])
516  max_edge_sides_[e->dim()-1] = intersection_list.size();
517 
518  if (intersection_list.size() == 1) { // outer edge, create boundary object as well
519  edg->n_sides=1;
520  edg->side_[0] = e->side(s);
521  e->edge_idx_[s] = last_edge_idx;
522 
523  if (e->boundary_idx_ == NULL) {
524  e->boundary_idx_ = new unsigned int [ e->n_sides() ];
525  std::fill( e->boundary_idx_, e->boundary_idx_ + e->n_sides(), Mesh::undef_idx);
526  }
527 
528  unsigned int bdr_idx=boundary_.size();
529  boundary_.resize(bdr_idx+1);
530  Boundary &bdr=boundary_.back();
531  e->boundary_idx_[s] = bdr_idx;
532 
533  // fill boundary element
534  ElementFullIter bc_ele = bc_elements.add_item( -bdr_idx ); // use negative bcd index as ID,
535  bc_ele->init(e->dim()-1, this, region_db_.implicit_boundary_region() );
536  region_db_.mark_used_region( bc_ele->region_idx_.idx() );
537  for(unsigned int ni = 0; ni< side_nodes.size(); ni++) bc_ele->node[ni] = &( node_vector[side_nodes[ni]] );
538 
539  // fill Boundary object
540  bdr.edge_idx_ = last_edge_idx;
541  bdr.bc_ele_idx_ = bc_ele.index();
542  bdr.mesh_=this;
543 
544  continue; // next side of element e
545  }
546  }
547 
548  // go through the elements connected to the edge or neighbour
549  for( vector<unsigned int>::iterator isect = intersection_list.begin(); isect!=intersection_list.end(); ++isect) {
550  Element *elem = &(element[*isect]);
551  for (unsigned int ecs=0; ecs<elem->n_sides(); ecs++) {
552  if (elem->edge_idx_[ecs] != Mesh::undef_idx) continue;
553  SideIter si = elem->side(ecs);
554  if ( same_sides( si, side_nodes) ) {
555  if (is_neighbour) {
556  // create a new edge and neighbour for this side, and element to the edge
557  last_edge_idx=edges.size();
558  edges.resize(last_edge_idx+1);
559  edg = &( edges.back() );
560  edg->n_sides = 1;
561  edg->side_ = new struct SideIter[1];
562  edg->side_[0] = si;
563  elem->edge_idx_[ecs] = last_edge_idx;
564 
565  neighbour.edge_idx_ = last_edge_idx;
566 
567  vb_neighbours_.push_back(neighbour); // copy neighbour with this edge setting
568  } else {
569  // connect the side to the edge, and side to the edge
570  edg->side_[ edg->n_sides++ ] = si;
571  elem->edge_idx_[ecs] = last_edge_idx;
572  }
573  break; // next element from intersection list
574  }
575  } // search for side of other connected element
576  } // connected elements
577  OLD_ASSERT( is_neighbour || ( (unsigned int) edg->n_sides ) == intersection_list.size(), "Some connected sides were not found.\n");
578  } // for element sides
579  } // for elements
580 
581  MessageOut().fmt( "Created {} edges and {} neighbours.\n", edges.size(), vb_neighbours_.size() );
582 }
583 
584 
585 
587 {
588  for (EdgeVector::iterator edg=edges.begin(); edg!=edges.end(); edg++)
589  {
590  // side 0 is reference, so its permutation is 0
591  edg->side(0)->element()->permutation_idx_[edg->side(0)->el_idx()] = 0;
592 
593  if (edg->n_sides > 1)
594  {
595  map<const Node*,unsigned int> node_numbers;
596  unsigned int permutation[edg->side(0)->n_nodes()];
597 
598  for (unsigned int i=0; i<edg->side(0)->n_nodes(); i++)
599  node_numbers[edg->side(0)->node(i)] = i;
600 
601  for (int sid=1; sid<edg->n_sides; sid++)
602  {
603  for (unsigned int i=0; i<edg->side(0)->n_nodes(); i++)
604  permutation[node_numbers[edg->side(sid)->node(i)]] = i;
605 
606  switch (edg->side(0)->dim())
607  {
608  case 0:
609  edg->side(sid)->element()->permutation_idx_[edg->side(sid)->el_idx()] = RefElement<1>::permutation_index(permutation);
610  break;
611  case 1:
612  edg->side(sid)->element()->permutation_idx_[edg->side(sid)->el_idx()] = RefElement<2>::permutation_index(permutation);
613  break;
614  case 2:
615  edg->side(sid)->element()->permutation_idx_[edg->side(sid)->el_idx()] = RefElement<3>::permutation_index(permutation);
616  break;
617  }
618  }
619  }
620  }
621 
622  for (vector<Neighbour>::iterator nb=vb_neighbours_.begin(); nb!=vb_neighbours_.end(); nb++)
623  {
624  map<const Node*,unsigned int> node_numbers;
625  unsigned int permutation[nb->element()->n_nodes()];
626 
627  // element of lower dimension is reference, so
628  // we calculate permutation for the adjacent side
629  for (unsigned int i=0; i<nb->element()->n_nodes(); i++)
630  node_numbers[nb->element()->node[i]] = i;
631 
632  for (unsigned int i=0; i<nb->side()->n_nodes(); i++)
633  permutation[node_numbers[nb->side()->node(i)]] = i;
634 
635  switch (nb->side()->dim())
636  {
637  case 0:
638  nb->side()->element()->permutation_idx_[nb->side()->el_idx()] = RefElement<1>::permutation_index(permutation);
639  break;
640  case 1:
641  nb->side()->element()->permutation_idx_[nb->side()->el_idx()] = RefElement<2>::permutation_index(permutation);
642  break;
643  case 2:
644  nb->side()->element()->permutation_idx_[nb->side()->el_idx()] = RefElement<3>::permutation_index(permutation);
645  break;
646  }
647  }
648 }
649 
650 
651 
652 
653 
654 //=============================================================================
655 //
656 //=============================================================================
658 {
659 
660  //MessageOut() << "Element to neighbours of vb2 type... "/*orig verb 5*/;
661 
662  FOR_ELEMENTS(this,ele) ele->n_neighs_vb =0;
663 
664  // count vb neighs per element
665  FOR_NEIGHBOURS(this, ngh ) ngh->element_->n_neighs_vb++;
666 
667  // Allocation of the array per element
668  FOR_ELEMENTS(this, ele )
669  if( ele->n_neighs_vb > 0 ) {
670  ele->neigh_vb = new struct Neighbour* [ele->n_neighs_vb];
671  ele->n_neighs_vb=0;
672  }
673 
674  // fill
675  ElementIter ele;
676  FOR_NEIGHBOURS(this, ngh ) {
677  ele = ngh->element();
678  ele->neigh_vb[ ele->n_neighs_vb++ ] = &( *ngh );
679  }
680 
681  //MessageOut() << "... O.K.\n"/*orig verb 6*/;
682 }
683 
684 
685 
686 
687 
688 
690  /* Algorithm:
691  *
692  * 1) create BIH tree
693  * 2) for every 1D, find list of candidates
694  * 3) compute intersections for 1d, store it to master_elements
695  *
696  */
697  if (! intersections) {
698  intersections = std::make_shared<MixedMeshIntersections>(this);
699  intersections->compute_intersections();
700  }
701  return *intersections;
702 }
703 
704 
705 
706 ElementAccessor<3> Mesh::element_accessor(unsigned int idx, bool boundary) {
707  return ElementAccessor<3>(this, idx, boundary);
708 }
709 
710 
711 
712 vector<int> const & Mesh::elements_id_maps( bool boundary_domain) const
713 {
714  if (bulk_elements_id_.size() ==0) {
716  int last_id;
717 
718  bulk_elements_id_.resize(n_elements());
719  map_it = bulk_elements_id_.begin();
720  last_id = -1;
721  for(unsigned int idx=0; idx < element.size(); idx++, ++map_it) {
722  int id = element.get_id(idx);
723  if (last_id >= id) xprintf(UsrErr, "Element IDs in non-increasing order, ID: %d\n", id);
724  last_id=*map_it = id;
725  }
726 
728  map_it = boundary_elements_id_.begin();
729  last_id = -1;
730  for(unsigned int idx=0; idx < bc_elements.size(); idx++, ++map_it) {
731  int id = bc_elements.get_id(idx);
732  // We set ID for boundary elements created by the mesh itself to "-1"
733  // this force gmsh reader to skip all remaining entries in boundary_elements_id_
734  // and thus report error for any remaining data lines
735  if (id < 0) last_id=*map_it=-1;
736  else {
737  if (last_id >= id) xprintf(UsrErr, "Element IDs in non-increasing order, ID: %d\n", id);
738  last_id=*map_it = id;
739  }
740  }
741  }
742 
743  if (boundary_domain) return boundary_elements_id_;
744  return bulk_elements_id_;
745 }
746 
748 {
750  it != region_list.end();
751  ++it) {
752  // constructor has side effect in the mesh - create new region or set and store them to Mesh::region_db_
753  (*it).factory< RegionSetBase, const Input::Record &, Mesh * >(*it, this);
754  }
755 }
756 
758 {
760  region_db_.el_to_reg_map_.clear();
761  region_db_.close();
763 
764  if ( in_record_.val<bool>("print_regions") ) {
765  stringstream ss;
767  MessageOut() << ss.str();
768  }
769 }
770 
771 
773  START_TIMER("Mesh::compute_element_boxes");
774  if (element_box_.size() > 0) return;
775 
776  // make element boxes
777  element_box_.resize(this->element.size());
778  unsigned int i=0;
779  FOR_ELEMENTS(this, element) {
780  element_box_[i] = element->bounding_box();
781  i++;
782  }
783 
784  // make mesh box
785  Node* node = this->node_vector.begin();
786  mesh_box_ = BoundingBox(node->point(), node->point());
787  FOR_NODES(this, node ) {
788  mesh_box_.expand( node->point() );
789  }
790 
791 }
792 
794  if (! this->bih_tree_)
795  bih_tree_ = std::make_shared<BIHTree>(this);
796  return *bih_tree_;
797 }
798 
800  return in_record_.val<double>("global_observe_search_radius");
801 }
802 
803 //-----------------------------------------------------------------------------
804 // vim: set cindent:
int n_triangles
Definition: mesh.h:272
Distribution * el_ds
Parallel distribution of elements.
Definition: mesh.h:431
Class for the mesh partitioning. This should provide:
Definition: partitioning.hh:39
Mesh(Input::Record in_record, MPI_Comm com=MPI_COMM_WORLD)
Definition: mesh.cc:101
Iterator< ValueType > begin() const
void read_stream(istream &in, const Type::TypeBase &root_type, FileFormat format)
This method actually reads the given stream in.
Bounding box in 3d ambient space.
Definition: bounding_box.hh:45
#define FOR_ELEMENT_NODES(i, j)
Definition: elements.h:155
vector< vector< unsigned int > > node_elements
Definition: mesh.h:306
Accessor to input data conforming to declared Array.
Definition: accessors.hh:561
unsigned int * boundary_idx_
Definition: elements.h:94
int get_id(const T *it) const
Definition: sys_vector.hh:458
void count_side_types()
Definition: mesh.cc:320
int MPI_Comm
Definition: mpi.h:141
Definition: nodes.hh:32
void check_and_finish()
Definition: mesh.cc:757
MapElementIDToRegionID el_to_reg_map_
Definition: region.hh:570
Reader for (slightly) modified input files.
MixedMeshIntersections & mixed_intersections()
Definition: mesh.cc:689
Class Input::Type::Default specifies default value of keys of a Input::Type::Record.
Definition: type_record.hh:56
#define FOR_ELEMENTS(_mesh_, __i)
Definition: mesh.h:444
Class for declaration of the input of type Bool.
Definition: type_base.hh:452
#define MessageOut()
Macro defining &#39;message&#39; record of log.
Definition: logger.hh:241
unsigned int * permutation_idx_
Definition: elements.h:103
Definition: abscissa.h:25
int n_lines
Definition: mesh.h:271
static const Input::Type::Record & get_input_type()
Definition: partitioning.cc:45
static const unsigned int undef_idx
Definition: mesh.h:121
#define INPUT_CATCH(ExceptionType, AddressEITag, input_accessor)
Definition: accessors.hh:57
void create_node_element_lists()
Definition: mesh.cc:333
static unsigned int permutation_index(unsigned int p[n_nodes_per_side])
Definition: ref_element.cc:493
static const Input::Type::Record & get_input_type()
Definition: mesh.cc:78
static Default obligatory()
The factory function to make an empty default value which is obligatory.
Definition: type_record.hh:105
std::shared_ptr< MixedMeshIntersections > intersections
Definition: mesh.h:254
unsigned int max_edge_sides_[3]
Maximal number of sides per one edge in the actual mesh (set in make_neighbours_and_edges()).
Definition: mesh.h:383
BoundingBox mesh_box_
Bounding box of whole mesh.
Definition: mesh.h:399
void expand(const Point &point)
Definition: mesh.h:95
int index() const
Definition: sys_vector.hh:78
Input::Record in_record_
Definition: mesh.h:410
Node ** node
Definition: elements.h:90
FullIter add_item(int id)
Definition: sys_vector.hh:359
int n_sides
Definition: edges.h:36
vector< vector< vector< unsigned int > > > side_nodes
Definition: mesh.h:284
FullIter find_id(const int id)
Definition: sys_vector.hh:434
Definition: edges.h:26
int n_tetrahedras
Definition: mesh.h:273
ElementAccessor< 3 > element_accessor(unsigned int idx, bool boundary=false)
Definition: mesh.cc:706
vector< Boundary > boundary_
Definition: mesh.h:239
Partitioning * get_part()
Definition: mesh.cc:217
unsigned int n_sides()
Definition: mesh.cc:198
Record & close() const
Close the Record for further declarations of keys.
Definition: type_record.cc:301
Class for declaration of inputs sequences.
Definition: type_base.hh:339
int * el_4_loc
Index set assigning to local element index its global index.
Definition: mesh.h:429
void compute_element_boxes()
Precompute element bounding boxes if it is not done yet.
Definition: mesh.cc:772
int * row_4_el
Index set assigning to global element index the local index used in parallel vectors.
Definition: mesh.h:427
int n_exsides
Definition: mesh.h:268
IteratorBase end() const
Region get_region(unsigned int id, unsigned int dim)
Definition: region.cc:150
unsigned int dim() const
unsigned int size() const
Returns size of the container. This is independent of the allocated space.
Definition: sys_vector.hh:391
static Default optional()
The factory function to make an empty default value which is optional.
Definition: type_record.hh:119
#define OLD_ASSERT(...)
Definition: global_defs.h:131
bool opt_val(const string &key, Ret &value) const
unsigned int edge_idx_
Definition: neighbours.h:135
unsigned int * edge_idx_
Definition: elements.h:93
void read_regions_from_input(Input::Array region_list)
Definition: mesh.cc:747
virtual Record & allow_auto_conversion(const string &from_key)
Allows shorter input of the Record providing only value of the from_key given as the parameter...
Definition: type_record.cc:130
unsigned int n_elements() const
Definition: mesh.h:146
bool same_sides(const SideIter &si, vector< unsigned int > &side_nodes)
Definition: mesh.cc:394
Class for declaration of the input data that are floating point numbers.
Definition: type_base.hh:534
std::vector< T >::iterator iterator
Definition: sys_vector.hh:215
vector< int > const & elements_id_maps(bool boundary_domain) const
Definition: mesh.cc:712
void setup_topology()
Definition: mesh.cc:292
IntersectionSearch get_intersection_search()
Getter for input type selection for intersection search algorithm.
Definition: mesh.cc:121
Neighbour ** neigh_vb
Definition: elements.h:133
T get_root_interface() const
Returns the root accessor.
friend class RegionSetBase
Definition: mesh.h:418
static const Input::Type::Selection & get_input_intersection_variant()
The definition of input record for selection of variant of file format.
Definition: mesh.cc:67
static FileName input()
The factory function for declaring type FileName for input files.
Definition: type_base.cc:501
Accessor to the data with type Type::Record.
Definition: accessors.hh:286
#define NDEF
Definition: mesh.cc:63
const Ret val(const string &key) const
unsigned int n_sides() const
#define xprintf(...)
Definition: system.hh:87
#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
Selection & add_value(const int value, const std::string &key, const std::string &description="", TypeBase::attribute_map attributes=TypeBase::attribute_map())
Adds one new value with name given by key to the Selection.
unsigned int n_corners()
Definition: mesh.cc:207
unsigned int index(const T *pointer) const
Definition: sys_vector.hh:373
#define FOR_NEIGHBOURS(_mesh_, it)
Definition: mesh.h:495
Record & declare_key(const string &key, std::shared_ptr< TypeBase > type, const Default &default_value, const string &description, TypeBase::attribute_map key_attributes=TypeBase::attribute_map())
Declares a new key of the Record.
Definition: type_record.cc:488
ElementVector bc_elements
Definition: mesh.h:243
void close()
Definition: region.cc:249
SideIter side(const unsigned int loc_index)
FullIter begin()
Definition: sys_vector.hh:383
bool is_empty() const
Definition: accessors.hh:360
Region implicit_boundary_region()
Definition: region.cc:75
std::shared_ptr< BIHTree > bih_tree_
Definition: mesh.h:404
#define FOR_NODES(_mesh_, i)
Definition: mesh.h:56
unsigned int edge_idx_
Definition: boundaries.h:75
void read_mesh(Mesh *mesh)
Accessor to the polymorphic input data of a type given by an AbstracRecord object.
Definition: accessors.hh:453
vector< int > boundary_elements_id_
Definition: mesh.h:378
unsigned int bc_ele_idx_
Definition: boundaries.h:76
void count_element_types()
Definition: mesh.cc:226
const BIHTree & get_bih_tree()
Getter for BIH. Creates and compute BIH at first call.
Definition: mesh.cc:793
void check_regions()
Definition: region.cc:461
Dedicated class for storing path to input and output files.
Definition: file_path.hh:48
Definition: system.hh:59
void read_gmsh_from_stream(istream &in)
Definition: mesh.cc:242
void mark_used_region(unsigned int idx)
Definition: region.cc:235
void print_region_table(ostream &stream) const
Definition: region.cc:409
Support classes for parallel programing.
vector< Neighbour > vb_neighbours_
Definition: mesh.h:265
FinishStatus finish(FinishStatus finish_type=FinishStatus::regular_) override
Finish declaration of the Record type.
Definition: type_record.cc:240
int n_sides_
Definition: mesh.h:269
RegionIdx region_idx_
Definition: elements.h:141
void read_physical_names(Mesh *mesh)
const Selection & close() const
Close the Selection, no more values can be added.
RegionDB region_db_
Definition: mesh.h:389
std::vector< Edge > edges
Vector of MH edges, this should not be part of the geometrical mesh.
Definition: mesh.h:246
MPI_Comm comm_
Definition: mesh.h:415
unsigned int n_neighs_vb
Definition: elements.h:131
int n_insides
Definition: mesh.h:267
void intersect_element_lists(vector< unsigned int > const &nodes_list, vector< unsigned int > &intersection_element_list)
Definition: mesh.cc:346
void modify_element_ids(const RegionDB::MapElementIDToRegionID &map)
Definition: mesh.cc:282
#define WarningOut()
Macro defining &#39;warning&#39; record of log.
Definition: logger.hh:244
void make_edge_permutations()
Definition: mesh.cc:586
Class RefElement defines numbering of vertices, sides, calculation of normal vectors etc...
static Input::Type::Abstract & get_input_type()
Definition: region_set.cc:25
Mesh * mesh_
Definition: boundaries.h:77
unsigned int n_nodes() const
Definition: mesh.h:142
Record type proxy class.
Definition: type_record.hh:177
ElementIter element_
Definition: neighbours.h:136
Base of exceptions used in Flow123d.
Definition: exceptions.hh:67
IntersectionSearch
Types of search algorithm for finding intersection candidates.
Definition: mesh.h:110
SideIter * side_
Definition: edges.h:37
void element_to_neigh_vb()
Definition: mesh.cc:657
const Node * node(unsigned int i) const
Definition: side_impl.hh:46
arma::vec3 & point()
Definition: nodes.hh:68
void reinit(Input::Record in_record)
Definition: mesh.cc:127
FullIter end()
Returns FullFullIterer of the fictions past the end element.
Definition: sys_vector.hh:387
#define FOR_SIDES(_mesh_, it)
Definition: mesh.h:488
void init_from_input()
Definition: mesh.cc:256
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
Definition: exceptions.hh:45
bool find_lower_dim_element(ElementVector &elements, vector< unsigned int > &element_list, unsigned int dim, unsigned int &element_idx)
Definition: mesh.cc:374
vector< int > bulk_elements_id_
Definition: mesh.h:378
Template for classes storing finite set of named values.
std::shared_ptr< Partitioning > part_
Definition: mesh.h:393
void make_neighbours_and_edges()
Definition: mesh.cc:411
NodeVector node_vector
Vector of nodes of the mesh.
Definition: mesh.h:233
double global_observe_radius() const
Maximal distance of observe point from Mesh relative to its size.
Definition: mesh.cc:799
Main class for computation of intersection of meshes of combined dimensions.
ElementVector element
Vector of elements of the mesh.
Definition: mesh.h:235
unsigned int n_nodes() const
Definition: side_impl.hh:33
~Mesh()
Destructor.
Definition: mesh.cc:172
unsigned int idx() const
Returns a global index of the region.
Definition: region.hh:81
std::vector< BoundingBox > element_box_
Auxiliary vector of mesh elements bounding boxes.
Definition: mesh.h:396