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