Flow123d
mesh.h
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2007 Technical University of Liberec. All rights reserved.
4  *
5  * Please make a following refer to Flow123d on your project site if you use the program for any purpose,
6  * especially for academic research:
7  * Flow123d, Research Centre: Advanced Remedial Technologies, Technical University of Liberec, Czech Republic
8  *
9  * This program is free software; you can redistribute it and/or modify it under the terms
10  * of the GNU General Public License version 3 as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14  * See the GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along with this program; if not,
17  * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 021110-1307, USA.
18  *
19  *
20  * $Id$
21  * $Revision$
22  * $LastChangedBy$
23  * $LastChangedDate$
24  *
25  * @file
26  * @brief ???
27  *
28  */
29 
30 #ifndef MAKE_MESH_H
31 #define MAKE_MESH_H
32 
33 #include <vector>
34 #include <mpi.h>
35 
36 #include "mesh/mesh_types.hh"
37 
38 #include "mesh/nodes.hh"
39 #include "mesh/elements.h"
40 #include "mesh/sides.h"
41 #include "mesh/edges.h"
42 #include "mesh/neighbours.h"
43 #include "mesh/boundaries.h"
44 #include "mesh/intersection.hh"
45 
46 #include "input/input_type.hh"
47 #include "input/accessors.hh"
48 #include "boost/shared_ptr.hpp"
49 
50 // Forward declarations
51 template <int spacedim>
52 class ElementAccessor;
53 class GmshMeshReader;
54 class Partitioning;
55 
56 
57 #define ELM 0
58 #define BC 1
59 #define NODE 2
60 
61 /**
62  * This parameter limits volume of elements from below.
63  */
64 #define MESH_CRITICAL_VOLUME 1.0E-12
65 
66 /**
67  * Provides for statement to iterate over the Nodes of the Mesh.
68  * The parameter is FullIter local variable of the cycle, so it need not be declared before.
69  * Macro assume that variable Mesh *mesh; is declared and points to a valid Mesh structure.
70  */
71 #define FOR_NODES(_mesh_, i) \
72  for( NodeFullIter i( (_mesh_)->node_vector.begin() ); \
73  i != (_mesh_)->node_vector.end(); \
74  ++i)
75 
76 /**
77  * Macro for conversion form Iter to FullIter for nodes.
78  */
79 #define NODE_FULL_ITER(_mesh_,i) \
80  (_mesh_)->node_vector.full_iter(i)
81 
82 /**
83  * Macro to get "NULL" ElementFullIter.
84  */
85 #define NODE_FULL_ITER_NULL(_mesh_) \
86  NodeFullIter((_mesh_)->node_vector)
87 
88 /**
89  * Macro for conversion form Iter to FullIter for elements.
90  */
91 #define ELEM_FULL_ITER(_mesh_,i) \
92  (_mesh_)->element.full_iter(i)
93 
94 
95 #define FOR_NODE_ELEMENTS(i,j) for((j)=0;(j)<(i)->n_elements();(j)++)
96 #define FOR_NODE_SIDES(i,j) for((j)=0;(j)<(i)->n_sides;(j)++)
97 
98 
100 public:
102 };
103 
104 //=============================================================================
105 // STRUCTURE OF THE MESH
106 //=============================================================================
107 
108 class Mesh {
109 public:
110  static const unsigned int undef_idx=-1;
112 
113 
114 
115  /** Labels for coordinate indexes in arma::vec3 representing vectors and points.*/
116  enum {x_coord=0, y_coord=1, z_coord=2};
117 
118  /**
119  * Constructor with input record given by string. Aimed for testing purpose.
120  * Do not process input record. That is done in init_from_input.
121  */
122  Mesh(const std::string &input_str="{mesh_file=\"\"}", MPI_Comm com = MPI_COMM_WORLD);
123  /**
124  * Constructor from an input record.
125  * Do not process input record. That is done in init_from_input.
126  */
127  Mesh(Input::Record in_record, MPI_Comm com = MPI_COMM_WORLD);
128  /**
129  * Common part of both previous constructors and way how to reinitialize a mesh from the given input record.
130  */
131  void reinit(Input::Record in_record);
132 
133  inline unsigned int n_nodes() const {
134  return node_vector.size();
135  }
136 
137  inline unsigned int n_elements() const {
138  return element.size();
139  }
140 
141  inline unsigned int n_boundaries() const {
142  return boundary_.size();
143  }
144 
145  inline unsigned int n_edges() const {
146  return edges.size();
147  }
148  inline const RegionDB &region_db() const {
149  return region_db_;
150  }
151 
152  /**
153  * Returns pointer to partitioning object. Partitioning is created during setup_topology.
154  */
156 
157  /**
158  * Returns MPI communicator of the mesh.
159  */
160  inline MPI_Comm get_comm() const { return comm_; }
161 
162 
163  void make_intersec_elements();
164 
165  unsigned int n_sides();
166 
167  inline unsigned int n_vb_neighbours() const {
168  return vb_neighbours_.size();
169  }
170 
171  /**
172  * Returns maximal number of sides of one edge, which connects elements of dimension @p dim.
173  * @param dim Dimension of elements sharing the edge.
174  */
175  unsigned int max_edge_sides(unsigned int dim) const { return max_edge_sides_[dim-1]; }
176 
177  /**
178  *
179  */
180  void read_gmsh_from_stream(istream &in);
181  /**
182  * Reads input record, creates regions, read the mesh, setup topology. creates region sets.
183  */
184  void init_from_input();
185 
186 
187  /**
188  * Returns vector of ID numbers of elements, either bulk or bc elemnts.
189  */
190  vector<int> const & elements_id_maps( bool boundary_domain) const;
191 
192 
193  ElementAccessor<3> element_accessor(unsigned int idx, bool boundary=false);
194 
195  /// Vector of nodes of the mesh.
197  /// Vector of elements of the mesh.
199 
200  /// Vector of boundary sides where is prescribed boundary condition.
201  /// TODO: apply all boundary conditions in the main assembling cycle over elements and remove this Vector.
203  /// vector of boundary elements - should replace 'boundary'
204  /// 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
205  /// the avoid usage of ElementVector etc.
207 
208  /// Vector of MH edges, this should not be part of the geometrical mesh
210 
211  //flow::VectorId<int> bcd_group_id; // gives a index of group for an id
212 
213  /**
214  * Vector of individual intersections of two elements.
215  * This is enough for local mortar.
216  */
218 
219  /**
220  * For every element El we have vector of indices into @var intersections array for every intersection in which El is master element.
221  * This is necessary for true mortar.
222  */
224 
225  /**
226  * Vector of compatible neighbourings.
227  */
229  //int n_materials; // # of materials
230 
231  int n_insides; // # of internal sides
232  int n_exsides; // # of external sides
233  int n_sides_; // total number of sides (should be easy to count when we have separated dimensions
234 
235  int n_lines; // Number of line elements
236  int n_triangles; // Number of triangle elements
237  int n_tetrahedras; // Number of tetrahedra elements
238 
239  // Temporary solution for numbering of nodes on sides.
240  // The data are defined in RefElement<dim>::side_nodes,
241  // Mesh::side_nodes can be removed as soon as Element
242  // is templated by dimension.
243  //
244  // for every side dimension D = 0 .. 2
245  // for every element side 0 .. D+1
246  // for every side node 0 .. D
247  // index into element node array
249 
250 
251 
252 
253 protected:
254 
255  /**
256  * This replaces read_neighbours() in order to avoid using NGH preprocessor.
257  *
258  * TODO:
259  * - Avoid maps:
260  *
261  * 4) replace EdgeVector by std::vector<Edge> (need not to know the size)
262  *
263  * 5) need not to have temporary array for Edges, only postpone setting pointers in elements and set them
264  * after edges are found; we can temporary save Edge index instead of pointer in Neigbours and elements
265  *
266  * 6) Try replace Edge * by indexes in Neigbours and elements (anyway we have mesh pointer in elements so it is accessible also from Neigbours)
267  *
268  */
270 
271  /**
272  * On edges sharing sides of many elements it may happen that each side has its nodes ordered in a different way.
273  * This method finds the permutation for each side so as to obtain the ordering of side 0.
274  */
275  void make_edge_permutations();
276  /**
277  * Create element lists for nodes in Mesh::nodes_elements.
278  */
280  /**
281  * Find intersection of element lists given by Mesh::node_elements for elements givne by @p nodes_list parameter.
282  * The result is placed into vector @p intersection_element_list. If the @p node_list is empty, and empty intersection is
283  * returned.
284  */
285  void intersect_element_lists(vector<unsigned int> const &nodes_list, vector<unsigned int> &intersection_element_list);
286  /**
287  * Remove elements with dimension not equal to @p dim from @p element_list. Index of the first element of dimension @p dim-1,
288  * 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,
289  * if more elements are found we report an user input error.
290  */
291  bool find_lower_dim_element(ElementVector&elements, vector<unsigned int> &element_list, unsigned int dim, unsigned int &element_idx);
292 
293  /**
294  * Returns true if side @p si has same nodes as in the list @p side_nodes.
295  */
297 
298  /**
299  * Initialize all mesh structures from raw information about nodes and elements (including boundary elements).
300  * Namely: create remaining boundary elements and Boundary objects, find edges and compatible neighborings.
301  */
302  void setup_topology();
303 
304 
305  void element_to_neigh_vb();
307 
308  void count_element_types();
309  void count_side_types();
310 
311  unsigned int n_bb_neigh, n_vb_neigh;
312 
313  /// Vector of both bulk and boundary IDs. Bulk elements come first, then boundary elements, but only the portion that appears
314  /// in input mesh file and has ID assigned.
315  ///
316  /// 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)
318  /// Number of elements read from input.
319  unsigned int n_all_input_elements_;
320 
321  // For each node the vector contains a list of elements that use this node
323 
324  /// Maximal number of sides per one edge in the actual mesh (set in make_neighbours_and_edges()).
325  unsigned int max_edge_sides_[3];
326 
327  /**
328  * Database of regions (both bulk and boundary) of the mesh. Regions are logical parts of the
329  * domain that allows setting of different data and boundary conditions on them.
330  */
332  /**
333  * Mesh partitioning. Created in setup_topology.
334  */
335  boost::shared_ptr<Partitioning> part_;
336  /**
337  * Accessor to the input record for the mesh.
338  */
340 
341  /**
342  * MPI communicator used for partitioning and ...
343  */
345 
346  friend class GmshMeshReader;
347 };
348 
349 
350 #include "mesh/side_impl.hh"
351 #include "mesh/element_impls.hh"
352 #include "mesh/neighbours_impl.hh"
353 
354 /**
355  * Provides for statement to iterate over the Elements of the Mesh.
356  * The parameter is FullIter local variable of the cycle, so it need not be declared before.
357  * Macro assume that variable Mesh *mesh; is declared and points to a valid Mesh structure.
358  */
359 #define FOR_ELEMENTS(_mesh_,__i) \
360  for( ElementFullIter __i( (_mesh_)->element.begin() ); \
361  __i != (_mesh_)->element.end(); \
362  ++__i)
363 
364 /**
365  * Macro for conversion form Iter to FullIter for elements.
366  */
367 #define ELEMENT_FULL_ITER(_mesh_,i) \
368  (_mesh_)->element.full_iter(i)
369 
370 /**
371  * Macro to get "NULL" ElementFullIter.
372  */
373 #define ELEMENT_FULL_ITER_NULL(_mesh_) \
374  ElementFullIter((_mesh_)->element)
375 
376 
377 #define FOR_BOUNDARIES(_mesh_,i) \
378 for( std::vector<Boundary>::iterator i= (_mesh_)->boundary_.begin(); \
379  i != (_mesh_)->boundary_.end(); \
380  ++i)
381 
382 /**
383  * Macro for conversion form Iter to FullIter for boundaries.
384  */
385 #define BOUNDARY_FULL_ITER(_mesh_,i) \
386  (_mesh_)->boundary.full_iter(i)
387 
388 /**
389  * Macro to get "NULL" BoundaryFullIter.
390  */
391 #define BOUNDARY_NULL(_mesh_) \
392  BoundaryFullIter((_mesh_)->boundary)
393 
394 
395 /**
396  * Provides for statement to iterate over the Edges of the Mesh. see FOR_ELEMENTS
397  */
398 #define FOR_EDGES(_mesh_,__i) \
399  for( vector<Edge>::iterator __i = (_mesh_)->edges.begin(); \
400  __i !=(_mesh_)->edges.end(); \
401  ++__i)
402 
403 #define FOR_SIDES(_mesh_, it) \
404  FOR_ELEMENTS((_mesh_), ele) \
405  for(SideIter it = ele->side(0); it->el_idx() < ele->n_sides(); ++it)
406 
407 #define FOR_SIDE_NODES(i,j) for((j)=0;(j)<(i)->n_nodes;(j)++)
408 
409 
410 #define FOR_NEIGHBOURS(_mesh_, it) \
411  for( std::vector<Neighbour>::iterator it = (_mesh_)->vb_neighbours_.begin(); \
412  (it)!= (_mesh_)->vb_neighbours_.end(); ++it)
413 
414 #define FOR_NEIGH_ELEMENTS(i,j) for((j)=0;(j)<(i)->n_elements;(j)++)
415 #define FOR_NEIGH_SIDES(i,j) for((j)=0;(j)<(i)->n_sides;(j)++)
416 
417 //int *max_entry();
418 
419 
420 #endif
421 //-----------------------------------------------------------------------------
422 // vim: set cindent: