Flow123d  last_with_con_2.0.0-4-g42e6930
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 with input record given by string. Aimed for testing purpose.
118  * Do not process input record. That is done in init_from_input.
119  */
120  Mesh(const std::string &input_str="{mesh_file=\"\"}", MPI_Comm com = MPI_COMM_WORLD);
121  /**
122  * Constructor from an input record.
123  * Do not process input record. That is done in init_from_input.
124  */
125  Mesh(Input::Record in_record, MPI_Comm com = MPI_COMM_WORLD);
126  /**
127  * Common part of both previous constructors and way how to reinitialize a mesh from the given input record.
128  */
129  void reinit(Input::Record in_record);
130 
131  /// Destructor.
132  ~Mesh();
133 
134  inline unsigned int n_nodes() const {
135  return node_vector.size();
136  }
137 
138  inline unsigned int n_elements() const {
139  return element.size();
140  }
141 
142  inline unsigned int n_boundaries() const {
143  return boundary_.size();
144  }
145 
146  inline unsigned int n_edges() const {
147  return edges.size();
148  }
149 
150  unsigned int n_corners();
151 
152  inline const RegionDB &region_db() const {
153  return region_db_;
154  }
155 
156  /**
157  * Returns pointer to partitioning object. Partitioning is created during setup_topology.
158  */
159  Partitioning *get_part();
160 
162  { return el_ds; }
163 
164  int *get_row_4_el() const
165  { return row_4_el; }
166 
167  int *get_el_4_loc() const
168  { return el_4_loc; }
169 
170  /**
171  * Returns MPI communicator of the mesh.
172  */
173  inline MPI_Comm get_comm() const { return comm_; }
174 
175 
176  void make_intersec_elements();
177 
178  unsigned int n_sides();
179 
180  inline unsigned int n_vb_neighbours() const {
181  return vb_neighbours_.size();
182  }
183 
184  /**
185  * Returns maximal number of sides of one edge, which connects elements of dimension @p dim.
186  * @param dim Dimension of elements sharing the edge.
187  */
188  unsigned int max_edge_sides(unsigned int dim) const { return max_edge_sides_[dim-1]; }
189 
190  /**
191  * Reads mesh from stream.
192  *
193  * Method is especially used in unit tests.
194  */
195  void read_gmsh_from_stream(istream &in);
196  /**
197  * Reads input record, creates regions, read the mesh, setup topology. creates region sets.
198  */
199  void init_from_input();
200 
201 
202  /**
203  * Returns vector of ID numbers of elements, either bulk or bc elemnts.
204  */
205  vector<int> const & elements_id_maps( bool boundary_domain) const;
206 
207 
208  ElementAccessor<3> element_accessor(unsigned int idx, bool boundary=false);
209 
210  /**
211  * Reads elements and their affiliation to regions and region sets defined by user in input file
212  * Format of input record is defined in method RegionSetBase::get_input_type()
213  *
214  * @param region_list Array input AbstractRecords which define regions, region sets and elements
215  */
216  void read_regions_from_input(Input::Array region_list);
217 
218  /// Vector of nodes of the mesh.
220  /// Vector of elements of the mesh.
222 
223  /// Vector of boundary sides where is prescribed boundary condition.
224  /// TODO: apply all boundary conditions in the main assembling cycle over elements and remove this Vector.
226  /// vector of boundary elements - should replace 'boundary'
227  /// 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
228  /// the avoid usage of ElementVector etc.
230 
231  /// Vector of MH edges, this should not be part of the geometrical mesh
233 
234  //flow::VectorId<int> bcd_group_id; // gives a index of group for an id
235 
236  /**
237  * Vector of individual intersections of two elements.
238  * This is enough for local mortar.
239  */
241 
242  /**
243  * For every element El we have vector of indices into @var intersections array for every intersection in which El is master element.
244  * This is necessary for true mortar.
245  */
247 
248  /**
249  * Vector of compatible neighbourings.
250  */
252 
253  int n_insides; // # of internal sides
254  int n_exsides; // # of external sides
255  int n_sides_; // total number of sides (should be easy to count when we have separated dimensions
256 
257  int n_lines; // Number of line elements
258  int n_triangles; // Number of triangle elements
259  int n_tetrahedras; // Number of tetrahedra elements
260 
261  // Temporary solution for numbering of nodes on sides.
262  // The data are defined in RefElement<dim>::side_nodes,
263  // Mesh::side_nodes can be removed as soon as Element
264  // is templated by dimension.
265  //
266  // for every side dimension D = 0 .. 2
267  // for every element side 0 .. D+1
268  // for every side node 0 .. D
269  // index into element node array
271 
272  /**
273  * Check usage of regions, set regions to elements defined by user, close RegionDB
274  */
275  void check_and_finish();
276 
277  const BIHTree &get_bih_tree();
278 
279  // For each node the vector contains a list of elements that use this node
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  /// Maximal number of sides per one edge in the actual mesh (set in make_neighbours_and_edges()).
360  unsigned int max_edge_sides_[3];
361 
362  /**
363  * Database of regions (both bulk and boundary) of the mesh. Regions are logical parts of the
364  * domain that allows setting of different data and boundary conditions on them.
365  */
367  /**
368  * Mesh partitioning. Created in setup_topology.
369  */
370  std::shared_ptr<Partitioning> part_;
371 
372  /**
373  * BIH Tree for intersection and observe points lookup.
374  */
375  std::shared_ptr<BIHTree> bih_tree_;
376  /**
377  * Accessor to the input record for the mesh.
378  */
380 
381  /**
382  * MPI communicator used for partitioning and ...
383  */
385 
386  friend class GmshMeshReader;
387  friend class RegionSetBase;
388 
389 
390 private:
391 
392  /// Index set assigning to global element index the local index used in parallel vectors.
393  int *row_4_el;
394  /// Index set assigning to local element index its global index.
395  int *el_4_loc;
396  /// Parallel distribution of elements.
398 };
399 
400 
401 #include "mesh/side_impl.hh"
402 #include "mesh/element_impls.hh"
403 #include "mesh/neighbours_impl.hh"
404 
405 /**
406  * Provides for statement to iterate over the Elements of the Mesh.
407  * The parameter is FullIter local variable of the cycle, so it need not be declared before.
408  * Macro assume that variable Mesh *mesh; is declared and points to a valid Mesh structure.
409  */
410 #define FOR_ELEMENTS(_mesh_,__i) \
411  for( ElementFullIter __i( (_mesh_)->element.begin() ); \
412  __i != (_mesh_)->element.end(); \
413  ++__i)
414 
415 /**
416  * Macro for conversion form Iter to FullIter for elements.
417  */
418 #define ELEMENT_FULL_ITER(_mesh_,i) \
419  (_mesh_)->element.full_iter(i)
420 
421 /**
422  * Macro to get "NULL" ElementFullIter.
423  */
424 #define ELEMENT_FULL_ITER_NULL(_mesh_) \
425  ElementFullIter((_mesh_)->element)
426 
427 
428 #define FOR_BOUNDARIES(_mesh_,i) \
429 for( std::vector<Boundary>::iterator i= (_mesh_)->boundary_.begin(); \
430  i != (_mesh_)->boundary_.end(); \
431  ++i)
432 
433 /**
434  * Macro for conversion form Iter to FullIter for boundaries.
435  */
436 #define BOUNDARY_FULL_ITER(_mesh_,i) \
437  (_mesh_)->boundary.full_iter(i)
438 
439 /**
440  * Macro to get "NULL" BoundaryFullIter.
441  */
442 #define BOUNDARY_NULL(_mesh_) \
443  BoundaryFullIter((_mesh_)->boundary)
444 
445 
446 /**
447  * Provides for statement to iterate over the Edges of the Mesh. see FOR_ELEMENTS
448  */
449 #define FOR_EDGES(_mesh_,__i) \
450  for( vector<Edge>::iterator __i = (_mesh_)->edges.begin(); \
451  __i !=(_mesh_)->edges.end(); \
452  ++__i)
453 
454 #define FOR_SIDES(_mesh_, it) \
455  FOR_ELEMENTS((_mesh_), ele) \
456  for(SideIter it = ele->side(0); it->el_idx() < ele->n_sides(); ++it)
457 
458 #define FOR_SIDE_NODES(i,j) for((j)=0;(j)<(i)->n_nodes;(j)++)
459 
460 
461 #define FOR_NEIGHBOURS(_mesh_, it) \
462  for( std::vector<Neighbour>::iterator it = (_mesh_)->vb_neighbours_.begin(); \
463  (it)!= (_mesh_)->vb_neighbours_.end(); ++it)
464 
465 #define FOR_NEIGH_ELEMENTS(i,j) for((j)=0;(j)<(i)->n_elements;(j)++)
466 #define FOR_NEIGH_SIDES(i,j) for((j)=0;(j)<(i)->n_sides;(j)++)
467 
468 
469 #endif
470 //-----------------------------------------------------------------------------
471 // vim: set cindent:
int n_triangles
Definition: mesh.h:258
Distribution * el_ds
Parallel distribution of elements.
Definition: mesh.h:397
Class for the mesh partitioning. This should provide:
Definition: partitioning.hh:39
vector< vector< unsigned int > > node_elements
Definition: mesh.h:280
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:88
int n_lines
Definition: mesh.h:257
Definition: mesh.h:95
Input::Record in_record_
Definition: mesh.h:379
int * get_el_4_loc() const
Definition: mesh.h:167
vector< vector< vector< unsigned int > > > side_nodes
Definition: mesh.h:270
int n_tetrahedras
Definition: mesh.h:259
const RegionDB & region_db() const
Definition: mesh.h:152
vector< Boundary > boundary_
Definition: mesh.h:225
#define DECLARE_EXCEPTION(ExcName, Format)
Macro for simple definition of exceptions.
Definition: exceptions.hh:150
int * el_4_loc
Index set assigning to local element index its global index.
Definition: mesh.h:395
int * row_4_el
Index set assigning to global element index the local index used in parallel vectors.
Definition: mesh.h:393
int n_exsides
Definition: mesh.h:254
unsigned int n_vb_neighbours() const
Definition: mesh.h:180
unsigned int n_elements() const
Definition: mesh.h:138
MPI_Comm get_comm() const
Definition: mesh.h:173
unsigned int n_boundaries() const
Definition: mesh.h:142
Accessor to the data with type Type::Record.
Definition: accessors.hh:277
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:229
std::shared_ptr< BIHTree > bih_tree_
Definition: mesh.h:375
Distribution * get_el_ds() const
Definition: mesh.h:161
vector< vector< unsigned int > > master_elements
Definition: mesh.h:246
vector< Neighbour > vb_neighbours_
Definition: mesh.h:251
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:255
unsigned int max_edge_sides(unsigned int dim) const
Definition: mesh.h:188
int * get_row_4_el() const
Definition: mesh.h:164
RegionDB region_db_
Definition: mesh.h:366
std::vector< Edge > edges
Vector of MH edges, this should not be part of the geometrical mesh.
Definition: mesh.h:232
vector< Intersection > intersections
Definition: mesh.h:240
MPI_Comm comm_
Definition: mesh.h:384
int n_insides
Definition: mesh.h:253
#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:186
unsigned int n_nodes() const
Definition: mesh.h:134
Record type proxy class.
Definition: type_record.hh:171
unsigned int n_edges() const
Definition: mesh.h:146
vector< int > bulk_elements_id_
Definition: mesh.h:355
std::shared_ptr< Partitioning > part_
Definition: mesh.h:370
NodeVector node_vector
Vector of nodes of the mesh.
Definition: mesh.h:219
ElementVector element
Vector of elements of the mesh.
Definition: mesh.h:221