Flow123d  JS_before_hm-1788-g649f0a9d1
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 
20 #include <unistd.h>
21 #include <set>
22 #include <unordered_map>
23 
24 #include "system/system.hh"
25 #include "system/exceptions.hh"
26 #include "system/index_types.hh"
28 #include "input/input_type.hh"
29 #include "input/accessors.hh"
30 #include "system/sys_profiler.hh"
31 #include "la/distribution.hh"
32 
33 #include "mesh/mesh.h"
34 #include "mesh/bc_mesh.hh"
35 #include "mesh/ref_element.hh"
36 #include "mesh/region_set.hh"
37 #include "mesh/range_wrapper.hh"
38 
39 // think about following dependencies
40 #include "mesh/accessors.hh"
41 #include "mesh/node_accessor.hh"
42 #include "mesh/partitioning.hh"
43 #include "mesh/neighbours.h"
44 
45 
46 #include "mesh/bih_tree.hh"
47 #include "mesh/duplicate_nodes.h"
48 #include "mesh/mesh_optimizer.hh"
49 
51 
52 
53 
54 //TODO: sources, concentrations, initial condition and similarly boundary conditions should be
55 // instances of a Element valued field
56 // concentrations is in fact reimplemented in transport REMOVE it HERE
57 
58 // After removing non-geometrical things from mesh, this should be part of mash initializing.
59 #include "mesh/region.hh"
60 
61 #define NDEF -1
62 
63 namespace IT = Input::Type;
64 
66  return Input::Type::Selection("Types of search algorithm for finding intersection candidates.")
67  .add_value(Mesh::BIHsearch, "BIHsearch",
68  "Use BIH for finding initial candidates, then continue by prolongation.")
69  .add_value(Mesh::BIHonly, "BIHonly",
70  "Use BIH for finding all candidates.")
71  .add_value(Mesh::BBsearch, "BBsearch",
72  "Use bounding boxes for finding initial candidates, then continue by prolongation.")
73  .close();
74 }
75 
77  return IT::Record("Mesh","Record with mesh related data." )
78  .allow_auto_conversion("mesh_file")
80  "Input file with mesh description.")
82  "List of additional region and region set definitions not contained in the mesh. "
83  "There are three region sets implicitly defined:\n\n"
84  "- ALL (all regions of the mesh)\n"
85  "- .BOUNDARY (all boundary regions)\n"
86  "- BULK (all bulk regions)")
87  .declare_key("partitioning", Partitioning::get_input_type(), IT::Default("\"any_neighboring\""), "Parameters of mesh partitioning algorithms.\n" )
88  .declare_key("print_regions", IT::Bool(), IT::Default("true"), "If true, print table of all used regions.")
89  .declare_key("intersection_search", Mesh::get_input_intersection_variant(),
90  IT::Default("\"BIHsearch\""), "Search algorithm for element intersections.")
91  .declare_key("global_snap_radius", IT::Double(0.0), IT::Default("1E-3"),
92  "Maximal snapping distance from the mesh in various search operations. In particular, it is used "
93  "to find the closest mesh element of an observe point; and in FieldFormula to find closest surface "
94  "element in plan view (Z projection).")
96  "Output file with neighboring data from mesh.")
97  .declare_key("optimize_mesh", IT::Bool(), IT::Default("true"), "If true, permute nodes and elements in order to increase cache locality. "
98  "This will speed up the calculations. GMSH output preserves original ordering but is slower. All variants of VTK output use the permuted.")
99  .close();
100 }
101 
102 //const unsigned int Mesh::undef_idx;
103 
105 : tree(nullptr),
106  comm_(MPI_COMM_WORLD),
107  bulk_size_(0),
108  nodes_(3, 1, 0),
109  row_4_el(nullptr),
110  el_4_loc(nullptr),
111  el_ds(nullptr),
112  node_4_loc_(nullptr),
113  node_ds_(nullptr),
114  bc_mesh_(nullptr)
115 
116 {init();}
117 
118 
119 
121 : tree(nullptr),
122  optimize_memory_locality(true),
123  in_record_(in_record),
124  comm_(com),
125  bulk_size_(0),
126  nodes_(3, 1, 0),
127  row_4_el(nullptr),
128  el_4_loc(nullptr),
129  el_ds(nullptr),
130  node_4_loc_(nullptr),
131  node_ds_(nullptr),
132  bc_mesh_(nullptr)
133 {
134 
135  init();
136 }
137 
138 
140  : tree(nullptr),
141  optimize_memory_locality(other.optimize_memory_locality),
142  in_record_(other.in_record_),
143  comm_(other.comm_),
144  bulk_size_(0),
145  nodes_(3, 1, 0),
146  row_4_el(nullptr),
147  el_4_loc(nullptr),
148  el_ds(nullptr),
149  node_4_loc_(nullptr),
150  node_ds_(nullptr),
151  bc_mesh_(nullptr)
152 {
153  init();
154 }
155 
156 
157 
159 {
160  return in_record_.val<Mesh::IntersectionSearch>("intersection_search");
161 }
162 
163 
165 {
166  // set in_record_, if input accessor is empty
167  if (in_record_.is_empty()) {
168  istringstream is("{mesh_file=\"\", optimize_mesh=false}");
169  Input::ReaderToStorage reader;
170  IT::Record &in_rec = const_cast<IT::Record &>(Mesh::get_input_type());
171  in_rec.finish();
172  reader.read_stream(is, in_rec, Input::FileFormat::format_JSON);
174  }
175 
176  optimize_memory_locality = in_record_.val<bool>("optimize_mesh");
177 
178  n_insides = NDEF;
179  n_exsides = NDEF;
180  n_sides_ = NDEF;
181 
182  for (int d=0; d<3; d++) max_edge_sides_[d] = 0;
183 
184  // Initialize numbering of nodes on sides.
185  // This is temporary solution, until class Element is templated
186  // by dimension. Then we can replace Mesh::side_nodes by
187  // RefElement<dim>::side_nodes.
188 
189  // indices of side nodes in element node array
190  // Currently this is made ad libitum
191  // with some ordering here we can get sides with correct orientation.
192  // This speedup normal calculation.
193 
194  side_nodes.resize(3); // three side dimensions
195  for(int dim=0; dim < 3; dim++) {
196  side_nodes[dim].resize(dim+2); // number of sides
197  for(int i_side=0; i_side < dim+2; i_side++)
198  side_nodes[dim][i_side].resize(dim+1);
199  }
200 
201  for (unsigned int sid=0; sid<RefElement<1>::n_sides; sid++)
202  for (unsigned int nid=0; nid<RefElement<1>::n_nodes_per_side; nid++)
203  side_nodes[0][sid][nid] = RefElement<1>::interact(Interaction<0,0>(sid))[nid];
204 
205  for (unsigned int sid=0; sid<RefElement<2>::n_sides; sid++)
206  for (unsigned int nid=0; nid<RefElement<2>::n_nodes_per_side; nid++)
207  side_nodes[1][sid][nid] = RefElement<2>::interact(Interaction<0,1>(sid))[nid];
208 
209  for (unsigned int sid=0; sid<RefElement<3>::n_sides; sid++)
210  for (unsigned int nid=0; nid<RefElement<3>::n_nodes_per_side; nid++)
211  side_nodes[2][sid][nid] = RefElement<3>::interact(Interaction<0,2>(sid))[nid];
212 }
213 
214 
216  for(EdgeData &edg : this->edges)
217  if (edg.side_) delete[] edg.side_;
218 
219  for (unsigned int idx=0; idx < bulk_size_; idx++) {
220  Element *ele=&(element_vec_[idx]);
221  if (ele->boundary_idx_) delete[] ele->boundary_idx_;
222  if (ele->neigh_vb) delete[] ele->neigh_vb;
223  }
224 
225  for(unsigned int idx=bulk_size_; idx < element_vec_.size(); idx++) {
226  Element *ele=&(element_vec_[idx]);
227  if (ele->boundary_idx_) delete[] ele->boundary_idx_;
228  }
229 
230  if (row_4_el != nullptr) delete[] row_4_el;
231  if (el_4_loc != nullptr) delete[] el_4_loc;
232  if (el_ds != nullptr) delete el_ds;
233  if (node_4_loc_ != nullptr) delete[] node_4_loc_;
234  if (node_ds_ != nullptr) delete node_ds_;
235  if (bc_mesh_ != nullptr) delete bc_mesh_;
236  if (tree != nullptr) delete tree;
237 }
238 
239 
240 unsigned int Mesh::n_sides() const
241 {
242  if (n_sides_ == NDEF) {
243  n_sides_=0;
244  for (auto ele : this->elements_range()) n_sides_ += ele->n_sides();
245  }
246  return n_sides_;
247 }
248 
249 unsigned int Mesh::n_vb_neighbours() const {
250  return vb_neighbours_.size();
251  }
252 
253 
254 unsigned int Mesh::n_corners() {
255  unsigned int li, count = 0;
256  for (auto ele : this->elements_range()) {
257  for (li=0; li<ele->n_nodes(); li++) {
258  count++;
259  }
260  }
261  return count;
262 }
263 
264 Edge Mesh::edge(uint edge_idx) const
265 {
266  ASSERT_LT_DBG(edge_idx, edges.size());
267  return Edge(this, edge_idx);
268 }
269 
271 {
272  ASSERT_LT_DBG(bc_idx, boundary_.size());
273  return Boundary(&boundary_[bc_idx]);
274 }
275 
277  return part_.get();
278 }
279 
281  return (LongIdx*)this->get_part()->get_loc_part();
282 }
283 
284 
285 
286 
288 
289  // get dim of the first element in the map, if it exists
290  uint dim_to_check = RegionDB::undefined_dim;
291  std::string reg_name = "UndefinedRegion";
292  if(map.size() > 0){
293  Element &ele = element_vec_[ elem_index(map.begin()->first) ];
294  dim_to_check = ele.dim();
295  reg_name = region_db_.find_id(map.begin()->second).label();
296  }
297 
298  for (auto elem_to_region : map) {
299  Element &ele = element_vec_[ elem_index(elem_to_region.first) ];
300 
301  if( ele.dim() != dim_to_check){
302  THROW(ExcRegionElmDiffDim() << EI_Region(reg_name) << EI_RegIdx(elem_to_region.second) << EI_Dim(dim_to_check)
303  << EI_DimOther(ele.dim()) << EI_ElemId(elem_to_region.first) );
304  }
305 
306  ele.region_idx_ = region_db_.get_region( elem_to_region.second, ele.dim() );
308  }
309 }
310 
311 
313  std::vector<uint> nodes_new_idx( this->n_nodes(), undef_idx );
314 
315  // check element quality and flag used nodes
316  for (auto ele : this->elements_range()) {
317  // element quality
318  double quality = ele.quality_measure_smooth();
319  if (quality < 0) {
320  ASSERT_LT_DBG(ele.jacobian_S3(), 0);
321  element_vec_[ele.mesh_idx()].inverted = true;
322  quality = -quality;
323  }
324  if (quality < 4*std::numeric_limits<double>::epsilon())
325  THROW( ExcBadElement() << EI_Quality(quality) << EI_ElemId(ele.idx()) );
326  if ( quality< 0.001)
327  WarningOut().fmt("Bad quality element ID={}, ({}<0.001).\n", ele.idx(), quality);
328 
329  // flag used nodes
330  for (uint ele_node=0; ele_node<ele->n_nodes(); ele_node++) {
331  uint inode = ele->node_idx(ele_node);
332  nodes_new_idx[inode] = inode;
333  }
334  }
335 
336  // possibly build new node ids map
337  BidirectionalMap<int> new_node_ids_;
338  new_node_ids_.reserve(node_ids_.size());
339 
340  // remove unused nodes from the mesh
341  uint inode_new = 0;
342  for(uint inode = 0; inode < nodes_new_idx.size(); inode++) {
343  if(nodes_new_idx[inode] == undef_idx){
344  WarningOut().fmt("A node {} does not belong to any element "
345  " and will be removed.",
346  find_node_id(inode));
347  }
348  else{
349  // map new node numbering
350  nodes_new_idx[inode] = inode_new;
351 
352  // possibly move the nodes
353  nodes_.vec<3>(inode_new) = nodes_.vec<3>(inode);
354  new_node_ids_.add_item(node_ids_[inode]);
355 
356  inode_new++;
357  }
358  }
359 
360  uint n_nodes_new = inode_new;
361 
362  // if some node erased, update node ids in elements
363  if(n_nodes_new < nodes_new_idx.size()){
364 
365  DebugOut() << "Updating node-element numbering due to unused nodes: "
366  << print_var(n_nodes_new) << print_var(nodes_new_idx.size()) << "\n";
367 
368  // throw away unused nodes
369  nodes_.resize(n_nodes_new);
370  node_ids_ = new_node_ids_;
371 
372  // update node-element numbering
373  for (auto ele : this->elements_range()) {
374  for (uint ele_node=0; ele_node<ele->n_nodes(); ele_node++) {
375  uint inode_orig = ele->node_idx(ele_node);
376  uint inode = nodes_new_idx[inode_orig];
377  ASSERT_DBG(inode != undef_idx);
378  const_cast<Element*>(ele.element())->nodes_[ele_node] = inode;
379  }
380  }
381  }
382 }
383 
384 
385 //void Mesh::array_sort(std::array<uint, 4> &nodes) {
386 // // TODO: use templated insert sort with recursion over length of array so that compiler can
387 // // optimize for the small array size.
388 //
389 // std::sort(nodes.begin(), nodes.end());
390 //}
391 
393  // element_vec_ still contains both bulk and boundary elements
394  for (uint i_el=0; i_el < element_vec_.size(); i_el++) {
395  Element &ele = element_vec_[i_el];
396  std::sort(ele.nodes_.begin(), ele.nodes_.end());
397  }
398 
399 }
400 
403  START_TIMER("MESH - optimizer");
404  this->optimize();
405  END_TIMER("MESH - optimizer");
406  }
407 
408  START_TIMER("MESH - setup topology");
409 
410  canonical_faces();
412 
413 
417 
418  tree = new DuplicateNodes(this);
419 
420  part_ = std::make_shared<Partitioning>(this, in_record_.val<Input::Record>("partitioning") );
421 
422  // create parallel distribution and numbering of elements
423  LongIdx *id_4_old = new LongIdx[n_elements()];
424  int i = 0;
425  for (auto ele : this->elements_range())
426  id_4_old[i++] = ele.idx();
427  part_->id_maps(n_elements(), id_4_old, el_ds, el_4_loc, row_4_el);
428 
429  delete[] id_4_old;
430 
431  this->distribute_nodes();
432 
434 }
435 
436 
438  MeshOptimizer<3> mo(this);
439  mo.calculate_sizes();
442 
443  this->sort_permuted_nodes_elements( mo.sort_nodes(this->node_permutation_), mo.sort_elements(this->elem_permutation_) );
444 }
445 
446 
448  BidirectionalMap<int> node_ids_backup = this->node_ids_;
449  this->node_ids_.clear();
450  this->node_ids_.reserve(this->n_nodes());
451  Armor::Array<double> nodes_backup = this->nodes_;
452  for (uint i = 0; i < this->element_vec_.size(); ++i) {
453  for (uint j = 0; j < this->element_vec_[i].dim() + 1; ++j) {
454  this->element_vec_[i].nodes_[j] = this->node_permutation_[this->element_vec_[i].nodes_[j]];
455  }
456  }
457  for (uint i = 0; i < this->n_nodes(); ++i) {
458  this->nodes_.set(node_permutation_[i]) = nodes_backup.vec<3>(i);
459  this->node_ids_.add_item( node_ids_backup[new_node_ids[i]] );
460  }
461 
462  BidirectionalMap<int> elem_ids_backup = this->element_ids_;
463  this->element_ids_.clear();
465  std::vector<Element> elements_backup = this->element_vec_;
466  for (uint i = 0; i < bulk_size_; ++i) {
467  this->element_vec_[elem_permutation_[i]] = elements_backup[i];
468  this->element_ids_.add_item( elem_ids_backup[new_elem_ids[i]] );
469  }
470 }
471 
472 
473 //
475 {
476 
477  n_insides = 0;
478  n_exsides = 0;
479  for (auto ele : this->elements_range())
480  for(SideIter sde = ele.side(0); sde->side_idx() < ele->n_sides(); ++sde) {
481  if (sde->is_external()) n_exsides++;
482  else n_insides++;
483  }
484 }
485 
486 
487 
489  // for each node we make a list of elements that use this node
490  node_elements_.resize( this->n_nodes() );
491 
492  for (auto ele : this->elements_range())
493  for (unsigned int n=0; n<ele->n_nodes(); n++)
494  node_elements_[ele.node(n).idx()].push_back(ele.idx());
495 
496  for (vector<vector<unsigned int> >::iterator n=node_elements_.begin(); n!=node_elements_.end(); n++)
497  stable_sort(n->begin(), n->end());
498 }
499 
500 
501 void Mesh::intersect_element_lists(vector<unsigned int> const &nodes_list, vector<unsigned int> &intersection_element_list)
502 {
503  if (node_elements_.size() == 0) {
505  }
506 
507  if (nodes_list.size() == 0) {
508  intersection_element_list.clear();
509  } else if (nodes_list.size() == 1) {
510  intersection_element_list = node_elements_[ nodes_list[0] ];
511  } else {
512  vector<unsigned int>::const_iterator it1=nodes_list.begin();
514  intersection_element_list.resize( node_elements_[*it1].size() ); // make enough space
515 
516  it1=set_intersection(
517  node_elements_[*it1].begin(), node_elements_[*it1].end(),
518  node_elements_[*it2].begin(), node_elements_[*it2].end(),
519  intersection_element_list.begin());
520  intersection_element_list.resize(it1-intersection_element_list.begin()); // resize to true size
521 
522  for(;it2<nodes_list.end();++it2) {
523  it1=set_intersection(
524  intersection_element_list.begin(), intersection_element_list.end(),
525  node_elements_[*it2].begin(), node_elements_[*it2].end(),
526  intersection_element_list.begin());
527  intersection_element_list.resize(it1-intersection_element_list.begin()); // resize to true size
528  }
529  }
530 }
531 
532 
533 bool Mesh::find_lower_dim_element( vector<unsigned int> &element_list, unsigned int dim, unsigned int &element_idx) {
534  bool is_neighbour = false;
535 
536  vector<unsigned int>::iterator e_dest=element_list.begin();
537  for( vector<unsigned int>::iterator ele = element_list.begin(); ele!=element_list.end(); ++ele) {
538  //DebugOut() << "Eid: " << this->elem_index(*ele)
539  // << format(element_vec_[*ele].nodes_);
540 
541  if (element_vec_[*ele].dim() == dim) { // keep only indexes of elements of same dimension
542  *e_dest=*ele;
543  ++e_dest;
544  } else if (element_vec_[*ele].dim() == dim-1) { // get only first element of lower dimension
545  if (is_neighbour) THROW(ExcTooMatchingIds() << EI_ElemId(this->elem_index(*ele)) << EI_ElemIdOther(this->elem_index(element_idx)) );
546 
547  is_neighbour = true;
548  element_idx = *ele;
549  }
550  }
551  element_list.resize( e_dest - element_list.begin());
552  return is_neighbour;
553 }
554 
555 bool Mesh::same_sides(const SideIter &si, vector<unsigned int> &side_nodes) {
556  // 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)
557  unsigned int ni=0;
558  while ( ni < si->n_nodes()
559  && find(side_nodes.begin(), side_nodes.end(), si->node(ni).idx() ) != side_nodes.end() ) ni++;
560  return ( ni == si->n_nodes() );
561 }
562 
563 /**
564  * TODO:
565  * - use std::is_any for setting is_neigbour
566  * - possibly make appropriate constructors for Edge and Neighbour
567  * - check side!=-1 when searching neigbouring element
568  * - process boundary elements first, there should be no Neigh, but check it
569  * set Edge and boundary there
570  */
571 
573 {
574  ASSERT(bc_element_tmp_.size()==0)
575  .error("Temporary structure of boundary element data is not empty. Did you call create_boundary_elements?");
576 
577  Neighbour neighbour;
578  EdgeData *edg = nullptr;
579  unsigned int ngh_element_idx;
580  unsigned int last_edge_idx = undef_idx;
581 
582  neighbour.mesh_ = this;
583 
585 
586  // pointers to created edges
587  //vector<Edge *> tmp_edges;
588  edges.resize(0); // be sure that edges are empty
589 
591  vector<unsigned int> intersection_list; // list of elements in intersection of node element lists
592 
593  for( unsigned int i=bulk_size_; i<element_vec_.size(); ++i) {
594 
595  ElementAccessor<3> bc_ele = this->element_accessor(i);
596  ASSERT(bc_ele.region().is_boundary());
597  // Find all elements that share this side.
598  side_nodes.resize(bc_ele->n_nodes());
599  for (unsigned n=0; n<bc_ele->n_nodes(); n++) side_nodes[n] = bc_ele->node_idx(n);
600  intersect_element_lists(side_nodes, intersection_list);
601  bool is_neighbour = find_lower_dim_element(intersection_list, bc_ele->dim() +1, ngh_element_idx);
602  if (is_neighbour) {
603  THROW( ExcBdrElemMatchRegular() << EI_ElemId(bc_ele.idx()) << EI_ElemIdOther(this->elem_index(ngh_element_idx)) );
604  } else {
605  if (intersection_list.size() == 0) {
606  // no matching dim+1 element found
607  WarningOut().fmt("Lonely boundary element, id: {}, region: {}, dimension {}.\n",
608  bc_ele.idx(), bc_ele.region().id(), bc_ele->dim());
609  continue; // skip the boundary element
610  }
611  last_edge_idx=edges.size();
612  edges.resize(last_edge_idx+1);
613  edg = &( edges.back() );
614  edg->n_sides = 0;
615  edg->side_ = new struct SideIter[ intersection_list.size() ];
616 
617  // common boundary object
618  unsigned int bdr_idx=boundary_.size();
619  boundary_.resize(bdr_idx+1);
620  BoundaryData &bdr=boundary_.back();
621  bdr.bc_ele_idx_ = i;
622  bdr.edge_idx_ = last_edge_idx;
623  bdr.mesh_=this;
624 
625  // for 1d boundaries there can be more then one 1d elements connected to the boundary element
626  // we do not detect this case later in the main search over bulk elements
627  for( vector<unsigned int>::iterator isect = intersection_list.begin(); isect!=intersection_list.end(); ++isect) {
628  ElementAccessor<3> elem = this->element_accessor(*isect);
629  for (unsigned int ecs=0; ecs<elem->n_sides(); ecs++) {
630  SideIter si = elem.side(ecs);
631  if ( same_sides( si, side_nodes) ) {
632  if (elem->edge_idx(ecs) != undef_idx) {
633  OLD_ASSERT(elem->boundary_idx_!=nullptr, "Null boundary idx array.\n");
634  int last_bc_ele_idx=this->boundary_[elem->boundary_idx_[ecs]].bc_ele_idx_;
635  int new_bc_ele_idx=i;
636  THROW( ExcDuplicateBoundary()
637  << EI_ElemLast(this->find_elem_id(last_bc_ele_idx))
638  << EI_RegLast(this->element_accessor(last_bc_ele_idx).region().label())
639  << EI_ElemNew(this->find_elem_id(new_bc_ele_idx))
640  << EI_RegNew(this->element_accessor(new_bc_ele_idx).region().label())
641  );
642  }
643  element_vec_[*isect].edge_idx_[ecs] = last_edge_idx;
644  edg->side_[ edg->n_sides++ ] = si;
645 
646  if (elem->boundary_idx_ == NULL) {
647  Element *el = &(element_vec_[*isect]);
648  el->boundary_idx_ = new unsigned int [ el->n_sides() ];
649  std::fill( el->boundary_idx_, el->boundary_idx_ + el->n_sides(), undef_idx);
650  }
651  elem->boundary_idx_[ecs] = bdr_idx;
652  break; // next element in intersection list
653  }
654  }
655  }
656 
657  }
658 
659  }
660  // Now we go through all element sides and create edges and neighbours
661  unsigned int new_bc_elem_idx = element_vec_.size(); //Mesh_idx of new boundary element generated in following block
662  for (auto e : this->elements_range()) {
663  for (unsigned int s=0; s<e->n_sides(); s++)
664  {
665  // skip sides that were already found
666  if (e->edge_idx(s) != undef_idx) continue;
667 
668 
669  // Find all elements that share this side.
670  side_nodes.resize(e.side(s)->n_nodes());
671  for (unsigned n=0; n<e.side(s)->n_nodes(); n++) side_nodes[n] = e.side(s)->node(n).idx();
672  intersect_element_lists(side_nodes, intersection_list);
673 
674  bool is_neighbour = find_lower_dim_element(intersection_list, e->dim(), ngh_element_idx);
675 
676  if (is_neighbour) { // edge connects elements of different dimensions
677  // Initialize for the neighbour case.
678  neighbour.elem_idx_ = ngh_element_idx;
679  } else { // edge connects only elements of the same dimension
680  // Initialize for the edge case.
681  last_edge_idx=edges.size();
682  edges.resize(last_edge_idx+1);
683  edg = &( edges.back() );
684  edg->n_sides = 0;
685  edg->side_ = new struct SideIter[ intersection_list.size() ];
686  if (intersection_list.size() > max_edge_sides_[e->dim()-1])
687  max_edge_sides_[e->dim()-1] = intersection_list.size();
688 
689  if (intersection_list.size() == 1) {
690  // outer edge, create boundary object as well
691  Element &elm = element_vec_[e.idx()];
692  edg->n_sides=1;
693  edg->side_[0] = e.side(s);
694  element_vec_[e.idx()].edge_idx_[s] = last_edge_idx;
695 
696  if (e->boundary_idx_ == NULL) {
697  elm.boundary_idx_ = new unsigned int [ e->n_sides() ];
698  std::fill( elm.boundary_idx_, elm.boundary_idx_ + e->n_sides(), undef_idx);
699  }
700 
701  unsigned int bdr_idx=boundary_.size()+1; // need for VTK mesh that has no boundary elements
702  // and bulk elements are indexed from 0
703  boundary_.resize(bdr_idx+1);
704  BoundaryData &bdr=boundary_.back();
705  elm.boundary_idx_[s] = bdr_idx;
706 
707  // fill boundary element
708  Element * bc_ele = add_element_to_vector(-bdr_idx);
709  bc_ele->init(e->dim()-1, region_db_.implicit_boundary_region() );
711  for(unsigned int ni = 0; ni< side_nodes.size(); ni++) bc_ele->nodes_[ni] = side_nodes[ni];
712 
713  // fill Boundary object
714  bdr.edge_idx_ = last_edge_idx;
715  bdr.bc_ele_idx_ = new_bc_elem_idx; //elem_index(-bdr_idx);
716  bdr.mesh_=this;
717  new_bc_elem_idx++;
718 
719  continue; // next side of element e
720  }
721  }
722 
723  // go through the elements connected to the edge or neighbour
724  // setup neigbour or edge
725  for( vector<unsigned int>::iterator isect = intersection_list.begin(); isect!=intersection_list.end(); ++isect) {
726  ElementAccessor<3> elem = this->element_accessor(*isect);
727  for (unsigned int ecs=0; ecs<elem->n_sides(); ecs++) {
728  if (elem->edge_idx(ecs) != undef_idx) continue; // ??? This should not happen.
729  SideIter si = elem.side(ecs);
730  if ( same_sides( si, side_nodes) ) {
731  if (is_neighbour) {
732  // create a new edge and neighbour for this side, and element to the edge
733  last_edge_idx=edges.size();
734  edges.resize(last_edge_idx+1);
735  edg = &( edges.back() );
736  edg->n_sides = 1;
737  edg->side_ = new struct SideIter[1];
738  edg->side_[0] = si;
739  element_vec_[elem.idx()].edge_idx_[ecs] = last_edge_idx;
740 
741  neighbour.edge_idx_ = last_edge_idx;
742 
743  vb_neighbours_.push_back(neighbour); // copy neighbour with this edge setting
744  } else {
745  // connect the side to the edge, and side to the edge
746  ASSERT_PTR_DBG(edg);
747  edg->side_[ edg->n_sides++ ] = si;
748  ASSERT_DBG(last_edge_idx != undef_idx);
749  element_vec_[elem.idx()].edge_idx_[ecs] = last_edge_idx;
750  }
751  break; // next element from intersection list
752  }
753  } // search for side of other connected element
754  } // connected elements
755 
756  if (! is_neighbour)
757  ASSERT_EQ( (unsigned int) edg->n_sides, intersection_list.size())(e.index())(s).error("Missing edge sides.");
758  } // for element sides
759  } // for elements
760 
761  MessageOut().fmt( "Created {} edges and {} neighbours.\n", edges.size(), vb_neighbours_.size() );
762 }
763 
764 
765 
766 //=============================================================================
767 //
768 //=============================================================================
770 {
771 
772  //MessageOut() << "Element to neighbours of vb2 type... "/*orig verb 5*/;
773 
774  for (vector<Element>::iterator ele = element_vec_.begin(); ele!= element_vec_.begin()+bulk_size_; ++ele)
775  ele->n_neighs_vb_ =0;
776 
777  // count vb neighs per element
778  for (auto & ngh : this->vb_neighbours_) ngh.element()->n_neighs_vb_++;
779 
780  // Allocation of the array per element
781  for (vector<Element>::iterator ele = element_vec_.begin(); ele!= element_vec_.begin()+bulk_size_; ++ele)
782  if( ele->n_neighs_vb() > 0 ) {
783  ele->neigh_vb = new struct Neighbour* [ele->n_neighs_vb()];
784  ele->n_neighs_vb_=0;
785  }
786 
787  // fill
788  ElementAccessor<3> ele;
789  for (auto & ngh : this->vb_neighbours_) {
790  ele = ngh.element();
791  ele->neigh_vb[ ele->n_neighs_vb_++ ] = &ngh;
792  }
793 
794  //MessageOut() << "... O.K.\n"/*orig verb 6*/;
795 }
796 
797 
798 
799 
800 
801 
803  /* Algorithm:
804  *
805  * 1) create BIH tree
806  * 2) for every 1D, find list of candidates
807  * 3) compute intersections for 1d, store it to master_elements
808  *
809  */
810  if (! intersections) {
811  intersections = std::make_shared<MixedMeshIntersections>(this);
812  intersections->compute_intersections();
813  }
814  return *intersections;
815 }
816 
817 
818 
820  return ElementAccessor<3>(this, idx);
821 }
822 
823 
824 
825 NodeAccessor<3> Mesh::node(unsigned int idx) const {
826  return NodeAccessor<3>(this, idx);
827 }
828 
829 
830 
831 void Mesh::elements_id_maps( vector<LongIdx> & bulk_elements_id, vector<LongIdx> & boundary_elements_id) const
832 {
833  if (bulk_elements_id.size() ==0) {
835  LongIdx last_id;
836 
837  bulk_elements_id.resize(n_elements());
838  map_it = bulk_elements_id.begin();
839  last_id = -1;
840  for(unsigned int idx=0; idx < n_elements(); idx++, ++map_it) {
841  LongIdx id = this->find_elem_id(idx);
842  last_id=*map_it = id;
843  }
844  std::sort(bulk_elements_id.begin(), bulk_elements_id.end());
845 
846  boundary_elements_id.resize(element_ids_.size()-bulk_size_);
847  map_it = boundary_elements_id.begin();
848  last_id = -1;
849  for(unsigned int idx=bulk_size_; idx<element_ids_.size(); idx++, ++map_it) {
850  LongIdx id = this->find_elem_id(idx);
851  // We set ID for boundary elements created by the mesh itself to "-1"
852  // this force gmsh reader to skip all remaining entries in boundary_elements_id
853  // and thus report error for any remaining data lines
854  if (id < 0) last_id=*map_it=-1;
855  else {
856  if (last_id >= id) THROW( ExcElmWrongOrder() << EI_ElemId(id) );
857  last_id=*map_it = id;
858  }
859  }
860  }
861 }
862 
863 
864 bool compare_points(const arma::vec3 &p1, const arma::vec3 &p2) {
865  static const double point_tolerance = 1E-10;
866  return fabs(p1[0]-p2[0]) < point_tolerance
867  && fabs(p1[1]-p2[1]) < point_tolerance
868  && fabs(p1[2]-p2[2]) < point_tolerance;
869 }
870 
871 
872 std::shared_ptr<std::vector<LongIdx>> Mesh::check_compatible_mesh( Mesh & input_mesh)
873 {
874  std::vector<unsigned int> node_ids; // allow mapping ids of nodes from source mesh to target mesh
875  std::vector<unsigned int> node_list;
876  std::vector<unsigned int> candidate_list; // returned by intersect_element_lists
877  std::vector<unsigned int> result_list; // list of elements with same dimension as vtk element
878  unsigned int i; // counter over vectors
879  std::shared_ptr<std::vector<LongIdx>> map_ptr = std::make_shared<std::vector<LongIdx>>(element_vec_.size());
880  std::vector<LongIdx> &element_ids_map = *(map_ptr.get());
881 
882  {
883  // iterates over node vector of \p this object
884  // to each node must be found just only one node in target \p mesh
885  // store orders (mapping between source and target meshes) into node_ids vector
886  std::vector<unsigned int> searched_elements; // for BIH tree
887  unsigned int i_node, i_elm_node;
888  const BIHTree &bih_tree=this->get_bih_tree();
889 
890  // create nodes of mesh
891  node_ids.resize( this->n_nodes(), undef_idx );
892  i=0;
893  for (auto nod : input_mesh.node_range()) {
894  uint found_i_node = undef_idx;
895  bih_tree.find_point(*nod, searched_elements);
896 
897  for (std::vector<unsigned int>::iterator it = searched_elements.begin(); it!=searched_elements.end(); it++) {
898  ElementAccessor<3> ele = this->element_accessor( *it );
899  for (i_node=0; i_node<ele->n_nodes(); i_node++)
900  {
901  static const double point_tolerance = 1E-10;
902  if ( arma::norm(*ele.node(i_node) - *nod, 1) < point_tolerance) {
903  i_elm_node = ele.node(i_node).idx();
904  if (found_i_node == undef_idx) found_i_node = i_elm_node;
905  else if (found_i_node != i_elm_node) {
906  // duplicate nodes in target mesh - not compatible
907  return std::make_shared<std::vector<LongIdx>>(0);
908  }
909  }
910  }
911  }
912  if (found_i_node!=undef_idx) node_ids[found_i_node] = i;
913  searched_elements.clear();
914  i++;
915  }
916  }
917  {
918  // iterates over bulk elements of \p this object
919  // elements in both meshes must be in ratio 1:1
920  // store orders (mapping between both mesh files) into bulk_elements_id vector
921  // iterate trough bulk part of element vector, to each element in source mesh must exist only one element in target mesh
922  i=0;
923  unsigned int n_found=0; // number of found equivalent elements
924  bool valid_nodes;
925  for (auto elm : this->elements_range()) {
926  valid_nodes = true;
927  for (unsigned int j=0; j<elm->n_nodes(); j++) { // iterate trough all nodes of any element
928  if (node_ids[ elm->node_idx(j) ] == undef_idx) valid_nodes = false;
929  node_list.push_back( node_ids[ elm->node_idx(j) ] );
930  }
931  if (valid_nodes) {
932  input_mesh.intersect_element_lists(node_list, candidate_list);
933  for (auto i_elm : candidate_list) {
934  if ( input_mesh.element_accessor(i_elm)->dim() == elm.dim() ) result_list.push_back(i_elm);
935  }
936  }
937  if (result_list.size() == 1) {
938  element_ids_map[i] = (LongIdx)result_list[0];
939  n_found++;
940  } else {
941  element_ids_map[i] = (LongIdx)undef_idx;
942  }
943  node_list.clear();
944  result_list.clear();
945  i++;
946  }
947 
948  if (n_found==0) {
949  // no equivalent bulk element found - mesh is not compatible
950  return std::make_shared<std::vector<LongIdx>>(0);
951  }
952  }
953 
954  {
955  // iterates over boundary elements of \p this object
956  // elements in both meshes must be in ratio 1:1
957  // store orders (mapping between both mesh files) into boundary_elements_id vector
958  auto bc_mesh = this->get_bc_mesh();
959  auto input_bc_mesh = input_mesh.get_bc_mesh();
960  // iterate trough boundary part of element vector, to each element in source mesh must exist only one element in target mesh
961  // fill boundary_elements_id vector
962  bool valid_nodes;
963  i=this->n_elements();
964  for (auto elm : bc_mesh->elements_range()) {
965  valid_nodes = true;
966  for (unsigned int j=0; j<elm->n_nodes(); j++) { // iterate trough all nodes of any element
967  if (node_ids[ elm->node_idx(j) ] == undef_idx) valid_nodes = false;
968  node_list.push_back( node_ids[ elm->node_idx(j) ] );
969  }
970  if (valid_nodes) {
971  input_bc_mesh->intersect_element_lists(node_list, candidate_list);
972  for (auto i_elm : candidate_list) {
973  if ( input_bc_mesh->element_accessor(i_elm)->dim() == elm.dim() ) result_list.push_back(i_elm);
974  }
975  }
976  if (result_list.size() == 1) {
977  element_ids_map[i] = (LongIdx)result_list[0];
978  } else {
979  element_ids_map[i] = (LongIdx)undef_idx;
980  }
981  node_list.clear();
982  result_list.clear();
983  i++;
984  }
985  }
986 
987  return map_ptr;
988 }
989 
990 
992  static const double point_tolerance = 1E-10;
993  if (elm1.dim() != elm2.dim()) return false;
994  bool equal_node;
995  for (unsigned int i=0; i<elm1->n_nodes(); i++) { // iterate trough all nodes of elm1
996  equal_node = false;
997  for (unsigned int j=0; j<elm2->n_nodes(); j++) { // iterate trough all nodes of elm2
998  if ( arma::norm(*elm1.node(i) - *elm2.node(j), 1) < point_tolerance)
999  equal_node = true; // equal node exists
1000  }
1001  if (!equal_node) return false;
1002  }
1003  return true;
1004 }
1005 
1006 
1007 std::shared_ptr<std::vector<LongIdx>> Mesh::check_compatible_discont_mesh( Mesh & input_mesh)
1008 {
1009  std::vector<unsigned int> result_list; // list of elements with same dimension as vtk element
1010  unsigned int i; // counter over vectors
1011  std::shared_ptr<std::vector<LongIdx>> map_ptr = std::make_shared<std::vector<LongIdx>>(element_vec_.size());
1012  std::vector<LongIdx> &element_ids_map = *(map_ptr.get());
1013  std::vector<unsigned int> searched_elements; // for BIH tree
1014  const BIHTree &bih_tree=input_mesh.get_bih_tree();
1015 
1016  {
1017  // iterates over bulk elements of \p this object
1018  // elements in both meshes must be in ratio 1:1
1019  // store orders (mapping between both mesh files) into bulk_elements_id vector
1020  // iterate trough bulk part of element vector, to each element in source mesh must exist only one element in target mesh
1021  i=0;
1022  unsigned int n_found=0; // number of found equivalent elements
1023  for (auto elm : this->elements_range()) {
1024  bih_tree.find_bounding_box(elm.bounding_box(), searched_elements);
1025  for (auto s : searched_elements) {
1026  auto acc = input_mesh.element_accessor(s);
1027  if ( equal_elm(elm, acc) ) result_list.push_back(s);
1028  }
1029 
1030  if (result_list.size() == 1) {
1031  element_ids_map[i] = (LongIdx)result_list[0];
1032  n_found++;
1033  } else {
1034  element_ids_map[i] = (LongIdx)undef_idx;
1035  }
1036  result_list.clear();
1037  searched_elements.clear();
1038  i++;
1039  }
1040 
1041  if (n_found==0) {
1042  // no equivalent bulk element found - mesh is not compatible
1043  return std::make_shared<std::vector<LongIdx>>(0);
1044  }
1045  }
1046 
1047  {
1048  // iterates over boundary elements of \p this object
1049  // elements in both meshes must be in ratio 1:1
1050  // store orders (mapping between both mesh files) into boundary_elements_id vector
1051  auto bc_mesh = this->get_bc_mesh();
1052 // auto input_bc_mesh = input_mesh.get_bc_mesh();
1053  // iterate trough boundary part of element vector, to each element in source mesh must exist only one element in target mesh
1054  // fill boundary_elements_id vector
1055  i=this->n_elements();
1056  for (auto elm : bc_mesh->elements_range()) {
1057  bih_tree.find_bounding_box(elm.bounding_box(), searched_elements);
1058  for (auto s : searched_elements) {
1059  auto acc = input_mesh.element_accessor(s);
1060  if ( equal_elm(elm, acc) ) result_list.push_back(s);
1061  }
1062  if (result_list.size() == 1) {
1063  element_ids_map[i] = (LongIdx)result_list[0];
1064  } else {
1065  element_ids_map[i] = (LongIdx)undef_idx;
1066  }
1067  result_list.clear();
1068  searched_elements.clear();
1069  i++;
1070  }
1071  }
1072 
1073  return map_ptr;
1074 }
1075 
1076 
1078 {
1080  it != region_list.end();
1081  ++it) {
1082  // constructor has side effect in the mesh - create new region or set and store them to Mesh::region_db_
1083  (*it).factory< RegionSetBase, const Input::Record &, Mesh * >(*it, this);
1084  }
1085 }
1086 
1088 {
1090  region_db_.el_to_reg_map_.clear();
1091  region_db_.close();
1093 
1094  if ( in_record_.val<bool>("print_regions") ) {
1095  stringstream ss;
1097  MessageOut() << ss.str();
1098  }
1099 }
1100 
1101 
1103  START_TIMER("Mesh::compute_element_boxes");
1105 
1106  // make element boxes
1107  unsigned int i=0;
1108  boxes.resize(this->n_elements());
1109  for (auto element : this->elements_range()) {
1110  boxes[i] = element.bounding_box();
1111  i++;
1112  }
1113 
1114  return boxes;
1115 }
1116 
1118  if (! this->bih_tree_) {
1119  bih_tree_ = std::make_shared<BIHTree>();
1120  bih_tree_->add_boxes( this->get_element_boxes() );
1121  bih_tree_->construct();
1122  }
1123  return *bih_tree_;
1124 }
1125 
1127  return in_record_.val<double>("global_snap_radius");
1128 }
1129 
1130 void Mesh::add_physical_name(unsigned int dim, unsigned int id, std::string name) {
1131  region_db_.add_region(id, name, dim, "$PhysicalNames");
1132 }
1133 
1134 
1135 void Mesh::add_node(unsigned int node_id, arma::vec3 coords) {
1136 
1137  nodes_.append(coords);
1138  node_ids_.add_item(node_id);
1139  node_permutation_.push_back(node_permutation_.size());
1140 }
1141 
1142 
1143 void Mesh::add_element(unsigned int elm_id, unsigned int dim, unsigned int region_id, unsigned int partition_id,
1144  std::vector<unsigned int> node_ids) {
1145  RegionIdx region_idx = region_db_.get_region( region_id, dim );
1146  if ( !region_idx.is_valid() ) {
1147  region_idx = region_db_.add_region( region_id, region_db_.create_label_from_id(region_id), dim, "$Element" );
1148  }
1149  region_db_.mark_used_region(region_idx.idx());
1150 
1151  if (region_idx.is_boundary()) {
1152  bc_element_tmp_.push_back( ElementTmpData(elm_id, dim, region_idx, partition_id, node_ids) );
1153  } else {
1154  if(dim == 0 ) {
1155  WarningOut().fmt("Bulk elements of zero size(dim=0) are not supported. Element ID: {}.\n", elm_id);
1156  }
1157  else {
1158  Element *ele = add_element_to_vector(elm_id);
1159  bulk_size_++;
1160  this->init_element(ele, elm_id, dim, region_idx, partition_id, node_ids);
1161  }
1162  }
1163 }
1164 
1165 
1166 void Mesh::init_element(Element *ele, unsigned int elm_id, unsigned int dim, RegionIdx region_idx, unsigned int partition_id,
1167  std::vector<unsigned int> node_ids) {
1168  ele->init(dim, region_idx);
1169  ele->pid_ = partition_id;
1170 
1171  unsigned int ni=0;
1172  for (; ni<ele->n_nodes(); ni++) {
1173  ele->nodes_[ni] = this->node_index(node_ids[ni]);
1174  }
1175  for( ;ni < 4; ni++) ele->nodes_[ni] = undef_idx;
1176 
1177  // check that tetrahedron element is numbered correctly and is not degenerated
1178  if(ele->dim() == 3)
1179  {
1180  ElementAccessor<3> ea = this->element_accessor( this->elem_index(elm_id) );
1181  double jac = ea.jacobian_S3();
1182  if( ! (jac > 0) ) {
1183  WarningOut().fmt("Tetrahedron element with id {} has wrong numbering or is degenerated (Jacobian = {}).",elm_id, jac);
1184  }
1185  }
1186 }
1187 
1188 
1190  if (node_elements_.size() == 0) {
1191  this->create_node_element_lists();
1192  }
1193  return node_elements_;
1194 }
1195 
1196 
1197 void Mesh::init_element_vector(unsigned int size) {
1198  element_vec_.clear();
1199  element_ids_.clear();
1200  elem_permutation_.clear();
1201  element_vec_.reserve(size);
1202  element_ids_.reserve(size);
1203  elem_permutation_.reserve(size);
1204  bc_element_tmp_.clear();
1205  bc_element_tmp_.reserve(size);
1206  bulk_size_ = 0;
1208 }
1209 
1210 
1211 void Mesh::init_node_vector(unsigned int size) {
1212  nodes_.reinit(size);
1213  node_ids_.clear();
1214  node_ids_.reserve(size);
1215  node_permutation_.clear();
1216  node_permutation_.reserve(size);
1217 }
1218 
1219 
1221  element_vec_.push_back( Element() );
1222  Element * elem = &element_vec_.back(); //[element_vec_.size()-1];
1223  element_ids_.add_item((unsigned int)(id));
1224  elem_permutation_.push_back(elem_permutation_.size());
1225  return elem;
1226 }
1227 
1229  auto bgn_it = make_iter<ElementAccessor<3>>( ElementAccessor<3>(this, 0) );
1230  auto end_it = make_iter<ElementAccessor<3>>( ElementAccessor<3>(this, bulk_size_) );
1231  return Range<ElementAccessor<3>>(bgn_it, end_it);
1232 }
1233 
1235  auto bgn_it = make_iter<NodeAccessor<3>>( NodeAccessor<3>(this, 0) );
1236  auto end_it = make_iter<NodeAccessor<3>>( NodeAccessor<3>(this, n_nodes()) );
1237  return Range<NodeAccessor<3>>(bgn_it, end_it);
1238 }
1239 
1241  auto bgn_it = make_iter<Edge>( Edge(this, 0) );
1242  auto end_it = make_iter<Edge>( Edge(this, edges.size()) );
1243  return Range<Edge>(bgn_it, end_it);
1244 }
1245 
1246 inline void Mesh::check_element_size(unsigned int elem_idx) const
1247 {
1248  ASSERT(elem_idx < element_vec_.size())(elem_idx)(element_vec_.size()).error("Index of element is out of bound of element vector!");
1249 }
1250 
1251 /*
1252  * Output of internal flow data.
1253  */
1255 {
1256  START_TIMER("Mesh::output_internal_ngh_data");
1257 
1258  FilePath raw_output_file_path;
1259  if (! in_record_.opt_val("raw_ngh_output", raw_output_file_path)) return;
1260 
1261  ofstream raw_ngh_output_file;
1262  int rank;
1263  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
1264  if (rank == 0) {
1265  MessageOut() << "Opening raw ngh output: " << raw_output_file_path << "\n";
1266  try {
1267  raw_output_file_path.open_stream(raw_ngh_output_file);
1268  } INPUT_CATCH(FilePath::ExcFileOpen, FilePath::EI_Address_String, (in_record_))
1269  }
1270 
1271  if (! raw_ngh_output_file.is_open()) return;
1272 
1273  // header
1274  raw_ngh_output_file << "// fields:\n//ele_id n_sides ns_side_neighbors[n] neighbors[n*ns] n_vb_neighbors vb_neighbors[n_vb]\n";
1275  raw_ngh_output_file << fmt::format("{}\n" , n_elements());
1276 
1277  int cit = 0;
1278 
1279  // map from higher dim elements to its lower dim neighbors, using gmsh IDs: ele->id()
1280  unsigned int undefined_ele_id = -1;
1282  for (auto ele : this->elements_range()) {
1283  if(ele->n_neighs_vb() > 0){
1284  for (unsigned int i = 0; i < ele->n_neighs_vb(); i++){
1285  ElementAccessor<3> higher_ele = ele->neigh_vb[i]->side()->element();
1286 
1287  auto search = neigh_vb_map.find(higher_ele.idx());
1288  if(search != neigh_vb_map.end()){
1289  // if found, add id to correct local side idx
1290  search->second[ele->neigh_vb[i]->side()->side_idx()] = ele.idx();
1291  }
1292  else{
1293  // if not found, create new vector, each side can have one vb neighbour
1294  std::vector<unsigned int> higher_ele_side_ngh(higher_ele->n_sides(), undefined_ele_id);
1295  higher_ele_side_ngh[ele->neigh_vb[i]->side()->side_idx()] = ele.idx();
1296  neigh_vb_map[higher_ele.idx()] = higher_ele_side_ngh;
1297  }
1298  }
1299  }
1300  }
1301 
1302  for (auto ele : this->elements_range()) {
1303  raw_ngh_output_file << ele.idx() << " ";
1304  raw_ngh_output_file << ele->n_sides() << " ";
1305 
1306  auto search_neigh = neigh_vb_map.end();
1307  for (unsigned int i = 0; i < ele->n_sides(); i++) {
1308  unsigned int n_side_neighs = ele.side(i)->edge().n_sides()-1; //n_sides - the current one
1309  // check vb neighbors (lower dimension)
1310  if(n_side_neighs == 0){
1311  //update search
1312  if(search_neigh == neigh_vb_map.end())
1313  search_neigh = neigh_vb_map.find(ele.idx());
1314 
1315  if(search_neigh != neigh_vb_map.end())
1316  if(search_neigh->second[i] != undefined_ele_id)
1317  n_side_neighs = 1;
1318  }
1319  raw_ngh_output_file << n_side_neighs << " ";
1320  }
1321 
1322  for (unsigned int i = 0; i < ele->n_sides(); i++) {
1323  Edge edge = ele.side(i)->edge();
1324  if(edge.n_sides() > 1){
1325  for (uint j = 0; j < edge.n_sides(); j++) {
1326  if(edge.side(j) != ele.side(i))
1327  raw_ngh_output_file << edge.side(j)->element().idx() << " ";
1328  }
1329  }
1330  //check vb neighbour
1331  else if(search_neigh != neigh_vb_map.end()
1332  && search_neigh->second[i] != undefined_ele_id){
1333  raw_ngh_output_file << search_neigh->second[i] << " ";
1334  }
1335  }
1336 
1337  // list higher dim neighbours
1338  raw_ngh_output_file << ele->n_neighs_vb() << " ";
1339  for (unsigned int i = 0; i < ele->n_neighs_vb(); i++)
1340  raw_ngh_output_file << ele->neigh_vb[i]->side()->element().idx() << " ";
1341 
1342  raw_ngh_output_file << endl;
1343  cit ++;
1344  }
1345  raw_ngh_output_file << "$EndFlowField\n" << endl;
1346 }
1347 
1348 
1350  // Copy boundary elements in temporary storage to the second part of the element vector
1351  for(ElementTmpData &e_data : bc_element_tmp_) {
1352  Element *ele = add_element_to_vector(e_data.elm_id);
1353  this->init_element(ele, e_data.elm_id, e_data.dim, e_data.region_idx,
1354  e_data.partition_id, e_data.node_ids);
1355  }
1356  // release memory
1357  unsigned int bdr_size = bc_element_tmp_.size();
1359  return bdr_size;
1360 }
1361 
1362 
1364  if (bc_mesh_ == nullptr) bc_mesh_ = new BCMesh(this);
1365  return bc_mesh_;
1366 }
1367 
1368 
1370  ASSERT_PTR(el_4_loc).error("Array 'el_4_loc' is not initialized. Did you call Partitioning::id_maps?\n");
1371 
1372  unsigned int i_proc, i_node, i_ghost_node, elm_node;
1373  unsigned int my_proc = el_ds->myp();
1374  unsigned int n_proc = el_ds->np();
1375 
1376  // distribute nodes between processes, every node is assigned to minimal process of elements that own node
1377  // fill node_proc vector with same values on all processes
1378  std::vector<unsigned int> node_proc( this->n_nodes(), n_proc );
1379  std::vector<bool> local_node_flag( this->n_nodes(), false );
1380 
1381  for ( auto elm : this->elements_range() ) {
1382  i_proc = elm.proc();
1383  for (elm_node=0; elm_node<elm->n_nodes(); elm_node++) {
1384  i_node = elm->node_idx(elm_node);
1385  if (i_proc == my_proc) local_node_flag[i_node] = true;
1386  if (i_proc < node_proc[i_node]) node_proc[i_node] = i_proc;
1387  }
1388  }
1389 
1390  unsigned int n_own_nodes=0, n_local_nodes=0; // number of own and ghost nodes
1391  for(uint loc_flag : local_node_flag) if (loc_flag) n_local_nodes++;
1392  for(uint i_proc : node_proc) {
1393  if (i_proc == my_proc)
1394  n_own_nodes++;
1395  else if (i_proc == n_proc)
1396  ASSERT(0)(find_node_id(n_own_nodes)).error("A node does not belong to any element!");
1397  }
1398 
1399  //DebugOut() << print_var(n_own_nodes) << print_var(n_local_nodes) << this->n_nodes();
1400  // create and fill node_4_loc_ (mapping local to global indexes)
1401  node_4_loc_ = new LongIdx [ n_local_nodes ];
1402  i_node=0;
1403  i_ghost_node = n_own_nodes;
1404  for (unsigned int i=0; i<this->n_nodes(); ++i) {
1405  if (local_node_flag[i]) {
1406  if (node_proc[i]==my_proc)
1407  node_4_loc_[i_node++] = i;
1408  else
1409  node_4_loc_[i_ghost_node++] = i;
1410  }
1411  }
1412 
1413  // Construct node distribution object, set number of local nodes (own+ghost)
1414  node_ds_ = new Distribution(n_own_nodes, PETSC_COMM_WORLD);
1415  node_ds_->get_lsizes_array(); // need to initialize lsizes data member
1417 
1418 }
1419 
1420 //-----------------------------------------------------------------------------
1421 // vim: set cindent:
ElementAccessor::dim
unsigned int dim() const
Definition: accessors.hh:190
Side::edge
Edge edge() const
Returns pointer to the edge connected to the side.
Definition: accessors_impl.hh:221
MeshOptimizer::calculate_node_curve_values_as_hilbert
void calculate_node_curve_values_as_hilbert()
Definition: mesh_optimizer.hh:59
Mesh::create_boundary_elements
unsigned int create_boundary_elements()
Create boundary elements from data of temporary structure, this method MUST be call after read mesh f...
Definition: mesh.cc:1349
Input::Type::Bool
Class for declaration of the input of type Bool.
Definition: type_base.hh:452
Distribution::np
unsigned int np() const
get num of processors
Definition: distribution.hh:105
reader_to_storage.hh
Boundary
Definition: accessors.hh:363
BidirectionalMap< int >
Mesh::BCMesh
friend class BCMesh
Definition: mesh.h:616
ref_element.hh
Class RefElement defines numbering of vertices, sides, calculation of normal vectors etc.
Mesh::nodes_
Armor::Array< double > nodes_
Definition: mesh.h:595
Mesh::check_compatible_discont_mesh
virtual std::shared_ptr< std::vector< LongIdx > > check_compatible_discont_mesh(Mesh &input_mesh)
Definition: mesh.cc:1007
Neighbour::mesh_
Mesh * mesh_
Pointer to Mesh to which belonged.
Definition: neighbours.h:136
MeshOptimizer::sort_elements
std::vector< int > sort_elements(std::vector< unsigned int > &elem_permutation)
Definition: mesh_optimizer.hh:108
Region::label
std::string label() const
Returns label of the region (using RegionDB)
Definition: region.cc:32
Mesh::get_input_intersection_variant
static const Input::Type::Selection & get_input_intersection_variant()
The definition of input record for selection of variant of file format.
Definition: mesh.cc:65
Mesh::get_element_boxes
std::vector< BoundingBox > get_element_boxes()
Compute bounding boxes of elements contained in mesh.
Definition: mesh.cc:1102
Neighbour::edge_idx_
unsigned int edge_idx_
Index of Edge in Mesh.
Definition: neighbours.h:138
Input::ReaderToStorage
Reader for (slightly) modified input files.
Definition: reader_to_storage.hh:96
Mesh::node_4_loc_
LongIdx * node_4_loc_
Index set assigning to local node index its global index.
Definition: mesh.h:634
bih_tree.hh
Input::ReaderToStorage::read_stream
void read_stream(istream &in, const Type::TypeBase &root_type, FileFormat format)
This method actually reads the given stream in.
Definition: reader_to_storage.cc:110
mesh_optimizer.hh
Mesh::in_record_
Input::Record in_record_
Definition: mesh.h:566
RefElement
Definition: ref_element.hh:339
Mesh::init_element_vector
void init_element_vector(unsigned int size)
Initialize element_vec_, set size and reset counters of boundary and bulk elements.
Definition: mesh.cc:1197
neighbours.h
Neighbour::elem_idx_
unsigned int elem_idx_
Index of element in Mesh::element_vec_.
Definition: neighbours.h:137
Mesh::n_exsides
int n_exsides
Definition: mesh.h:316
Mesh::init_element
void init_element(Element *ele, unsigned int elm_id, unsigned int dim, RegionIdx region_idx, unsigned int partition_id, std::vector< unsigned int > node_ids)
Initialize element.
Definition: mesh.cc:1166
Distribution::myp
unsigned int myp() const
get my processor
Definition: distribution.hh:107
RegionSetBase::get_input_type
static Input::Type::Abstract & get_input_type()
Definition: region_set.cc:25
MeshOptimizer::calculate_element_curve_values_as_hilbert_of_centers
void calculate_element_curve_values_as_hilbert_of_centers()
Definition: mesh_optimizer.hh:86
ASSERT
#define ASSERT(expr)
Allow use shorter versions of macro names if these names is not used with external library.
Definition: asserts.hh:347
RegionDB::check_regions
void check_regions()
Definition: region.cc:461
Element::dim
unsigned int dim() const
Definition: elements.h:127
Mesh::elements_range
virtual Range< ElementAccessor< 3 > > elements_range() const
Returns range of bulk elements.
Definition: mesh.cc:1228
Mesh::n_sides
unsigned int n_sides() const
Definition: mesh.cc:240
distribution.hh
Support classes for parallel programing.
bc_mesh.hh
Edge::n_sides
unsigned int n_sides() const
Returns number of sides aligned with the edge.
Definition: accessors.hh:343
BoundaryData::edge_idx_
unsigned int edge_idx_
Definition: mesh_data.hh:49
MixedMeshIntersections
Main class for computation of intersection of meshes of combined dimensions.
Definition: mixed_mesh_intersections.hh:64
compare_points
bool compare_points(const arma::vec3 &p1, const arma::vec3 &p2)
Definition: mesh.cc:864
Input::Record::val
const Ret val(const string &key) const
Definition: accessors_impl.hh:31
Mesh::boundary_loaded_size_
unsigned int boundary_loaded_size_
Count of boundary elements loaded from mesh file.
Definition: mesh.h:587
Armor::Array::vec
ArmaVec< Type, nr > vec(uint mat_index) const
Definition: armor.hh:821
Input::Type::Selection::close
const Selection & close() const
Close the Selection, no more values can be added.
Definition: type_selection.cc:65
Mesh::tree
DuplicateNodes * tree
Definition: mesh.h:308
Mesh::element_vec_
vector< Element > element_vec_
Definition: mesh.h:578
Neighbour::side
SideIter side()
Definition: neighbours.h:145
Element::pid_
int pid_
Id # of mesh partition.
Definition: elements.h:104
FilePath
Dedicated class for storing path to input and output files.
Definition: file_path.hh:54
ASSERT_DBG
#define ASSERT_DBG(expr)
Definition: include_fadbad.hh:28
MeshOptimizer::calculate_sizes
void calculate_sizes()
Definition: mesh_optimizer.hh:40
RegionIdx::is_valid
bool is_valid() const
Returns false if the region has undefined/invalid value.
Definition: region.hh:78
Input::Type::Double
Class for declaration of the input data that are floating point numbers.
Definition: type_base.hh:534
Mesh::sort_permuted_nodes_elements
void sort_permuted_nodes_elements(std::vector< int > new_node_ids, std::vector< int > new_elem_ids)
Sort elements and nodes by order stored in permutation vectors.
Definition: mesh.cc:447
RegionDB::mark_used_region
void mark_used_region(unsigned int idx)
Definition: region.cc:235
Mesh::get_input_type
static const Input::Type::Record & get_input_type()
Definition: mesh.cc:76
BIHTree
Class for O(log N) lookup for intersections with a set of bounding boxes.
Definition: bih_tree.hh:38
THROW
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
Definition: exceptions.hh:53
Mesh::RegionSetBase
friend class RegionSetBase
Definition: mesh.h:612
Mesh::max_edge_sides_
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:526
std::vector< uint >
Mesh::count_side_types
void count_side_types()
Definition: mesh.cc:474
ElementAccessor< 3 >
Partitioning
Class for the mesh partitioning. This should provide:
Definition: partitioning.hh:52
Input::Type::FileName::output
static FileName output()
The factory function for declaring type FileName for input files.
Definition: type_base.cc:531
system.hh
arma::vec3
Definition: doxy_dummy_defs.hh:17
RegionDB::get_region
Region get_region(unsigned int id, unsigned int dim)
Definition: region.cc:150
BoundaryData
Definition: mesh_data.hh:40
Mesh::node_range
Range< NodeAccessor< 3 > > node_range() const
Returns range of nodes.
Definition: mesh.cc:1234
Partitioning::get_loc_part
const LongIdx * get_loc_part() const
Definition: partitioning.cc:85
Mesh::boundary
Boundary boundary(uint edge_idx) const
Definition: mesh.cc:270
EdgeData
Definition: mesh_data.hh:25
Armor::Array::resize
void resize(uint size)
Definition: armor.hh:710
uint
unsigned int uint
Definition: mh_dofhandler.hh:101
RegionIdx::idx
unsigned int idx() const
Returns a global index of the region.
Definition: region.hh:82
Mesh::n_local_nodes_
unsigned int n_local_nodes_
Hold number of local nodes (own + ghost), value is equal with size of node_4_loc array.
Definition: mesh.h:638
fmt::format
std::string format(CStringRef format_str, ArgList args)
Definition: format.h:3141
duplicate_nodes.h
Neighbour
Definition: neighbours.h:117
ElementAccessor::element
const Element * element() const
Definition: accessors.hh:195
FilePath::open_stream
void open_stream(Stream &stream) const
Definition: file_path.cc:211
Input::Array::begin
Iterator< ValueType > begin() const
Definition: accessors_impl.hh:145
Mesh::read_regions_from_input
void read_regions_from_input(Input::Array region_list)
Definition: mesh.cc:1077
RegionDB::create_label_from_id
std::string create_label_from_id(unsigned int id) const
Definition: region.cc:337
index_types.hh
RegionDB::el_to_reg_map_
MapElementIDToRegionID el_to_reg_map_
Definition: region.hh:571
BoundaryData::bc_ele_idx_
unsigned int bc_ele_idx_
Definition: mesh_data.hh:53
Mesh::get_intersection_search
IntersectionSearch get_intersection_search()
Getter for input type selection for intersection search algorithm.
Definition: mesh.cc:158
Mesh::optimize_memory_locality
bool optimize_memory_locality
Definition: mesh.h:545
Mesh::n_vb_neighbours
unsigned int n_vb_neighbours() const
Definition: mesh.cc:249
exceptions.hh
Mesh::n_elements
virtual unsigned int n_elements() const
Returns count of boundary or bulk elements.
Definition: mesh.h:389
Element
Definition: elements.h:40
MPI_Comm_rank
#define MPI_Comm_rank
Definition: mpi.h:236
ASSERT_PTR_DBG
#define ASSERT_PTR_DBG(ptr)
Definition of assert macro checking non-null pointer (PTR) only for debug mode.
Definition: asserts.hh:340
Mesh::optimize
void optimize()
Definition: mesh.cc:437
Mesh::el_ds
Distribution * el_ds
Parallel distribution of elements.
Definition: mesh.h:632
Region::id
unsigned int id() const
Returns id of the region (using RegionDB)
Definition: region.cc:37
Mesh::intersect_element_lists
void intersect_element_lists(vector< unsigned int > const &nodes_list, vector< unsigned int > &intersection_element_list)
Definition: mesh.cc:501
Mesh::n_sides_
int n_sides_
Definition: mesh.h:317
EdgeData::side_
SideIter * side_
Definition: mesh_data.hh:32
Input::Iterator
Definition: accessors.hh:143
Input::Type::Default
Class Input::Type::Default specifies default value of keys of a Input::Type::Record.
Definition: type_record.hh:61
RegionDB::undefined_dim
static const unsigned int undefined_dim
Definition: region.hh:332
MeshOptimizer::sort_nodes
std::vector< int > sort_nodes(std::vector< unsigned int > &node_permutation)
Definition: mesh_optimizer.hh:104
Mesh::output_internal_ngh_data
void output_internal_ngh_data()
Output of neighboring data into raw output.
Definition: mesh.cc:1254
Mesh::get_local_part
virtual const LongIdx * get_local_part()
Definition: mesh.cc:280
Distribution
Definition: distribution.hh:50
Mesh::node_ids_
BidirectionalMap< int > node_ids_
Maps node ids to indexes into vector node_vec_.
Definition: mesh.h:598
ElementAccessor::bounding_box
BoundingBox bounding_box() const
Definition: accessors.hh:253
accessors.hh
Mesh::BBsearch
@ BBsearch
Definition: mesh.h:117
Mesh::check_mesh_on_read
void check_mesh_on_read()
Definition: mesh.cc:312
Mesh::n_corners
unsigned int n_corners()
Definition: mesh.cc:254
BIHTree::find_point
void find_point(const Space< 3 >::Point &point, std::vector< unsigned int > &result_list, bool full_list=false) const
Definition: bih_tree.cc:287
Mesh::find_lower_dim_element
bool find_lower_dim_element(vector< unsigned int > &element_list, unsigned int dim, unsigned int &element_idx)
Definition: mesh.cc:533
Input::Record
Accessor to the data with type Type::Record.
Definition: accessors.hh:291
Mesh::get_bih_tree
const BIHTree & get_bih_tree()
Getter for BIH. Creates and compute BIH at first call.
Definition: mesh.cc:1117
Mesh::distribute_nodes
void distribute_nodes()
Fill array node_4_loc_ and create object node_ds_ according to element distribution.
Definition: mesh.cc:1369
sys_profiler.hh
Edge::side
SideIter side(const unsigned int i) const
Gets side iterator of the i -th side.
Definition: accessors_impl.hh:171
undef_idx
const unsigned int undef_idx
Definition: index_types.hh:32
Mesh::get_bc_mesh
BCMesh * get_bc_mesh()
Create boundary mesh if doesn't exist and return it.
Definition: mesh.cc:1363
RegionIdx::is_boundary
bool is_boundary() const
Returns true if it is a Boundary region and false if it is a Bulk region.
Definition: region.hh:74
mixed_mesh_intersections.hh
Input::Type::Record::allow_auto_conversion
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:133
accessors.hh
Mesh::el_4_loc
LongIdx * el_4_loc
Index set assigning to local element index its global index.
Definition: mesh.h:630
Mesh::elements_id_maps
void elements_id_maps(vector< LongIdx > &bulk_elements_id, vector< LongIdx > &boundary_elements_id) const
Definition: mesh.cc:831
INPUT_CATCH
#define INPUT_CATCH(ExceptionType, AddressEITag, input_accessor)
Definition: accessors.hh:63
Element::n_neighs_vb_
unsigned int n_neighs_vb_
Definition: elements.h:106
Mesh::side_nodes
vector< vector< vector< unsigned int > > > side_nodes
Definition: mesh.h:330
Mesh::node_permutation_
std::vector< unsigned int > node_permutation_
Vector of node permutations of optimized mesh (see class MeshOptimizer)
Definition: mesh.h:604
Mesh::canonical_faces
void canonical_faces()
Definition: mesh.cc:392
Mesh::region_db_
RegionDB region_db_
Definition: mesh.h:551
Distribution::get_lsizes_array
const unsigned int * get_lsizes_array()
get local sizes array
Definition: distribution.cc:142
Input::AbstractRecord
Accessor to the polymorphic input data of a type given by an AbstracRecord object.
Definition: accessors.hh:458
Neighbour::element
ElementAccessor< 3 > element()
Definition: neighbours.h:161
Input::Type::Default::obligatory
static Default obligatory()
The factory function to make an empty default value which is obligatory.
Definition: type_record.hh:110
ElementAccessor::jacobian_S3
double jacobian_S3() const
Definition: accessors.hh:131
Mesh::IntersectionSearch
IntersectionSearch
Types of search algorithm for finding intersection candidates.
Definition: mesh.h:114
RegionDB::close
void close()
Definition: region.cc:249
Mesh::find_elem_id
int find_elem_id(unsigned int pos) const
Return element id (in GMSH file) of element of given position in element vector.
Definition: mesh.h:403
ASSERT_EQ
#define ASSERT_EQ(a, b)
Definition of comparative assert macro (EQual)
Definition: asserts.hh:328
Element::init
void init(unsigned int dim, RegionIdx reg)
Definition: elements.cc:53
Mesh::init
void init()
Definition: mesh.cc:164
RegionDB::find_id
Region find_id(unsigned int id, unsigned int dim) const
Definition: region.cc:180
Input::Record::opt_val
bool opt_val(const string &key, Ret &value) const
Definition: accessors_impl.hh:107
Input::format_JSON
@ format_JSON
Definition: reader_to_storage.hh:60
Input::Type::Record::declare_key
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:503
Input::ReaderToStorage::get_root_interface
T get_root_interface() const
Returns the root accessor.
Definition: reader_to_storage.cc:150
Side::element
ElementAccessor< 3 > element() const
Returns iterator to the element of the side.
Definition: accessors_impl.hh:212
mesh.h
Mesh::bih_tree_
std::shared_ptr< BIHTree > bih_tree_
Definition: mesh.h:560
Mesh::node_ds_
Distribution * node_ds_
Parallel distribution of nodes. Depends on elements distribution.
Definition: mesh.h:636
Input::Type::Selection
Template for classes storing finite set of named values.
Definition: type_selection.hh:65
std::map< unsigned int, unsigned int >
Side::n_nodes
unsigned int n_nodes() const
Returns number of nodes of the side.
Definition: accessors.hh:450
Element::region_idx_
RegionIdx region_idx_
Definition: elements.h:113
ElementAccessor::node
NodeAccessor< 3 > node(unsigned int ni) const
Definition: accessors.hh:245
Input::Type::FileName::input
static FileName input()
The factory function for declaring type FileName for input files.
Definition: type_base.cc:524
Mesh::same_sides
bool same_sides(const SideIter &si, vector< unsigned int > &side_nodes)
Definition: mesh.cc:555
Armor::Array::set
ArrayMatSet set(uint index)
Definition: armor.hh:838
Input::Type::Record::close
Record & close() const
Close the Record for further declarations of keys.
Definition: type_record.cc:304
Mesh::element_to_neigh_vb
void element_to_neigh_vb()
Definition: mesh.cc:769
Element::node_idx
unsigned int node_idx(unsigned int ni) const
Return index (in Mesh::node_vec) of ni-th node.
Definition: elements.h:73
Mesh::check_element_size
void check_element_size(unsigned int elem_idx) const
Check if given index is in element_vec_.
Definition: mesh.cc:1246
Mesh::add_element
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:1143
Side::side_idx
unsigned int side_idx() const
Returns local index of the side on the element.
Definition: accessors.hh:458
Input::Type
Definition: balance.hh:41
partitioning.hh
Partitioning::get_input_type
static const Input::Type::Record & get_input_type()
Definition: partitioning.cc:49
RegionDB::implicit_boundary_region
Region implicit_boundary_region()
Definition: region.cc:75
Input::Type::Record
Record type proxy class.
Definition: type_record.hh:182
MPI_Comm
int MPI_Comm
Definition: mpi.h:141
Mesh::Element
friend class Element
Definition: mesh.h:613
Mesh::~Mesh
virtual ~Mesh()
Destructor.
Definition: mesh.cc:215
Mesh::Edge
friend class Edge
Definition: mesh.h:610
Element::neigh_vb
Neighbour ** neigh_vb
Definition: elements.h:86
Element::nodes_
std::array< unsigned int, 4 > nodes_
indices to element's nodes
Definition: elements.h:117
Interaction
Definition: ref_element.hh:286
Mesh::create_node_element_lists
void create_node_element_lists()
Definition: mesh.cc:488
Element::edge_idx
unsigned int edge_idx(unsigned int edg_idx) const
Return edge_idx of given index.
Definition: elements.h:142
EdgeData::n_sides
unsigned int n_sides
Definition: mesh_data.hh:29
LongIdx
int LongIdx
Define type that represents indices of large arrays (elements, nodes, dofs etc.)
Definition: index_types.hh:24
Mesh::setup_topology
void setup_topology()
Definition: mesh.cc:401
input_type.hh
Mesh::add_element_to_vector
Element * add_element_to_vector(int id)
Adds element to mesh data structures (element_vec_, element_ids_), returns pointer to this element.
Definition: mesh.cc:1220
Mesh::modify_element_ids
void modify_element_ids(const RegionDB::MapElementIDToRegionID &map)
Definition: mesh.cc:287
Mesh
Definition: mesh.h:77
equal_elm
bool equal_elm(ElementAccessor< 3 > elm1, ElementAccessor< 3 > elm2)
Definition: mesh.cc:991
Armor::Array::reinit
void reinit(uint size)
Definition: armor.hh:698
Element::n_sides
unsigned int n_sides() const
Definition: elements.h:138
Mesh::BIHsearch
@ BIHsearch
Definition: mesh.h:115
Mesh::elem_index
int elem_index(int elem_id) const
For element of given elem_id returns index in element_vec_ or (-1) if element doesn't exist.
Definition: mesh.h:397
Range
Range helper class.
Definition: range_wrapper.hh:65
Input::Type::Array
Class for declaration of inputs sequences.
Definition: type_base.hh:339
OLD_ASSERT
#define OLD_ASSERT(...)
Definition: global_defs.h:108
Mesh::edges
std::vector< EdgeData > edges
Vector of MH edges, this should not be part of the geometrical mesh.
Definition: mesh.h:601
Mesh::make_neighbours_and_edges
void make_neighbours_and_edges()
Definition: mesh.cc:572
BidirectionalMap::clear
void clear()
Clear the content. Do not release memory.
Definition: bidirectional_map.hh:121
Mesh::init_node_vector
void init_node_vector(unsigned int size)
Initialize node_vec_, set size.
Definition: mesh.cc:1211
Mesh::check_compatible_mesh
virtual std::shared_ptr< std::vector< LongIdx > > check_compatible_mesh(Mesh &input_mesh)
Definition: mesh.cc:872
Mesh::elem_permutation_
std::vector< unsigned int > elem_permutation_
Vector of element permutations of optimized mesh (see class MeshOptimizer)
Definition: mesh.h:607
Edge
Definition: accessors.hh:308
Input::Array
Accessor to input data conforming to declared Array.
Definition: accessors.hh:566
Mesh::Mesh
Mesh()
Definition: mesh.cc:104
WarningOut
#define WarningOut()
Macro defining 'warning' record of log.
Definition: logger.hh:278
RegionIdx
Definition: region.hh:67
Input::Type::Record::finish
FinishStatus finish(FinishStatus finish_type=FinishStatus::regular_) override
Finish declaration of the Record type.
Definition: type_record.cc:243
Armor::Array::append
void append(const ArmaMat< Type, nr, nc > &item)
Definition: armor.hh:736
region_set.hh
ElementAccessor::region
Region region() const
Definition: accessors.hh:201
Mesh::node_index
int node_index(int node_id) const
For node of given node_id returns index in element_vec_ or (-1) if node doesn't exist.
Definition: mesh.h:415
BCMesh
Class represents boundary part of mesh.
Definition: bc_mesh.hh:35
Mesh::check_and_finish
void check_and_finish()
Definition: mesh.cc:1087
Mesh::edge_range
Range< Edge > edge_range() const
Returns range of edges.
Definition: mesh.cc:1240
NodeAccessor
Definition: mesh.h:55
Mesh::node_elements_
vector< vector< unsigned int > > node_elements_
For each node the vector contains a list of elements that use this node.
Definition: mesh.h:394
MPI_COMM_WORLD
#define MPI_COMM_WORLD
Definition: mpi.h:123
ASSERT_LT_DBG
#define ASSERT_LT_DBG(a, b)
Definition of comparative assert macro (Less Than) only for debug mode.
Definition: asserts.hh:300
region.hh
Mesh::element_ids_
BidirectionalMap< int > element_ids_
Maps element ids to indexes into vector element_vec_.
Definition: mesh.h:590
Armor::Array< double >
Mesh::add_node
void add_node(unsigned int node_id, arma::vec3 coords)
Add new node of given id and coordinates to mesh.
Definition: mesh.cc:1135
Mesh::bc_element_tmp_
vector< ElementTmpData > bc_element_tmp_
Hold data of boundary elements during reading mesh (allow to preserve correct order during reading of...
Definition: mesh.h:581
BIHTree::find_bounding_box
void find_bounding_box(const BoundingBox &boundingBox, std::vector< unsigned int > &result_list, bool full_list=false) const
Definition: bih_tree.cc:234
ElementAccessor::idx
unsigned int idx() const
Return local idx of element in boundary / bulk part of element vector.
Definition: accessors.hh:223
NDEF
#define NDEF
Definition: mesh.cc:61
RegionDB::add_region
Region add_region(unsigned int id, const std::string &label, unsigned int dim, const std::string &address="implicit")
Definition: region.cc:85
MeshOptimizer
Definition: mesh_optimizer.hh:35
Mesh::part_
std::shared_ptr< Partitioning > part_
Definition: mesh.h:555
print_var
#define print_var(var)
Definition: logger.hh:292
Mesh::bulk_size_
unsigned int bulk_size_
Count of bulk elements.
Definition: mesh.h:584
BidirectionalMap::add_item
unsigned int add_item(T val)
Add new item at the end position of map.
Definition: bidirectional_map.hh:106
RegionDB::print_region_table
void print_region_table(std::ostream &stream) const
Definition: region.cc:409
Mesh::row_4_el
LongIdx * row_4_el
Index set assigning to global element index the local index used in parallel vectors.
Definition: mesh.h:628
Mesh::node_elements
const vector< vector< unsigned int > > & node_elements()
Definition: mesh.cc:1189
Mesh::global_snap_radius
double global_snap_radius() const
Maximal distance of observe point from Mesh relative to its size.
Definition: mesh.cc:1126
Mesh::boundary_
vector< BoundaryData > boundary_
Definition: mesh.h:292
Mesh::Boundary
friend class Boundary
Definition: mesh.h:615
Mesh::n_local_nodes
unsigned int n_local_nodes() const
Definition: mesh.h:192
Mesh::get_part
virtual Partitioning * get_part()
Definition: mesh.cc:276
Mesh::n_insides
int n_insides
Definition: mesh.h:315
Side::node
NodeAccessor< 3 > node(unsigned int i) const
Returns node for given local index i on the side.
Definition: accessors_impl.hh:206
Mesh::bc_mesh_
BCMesh * bc_mesh_
Boundary mesh, object is created only if it's necessary.
Definition: mesh.h:640
Mesh::mixed_intersections
MixedMeshIntersections & mixed_intersections()
Definition: mesh.cc:802
DebugOut
#define DebugOut()
Macro defining 'debug' record of log.
Definition: logger.hh:284
Input::Type::Selection::add_value
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.
Definition: type_selection.cc:50
Mesh::BIHonly
@ BIHonly
Definition: mesh.h:116
ASSERT_PTR
#define ASSERT_PTR(ptr)
Definition of assert macro checking non-null pointer (PTR)
Definition: asserts.hh:336
ElementAccessor::side
SideIter side(const unsigned int loc_index)
Definition: accessors_impl.hh:139
Mesh::node
NodeAccessor< 3 > node(unsigned int idx) const
Create and return NodeAccessor to node of given idx.
Definition: mesh.cc:825
Mesh::element_accessor
virtual ElementAccessor< 3 > element_accessor(unsigned int idx) const
Create and return ElementAccessor to element of given idx.
Definition: mesh.cc:819
BoundaryData::mesh_
Mesh * mesh_
Definition: mesh_data.hh:54
BidirectionalMap::reserve
void reserve(unsigned int init_size=0)
Reset data of map, reserve space for given size.
Definition: bidirectional_map.hh:139
Input::Type::Default::optional
static Default optional()
The factory function to make an empty default value which is optional.
Definition: type_record.hh:124
Mesh::n_nodes
virtual unsigned int n_nodes() const
Definition: mesh.h:149
START_TIMER
#define START_TIMER(tag)
Starts a timer with specified tag.
Definition: sys_profiler.hh:115
Input::Array::end
IteratorBase end() const
Definition: accessors_impl.hh:157
Mesh::find_node_id
int find_node_id(unsigned int pos) const
Return node id (in GMSH file) of node of given position in node vector.
Definition: mesh.h:421
SideIter
Definition: accessors.hh:504
Input::Record::is_empty
bool is_empty() const
Definition: accessors.hh:365
Element::boundary_idx_
unsigned int * boundary_idx_
Definition: elements.h:82
Mesh::edge
Edge edge(uint edge_idx) const
Definition: mesh.cc:264
Mesh::add_physical_name
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:1130
Mesh::vb_neighbours_
vector< Neighbour > vb_neighbours_
Definition: mesh.h:313
END_TIMER
#define END_TIMER(tag)
Ends a timer with specified tag.
Definition: sys_profiler.hh:149
Element::n_nodes
unsigned int n_nodes() const
Definition: elements.h:132
Mesh::ElementTmpData
Definition: mesh.h:454
DuplicateNodes
Definition: duplicate_nodes.h:96
BidirectionalMap::size
unsigned int size() const
Return size of map.
Definition: bidirectional_map.hh:80
range_wrapper.hh
Implementation of range helper class.
MessageOut
#define MessageOut()
Macro defining 'message' record of log.
Definition: logger.hh:275
node_accessor.hh
Mesh::intersections
std::shared_ptr< MixedMeshIntersections > intersections
Definition: mesh.h:300