Flow123d  release_2.1.0-84-g6a13a75
mesh.h
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.h
15  * @brief
16  */
17 
18 #ifndef MAKE_MESH_H
19 #define MAKE_MESH_H
20 
21 #include <vector>
22 #include <mpi.h>
23 
24 #include "mesh/mesh_types.hh"
25 
26 #include "mesh/nodes.hh"
27 //#include "mesh/elements.h"
28 //#include "mesh/sides.h"
29 #include "mesh/edges.h"
30 #include "mesh/neighbours.h"
31 #include "mesh/boundaries.h"
32 #include "mesh/intersection.hh"
33 #include "mesh/partitioning.hh"
34 #include "mesh/region_set.hh"
35 
36 
39 #include "system/exceptions.hh"
40 
41 
42 
43 
44 #define ELM 0
45 #define BC 1
46 #define NODE 2
47 
48 /**
49  * This parameter limits volume of elements from below.
50  */
51 #define MESH_CRITICAL_VOLUME 1.0E-12
52 
53 /**
54  * Provides for statement to iterate over the Nodes of the Mesh.
55  * The parameter is FullIter local variable of the cycle, so it need not be declared before.
56  * Macro assume that variable Mesh *mesh; is declared and points to a valid Mesh structure.
57  */
58 #define FOR_NODES(_mesh_, i) \
59  for( NodeFullIter i( (_mesh_)->node_vector.begin() ); \
60  i != (_mesh_)->node_vector.end(); \
61  ++i)
62 
63 /**
64  * Macro for conversion form Iter to FullIter for nodes.
65  */
66 #define NODE_FULL_ITER(_mesh_,i) \
67  (_mesh_)->node_vector.full_iter(i)
68 
69 /**
70  * Macro to get "NULL" ElementFullIter.
71  */
72 #define NODE_FULL_ITER_NULL(_mesh_) \
73  NodeFullIter((_mesh_)->node_vector)
74 
75 /**
76  * Macro for conversion form Iter to FullIter for elements.
77  */
78 #define ELEM_FULL_ITER(_mesh_,i) \
79  (_mesh_)->element.full_iter(i)
80 
81 
82 #define FOR_NODE_ELEMENTS(i,j) for((j)=0;(j)<(i)->n_elements();(j)++)
83 #define FOR_NODE_SIDES(i,j) for((j)=0;(j)<(i)->n_sides;(j)++)
84 
85 
87 public:
89 };
90 
91 //=============================================================================
92 // STRUCTURE OF THE MESH
93 //=============================================================================
94 
95 class Mesh {
96 public:
97  TYPEDEF_ERR_INFO( EI_ElemLast, int);
98  TYPEDEF_ERR_INFO( EI_ElemNew, int);
99  TYPEDEF_ERR_INFO( EI_RegLast, std::string);
100  TYPEDEF_ERR_INFO( EI_RegNew, std::string);
101  DECLARE_EXCEPTION(ExcDuplicateBoundary,
102  << "Duplicate boundary elements! \n"
103  << "Element id: " << EI_ElemLast::val << " on region name: " << EI_RegLast::val << "\n"
104  << "Element id: " << EI_ElemNew::val << " on region name: " << EI_RegNew::val << "\n");
105 
106 
107 
108  static const unsigned int undef_idx=-1;
109  static const Input::Type::Record & get_input_type();
110 
111 
112 
113  /** Labels for coordinate indexes in arma::vec3 representing vectors and points.*/
114  enum {x_coord=0, y_coord=1, z_coord=2};
115 
116  /**
117  * Constructor from an input record.
118  * Do not process input record. That is done in init_from_input.
119  */
120  Mesh(Input::Record in_record, MPI_Comm com = MPI_COMM_WORLD);
121  /**
122  * Common part of both previous constructors and way how to reinitialize a mesh from the given input record.
123  */
124  void reinit(Input::Record in_record);
125 
126  /// Destructor.
127  ~Mesh();
128 
129  inline unsigned int n_nodes() const {
130  return node_vector.size();
131  }
132 
133  inline unsigned int n_elements() const {
134  return element.size();
135  }
136 
137  inline unsigned int n_boundaries() const {
138  return boundary_.size();
139  }
140 
141  inline unsigned int n_edges() const {
142  return edges.size();
143  }
144 
145  unsigned int n_corners();
146 
147  inline const RegionDB &region_db() const {
148  return region_db_;
149  }
150 
151  /**
152  * Returns pointer to partitioning object. Partitioning is created during setup_topology.
153  */
154  Partitioning *get_part();
155 
157  { return el_ds; }
158 
159  int *get_row_4_el() const
160  { return row_4_el; }
161 
162  int *get_el_4_loc() const
163  { return el_4_loc; }
164 
165  /**
166  * Returns MPI communicator of the mesh.
167  */
168  inline MPI_Comm get_comm() const { return comm_; }
169 
170 
171  void make_intersec_elements();
172 
173  unsigned int n_sides();
174 
175  inline unsigned int n_vb_neighbours() const {
176  return vb_neighbours_.size();
177  }
178 
179  /**
180  * Returns maximal number of sides of one edge, which connects elements of dimension @p dim.
181  * @param dim Dimension of elements sharing the edge.
182  */
183  unsigned int max_edge_sides(unsigned int dim) const { return max_edge_sides_[dim-1]; }
184 
185  /**
186  * Reads mesh from stream.
187  *
188  * Method is especially used in unit tests.
189  */
190  void read_gmsh_from_stream(istream &in);
191  /**
192  * Reads input record, creates regions, read the mesh, setup topology. creates region sets.
193  */
194  void init_from_input();
195 
196 
197  /**
198  * Returns vector of ID numbers of elements, either bulk or bc elemnts.
199  */
200  vector<int> const & elements_id_maps( bool boundary_domain) const;
201 
202 
203  ElementAccessor<3> element_accessor(unsigned int idx, bool boundary=false);
204 
205  /**
206  * Reads elements and their affiliation to regions and region sets defined by user in input file
207  * Format of input record is defined in method RegionSetBase::get_input_type()
208  *
209  * @param region_list Array input AbstractRecords which define regions, region sets and elements
210  */
211  void read_regions_from_input(Input::Array region_list);
212 
213  /// Vector of nodes of the mesh.
215  /// Vector of elements of the mesh.
217 
218  /// Vector of boundary sides where is prescribed boundary condition.
219  /// TODO: apply all boundary conditions in the main assembling cycle over elements and remove this Vector.
221  /// vector of boundary elements - should replace 'boundary'
222  /// TODO: put both bulk and bc elements (on zero level) to the same vector or make better map id->element for field inputs that use element IDs
223  /// the avoid usage of ElementVector etc.
225 
226  /// Vector of MH edges, this should not be part of the geometrical mesh
228 
229  //flow::VectorId<int> bcd_group_id; // gives a index of group for an id
230 
231  /**
232  * Vector of individual intersections of two elements.
233  * This is enough for local mortar.
234  */
236 
237  /**
238  * For every element El we have vector of indices into @var intersections array for every intersection in which El is master element.
239  * This is necessary for true mortar.
240  */
242 
243  /**
244  * Vector of compatible neighbourings.
245  */
247 
248  int n_insides; // # of internal sides
249  int n_exsides; // # of external sides
250  int n_sides_; // total number of sides (should be easy to count when we have separated dimensions
251 
252  int n_lines; // Number of line elements
253  int n_triangles; // Number of triangle elements
254  int n_tetrahedras; // Number of tetrahedra elements
255 
256  // Temporary solution for numbering of nodes on sides.
257  // The data are defined in RefElement<dim>::side_nodes,
258  // Mesh::side_nodes can be removed as soon as Element
259  // is templated by dimension.
260  //
261  // for every side dimension D = 0 .. 2
262  // for every element side 0 .. D+1
263  // for every side node 0 .. D
264  // index into element node array
266 
267  /**
268  * Check usage of regions, set regions to elements defined by user, close RegionDB
269  */
270  void check_and_finish();
271 
272  const BIHTree &get_bih_tree();
273 
274  // For each node the vector contains a list of elements that use this node
276 
277 
278 protected:
279 
280  /**
281  * This replaces read_neighbours() in order to avoid using NGH preprocessor.
282  *
283  * TODO:
284  * - Avoid maps:
285  *
286  * 4) replace EdgeVector by std::vector<Edge> (need not to know the size)
287  *
288  * 5) need not to have temporary array for Edges, only postpone setting pointers in elements and set them
289  * after edges are found; we can temporary save Edge index instead of pointer in Neigbours and elements
290  *
291  * 6) Try replace Edge * by indexes in Neigbours and elements (anyway we have mesh pointer in elements so it is accessible also from Neigbours)
292  *
293  */
294  void make_neighbours_and_edges();
295 
296  /**
297  * On edges sharing sides of many elements it may happen that each side has its nodes ordered in a different way.
298  * This method finds the permutation for each side so as to obtain the ordering of side 0.
299  */
300  void make_edge_permutations();
301  /**
302  * Create element lists for nodes in Mesh::nodes_elements.
303  */
304  void create_node_element_lists();
305  /**
306  * Find intersection of element lists given by Mesh::node_elements for elements givne by @p nodes_list parameter.
307  * The result is placed into vector @p intersection_element_list. If the @p node_list is empty, and empty intersection is
308  * returned.
309  */
310  void intersect_element_lists(vector<unsigned int> const &nodes_list, vector<unsigned int> &intersection_element_list);
311  /**
312  * Remove elements with dimension not equal to @p dim from @p element_list. Index of the first element of dimension @p dim-1,
313  * is returned in @p element_idx. If no such element is found the method returns false, if one such element is found the method returns true,
314  * if more elements are found we report an user input error.
315  */
316  bool find_lower_dim_element(ElementVector&elements, vector<unsigned int> &element_list, unsigned int dim, unsigned int &element_idx);
317 
318  /**
319  * Returns true if side @p si has same nodes as in the list @p side_nodes.
320  */
321  bool same_sides(const SideIter &si, vector<unsigned int> &side_nodes);
322 
323  /**
324  * Initialize all mesh structures from raw information about nodes and elements (including boundary elements).
325  * Namely: create remaining boundary elements and Boundary objects, find edges and compatible neighborings.
326  */
327  void setup_topology();
328 
329 
330  void element_to_neigh_vb();
331 
332  void count_element_types();
333  void count_side_types();
334 
335  /**
336  * Possibly modify region id of elements sets by user in "regions" part of input file.
337  *
338  * TODO: This method needs check in issue 'Review mesh setting'.
339  * Changes have been done during generalized region key and may be causing problems
340  * during the further development.
341  */
342  void modify_element_ids(const RegionDB::MapElementIDToRegionID &map);
343 
344  unsigned int n_bb_neigh, n_vb_neigh;
345 
346  /// Vector of both bulk and boundary IDs. Bulk elements come first, then boundary elements, but only the portion that appears
347  /// in input mesh file and has ID assigned.
348  ///
349  /// TODO: Rather should be part of GMSH reader, but in such case we need store pointer to it in the mesh (good idea, but need more general interface for readers)
350  mutable vector<int> bulk_elements_id_, boundary_elements_id_;
351  /// Number of elements read from input.
352  unsigned int n_all_input_elements_;
353 
354  /// Maximal number of sides per one edge in the actual mesh (set in make_neighbours_and_edges()).
355  unsigned int max_edge_sides_[3];
356 
357  /**
358  * Database of regions (both bulk and boundary) of the mesh. Regions are logical parts of the
359  * domain that allows setting of different data and boundary conditions on them.
360  */
362  /**
363  * Mesh partitioning. Created in setup_topology.
364  */
365  std::shared_ptr<Partitioning> part_;
366 
367  /**
368  * BIH Tree for intersection and observe points lookup.
369  */
370  std::shared_ptr<BIHTree> bih_tree_;
371  /**
372  * Accessor to the input record for the mesh.
373  */
375 
376  /**
377  * MPI communicator used for partitioning and ...
378  */
380 
381  friend class GmshMeshReader;
382  friend class RegionSetBase;
383 
384 
385 private:
386 
387  /// Index set assigning to global element index the local index used in parallel vectors.
388  int *row_4_el;
389  /// Index set assigning to local element index its global index.
390  int *el_4_loc;
391  /// Parallel distribution of elements.
393 };
394 
395 
396 #include "mesh/side_impl.hh"
397 #include "mesh/element_impls.hh"
398 #include "mesh/neighbours_impl.hh"
399 
400 /**
401  * Provides for statement to iterate over the Elements of the Mesh.
402  * The parameter is FullIter local variable of the cycle, so it need not be declared before.
403  * Macro assume that variable Mesh *mesh; is declared and points to a valid Mesh structure.
404  */
405 #define FOR_ELEMENTS(_mesh_,__i) \
406  for( ElementFullIter __i( (_mesh_)->element.begin() ); \
407  __i != (_mesh_)->element.end(); \
408  ++__i)
409 
410 /**
411  * Macro for conversion form Iter to FullIter for elements.
412  */
413 #define ELEMENT_FULL_ITER(_mesh_,i) \
414  (_mesh_)->element.full_iter(i)
415 
416 /**
417  * Macro to get "NULL" ElementFullIter.
418  */
419 #define ELEMENT_FULL_ITER_NULL(_mesh_) \
420  ElementFullIter((_mesh_)->element)
421 
422 
423 #define FOR_BOUNDARIES(_mesh_,i) \
424 for( std::vector<Boundary>::iterator i= (_mesh_)->boundary_.begin(); \
425  i != (_mesh_)->boundary_.end(); \
426  ++i)
427 
428 /**
429  * Macro for conversion form Iter to FullIter for boundaries.
430  */
431 #define BOUNDARY_FULL_ITER(_mesh_,i) \
432  (_mesh_)->boundary.full_iter(i)
433 
434 /**
435  * Macro to get "NULL" BoundaryFullIter.
436  */
437 #define BOUNDARY_NULL(_mesh_) \
438  BoundaryFullIter((_mesh_)->boundary)
439 
440 
441 /**
442  * Provides for statement to iterate over the Edges of the Mesh. see FOR_ELEMENTS
443  */
444 #define FOR_EDGES(_mesh_,__i) \
445  for( vector<Edge>::iterator __i = (_mesh_)->edges.begin(); \
446  __i !=(_mesh_)->edges.end(); \
447  ++__i)
448 
449 #define FOR_SIDES(_mesh_, it) \
450  FOR_ELEMENTS((_mesh_), ele) \
451  for(SideIter it = ele->side(0); it->el_idx() < ele->n_sides(); ++it)
452 
453 #define FOR_SIDE_NODES(i,j) for((j)=0;(j)<(i)->n_nodes;(j)++)
454 
455 
456 #define FOR_NEIGHBOURS(_mesh_, it) \
457  for( std::vector<Neighbour>::iterator it = (_mesh_)->vb_neighbours_.begin(); \
458  (it)!= (_mesh_)->vb_neighbours_.end(); ++it)
459 
460 #define FOR_NEIGH_ELEMENTS(i,j) for((j)=0;(j)<(i)->n_elements;(j)++)
461 #define FOR_NEIGH_SIDES(i,j) for((j)=0;(j)<(i)->n_sides;(j)++)
462 
463 
464 #endif
465 //-----------------------------------------------------------------------------
466 // vim: set cindent:
int n_triangles
Definition: mesh.h:253
Distribution * el_ds
Parallel distribution of elements.
Definition: mesh.h:392
Class for the mesh partitioning. This should provide:
Definition: partitioning.hh:39
vector< vector< unsigned int > > node_elements
Definition: mesh.h:275
Accessor to input data conforming to declared Array.
Definition: accessors.hh:561
int MPI_Comm
Definition: mpi.h:141
Nodes of a mesh.
static Input::Type::Record input_type
Definition: mesh.h:88
int n_lines
Definition: mesh.h:252
#define DECLARE_EXCEPTION(ExcName, Format)
Macro for simple definition of exceptions.
Definition: exceptions.hh:150
Definition: mesh.h:95
Input::Record in_record_
Definition: mesh.h:374
int * get_el_4_loc() const
Definition: mesh.h:162
vector< vector< vector< unsigned int > > > side_nodes
Definition: mesh.h:265
int n_tetrahedras
Definition: mesh.h:254
const RegionDB & region_db() const
Definition: mesh.h:147
vector< Boundary > boundary_
Definition: mesh.h:220
int * el_4_loc
Index set assigning to local element index its global index.
Definition: mesh.h:390
int * row_4_el
Index set assigning to global element index the local index used in parallel vectors.
Definition: mesh.h:388
int n_exsides
Definition: mesh.h:249
unsigned int n_vb_neighbours() const
Definition: mesh.h:175
unsigned int n_elements() const
Definition: mesh.h:133
MPI_Comm get_comm() const
Definition: mesh.h:168
unsigned int n_boundaries() const
Definition: mesh.h:137
Accessor to the data with type Type::Record.
Definition: accessors.hh:286
Class for O(log N) lookup for intersections with a set of bounding boxes.
Definition: bih_tree.hh:36
ElementVector bc_elements
Definition: mesh.h:224
#define TYPEDEF_ERR_INFO(EI_Type, Type)
Macro to simplify declaration of error_info types.
Definition: exceptions.hh:186
std::shared_ptr< BIHTree > bih_tree_
Definition: mesh.h:370
Distribution * get_el_ds() const
Definition: mesh.h:156
vector< vector< unsigned int > > master_elements
Definition: mesh.h:241
vector< Neighbour > vb_neighbours_
Definition: mesh.h:246
unsigned int n_vb_neigh
Definition: mesh.h:344
unsigned int n_all_input_elements_
Number of elements read from input.
Definition: mesh.h:352
int n_sides_
Definition: mesh.h:250
unsigned int max_edge_sides(unsigned int dim) const
Definition: mesh.h:183
int * get_row_4_el() const
Definition: mesh.h:159
RegionDB region_db_
Definition: mesh.h:361
std::vector< Edge > edges
Vector of MH edges, this should not be part of the geometrical mesh.
Definition: mesh.h:227
vector< Intersection > intersections
Definition: mesh.h:235
MPI_Comm comm_
Definition: mesh.h:379
int n_insides
Definition: mesh.h:248
#define MPI_COMM_WORLD
Definition: mpi.h:123
unsigned int n_nodes() const
Definition: mesh.h:129
Record type proxy class.
Definition: type_record.hh:177
unsigned int n_edges() const
Definition: mesh.h:141
vector< int > bulk_elements_id_
Definition: mesh.h:350
std::shared_ptr< Partitioning > part_
Definition: mesh.h:365
NodeVector node_vector
Vector of nodes of the mesh.
Definition: mesh.h:214
ElementVector element
Vector of elements of the mesh.
Definition: mesh.h:216