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