GetFEM++  5.3
getfem_im_data.h
Go to the documentation of this file.
1 /* -*- c++ -*- (enables emacs c++ mode) */
2 /*===========================================================================
3 
4  Copyright (C) 2012-2017 Liang Jin Lim
5 
6  This file is a part of GetFEM++
7 
8  GetFEM++ is free software; you can redistribute it and/or modify it
9  under the terms of the GNU Lesser General Public License as published
10  by the Free Software Foundation; either version 3 of the License, or
11  (at your option) any later version along with the GCC Runtime Library
12  Exception either version 3.1 or (at your option) any later version.
13  This program is distributed in the hope that it will be useful, but
14  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16  License and GCC Runtime Library Exception for more details.
17  You should have received a copy of the GNU Lesser General Public License
18  along with this program; if not, write to the Free Software Foundation,
19  Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
20 
21  As a special exception, you may use this file as it is a part of a free
22  software library without restriction. Specifically, if other files
23  instantiate templates or use macros or inline functions from this file,
24  or you compile this file and link it with other files to produce an
25  executable, this file does not by itself cause the resulting executable
26  to be covered by the GNU Lesser General Public License. This exception
27  does not however invalidate any other reasons why the executable file
28  might be covered by the GNU Lesser General Public License.
29 
30 ===========================================================================*/
31 /**
32 @file getfem_im_data.h
33 @brief Provides indexing of integration points for mesh_im.
34 @date Feb 2014
35 @author Liang Jin Lim
36 */
37 
38 #pragma once
39 
40 #ifndef GETFEM_IM_DATA_H__
41 #define GETFEM_IM_DATA_H__
42 
43 #include <getfem/getfem_mesh_im.h>
44 
45 namespace getfem{
46  using bgeot::size_type;
47  using bgeot::scalar_type;
48 
49  /**check if a given tensor size is equivalent to a vector*/
50  bool is_equivalent_with_vector(const bgeot::multi_index &sizes, size_type vector_size);
51  /**check if a given tensor size is equivalent to a matrix*/
52  bool is_equivalent_with_matrix(const bgeot::multi_index &sizes, size_type nrows, size_type ncols);
53 
54  /** im_data provides indexing to the integration points of a mesh
55  im object. The im_data data contains a reference of mesh_im object
56  . The index can be filtered by region, and each im_data has its
57  own tensorial size.
58 
59  Filtered methods will provide filtered index on the region.
60  This class also provides reading and writing tensor( including
61  matrix, vector and scalar) from a vector data (generally a
62  fixed-size variable from the model.)
63 
64  im_data can be used to provide integration point index on convex or
65  on faces of convex, but not both. To create an im_data that represents
66  integration points on a face, the filter region provided has to contain
67  only faces.
68  */
69  class im_data : public context_dependencies, virtual public dal::static_stored_object {
70  public:
71  /**
72  * Constructor
73  * @param mim Reference mesh_im object
74  * @param tensor_size tensor dimension of each integration points
75  * @param filtered_region index not in the region will be filtered
76  * out. If filtered_region can contain only convexes or only
77  * faces or both convexes and faces.
78  */
79  im_data(const mesh_im& mim_, bgeot::multi_index tensor_size,
80  size_type filtered_region_ = size_type(-1));
81 
82  /**
83  * Constructor. The tensor size by default is a scalar value.
84  * @param mim Reference mesh_im object
85  * @param filtered_region index not in the region will be filtered
86  * out. If filtered_region can contain only convexes or only
87  * faces or both convexes and faces.
88  */
89  im_data(const mesh_im& mim_, size_type filtered_region_ = size_type(-1));
90 
91  /**set filtered region id*/
92  void set_region(size_type region);
93 
94  /**return filtered region id*/
95  inline size_type filtered_region() const {return region_;}
96 
97  /**Returns the index of an integration point with no filtering*/
99  bool use_filter = false) const;
100 
101  /**Returns the index of an integration point with filtering*/
103 
104  /**Returns the index of the first integration point with no filtering*/
106  bool use_filter = false) const;
107 
108  /**Returns the index of the first integration point with filtering*/
110 
111  /**Total numbers of index (integration points)*/
112  size_type nb_index(bool use_filter=false) const;
113 
114  /**Total numbers of filtered index (integration points)*/
116  { return nb_index(true); }
117 
118  /**Total number of points in element cv*/
119  size_type nb_points_of_element(size_type cv, bool use_filter=false) const;
120 
121  /**Number of points in element cv, on face f (or in the interior)*/
122  size_type nb_points_of_element(size_type cv, short_type f, bool use_filter=false) const;
123 
124  /**Total number of points in element cv, which lie in filtered_region()*/
126  { return nb_points_of_element(cv, true); }
127 
128  /**Number of points in element cv, on face f (or in the interior),
129  which lie in filtered_region()*/
131  { return nb_points_of_element(cv, f, true); }
132 
133  /**Number of (active) faces in element cv*/
135 
136  /**sum of tensor elements, M(3,3) will have 3*3=9 elements*/
137  size_type nb_tensor_elem() const;
138 
139  /**List of convexes*/
140  dal::bit_vector convex_index(bool use_filter=false) const;
141 
142  /**List of convex in filtered region*/
143  dal::bit_vector filtered_convex_index() const
144  { return convex_index(true); }
145 
146  /**called automatically when there is a change in dependencies*/
147  void update_from_context () const;
148 
149  /**linked mesh im*/
150  inline const mesh_im &linked_mesh_im() const { return im_; }
151 
152  /**implicit conversion to mesh im*/
153  inline operator const mesh_im &() const { return im_; }
154 
155  /**linked mesh*/
156  inline const mesh &linked_mesh () const { return im_.linked_mesh(); }
157 
158  getfem::papprox_integration approx_int_method_of_element(size_type cv) const
159  { return im_.int_method_of_element(cv)->approx_method(); }
160 
161  inline const bgeot::multi_index& tensor_size () const { return tensor_size_;}
162 
163  void set_tensor_size (const bgeot::multi_index& tensor_size);
164 
165  inline gmm::uint64_type version_number() const { context_check(); return v_num_; }
166 
167  /**Extend a vector from filtered size to full size and copy the data to correct index*/
168  template <typename VECT>
169  void extend_vector(const VECT &V1, VECT &V2) const {
170  if (V1.size() == 0 && V2.size() == 0)
171  return;
172  size_type nb_data = V1.size()/nb_filtered_index();
173  GMM_ASSERT2(V1.size() == nb_data*nb_filtered_index(), "Invalid size of vector V1");
174  GMM_ASSERT2(V2.size() == nb_data*nb_index(), "Invalid size of vector V2");
175  if (nb_filtered_index() == nb_index()) {
176  gmm::copy(V1, V2);
177  return;
178  }
179 
181  for (getfem::mr_visitor v(rg); !v.finished(); ++v) {
182  size_type nb_pts = nb_points_of_element(v.cv(), v.f());
183  size_type first_id = (v.f() == short_type(-1))
184  ? convexes[v.cv()].first_int_pt_id
185  : convexes[v.cv()].first_int_pt_onface_id[v.f()];
186  size_type first_fid = (v.f() == short_type(-1))
187  ? convexes[v.cv()].first_int_pt_fid
188  : convexes[v.cv()].first_int_pt_onface_fid[v.f()];
189  if (first_fid != size_type(-1))
190  gmm::copy(
191  gmm::sub_vector(V1, gmm::sub_interval(first_fid*nb_data, nb_pts*nb_data)),
192  gmm::sub_vector(V2, gmm::sub_interval(first_id*nb_data, nb_pts*nb_data)));
193  }
194  }
195 
196  /**Filter a vector from full size to filtered size and copy the data to correct index*/
197  template <typename VECT>
198  void reduce_vector(const VECT &V1, VECT &V2) const {
199  if (V1.size() == 0 && V2.size() == 0)
200  return;
201  size_type nb_data = V1.size()/nb_index();
202  GMM_ASSERT2(V1.size() == nb_data*nb_index(), "Invalid size of vector V1");
203  GMM_ASSERT2(V2.size() == nb_data*nb_filtered_index(),
204  "Invalid size of vector V2");
205  if (nb_filtered_index() == nb_index()) {
206  gmm::copy(V1, V2);
207  return;
208  }
209 
211  for (getfem::mr_visitor v(rg); !v.finished(); ++v) {
212  size_type nb_pts = nb_points_of_element(v.cv(), v.f());
213  size_type first_id = (v.f() == short_type(-1))
214  ? convexes[v.cv()].first_int_pt_id
215  : convexes[v.cv()].first_int_pt_onface_id[v.f()];
216  size_type first_fid = (v.f() == short_type(-1))
217  ? convexes[v.cv()].first_int_pt_fid
218  : convexes[v.cv()].first_int_pt_onface_fid[v.f()];
219  if (first_fid != size_type(-1))
220  gmm::copy(
221  gmm::sub_vector(V1, gmm::sub_interval(first_id*nb_data, nb_pts*nb_data)),
222  gmm::sub_vector(V2, gmm::sub_interval(first_fid*nb_data, nb_pts*nb_data)));
223  }
224  }
225 
226  /**get a scalar value of an integration point
227  from a raw vector data, described by the tensor size.*/
228  template <typename VECT>
229  typename VECT::value_type get_value(const VECT &V1, size_type cv,
230  size_type i, bool use_filter = true) const {
231  GMM_ASSERT2(nb_tensor_elem_*nb_index(use_filter) == V1.size(),
232  "Invalid tensorial size for vector V1");
233  GMM_ASSERT2(nb_tensor_elem_ == 1, "im_data is not of scalar type");
234  size_type ptid = index_of_point(cv,i,use_filter);
235  GMM_ASSERT2(ptid != size_type(-1), "Point index of gauss point not found");
236  return V1[ptid];
237  }
238 
239  /**get a vector of an integration point
240  from a raw vector data, described by the tensor size.*/
241  template <typename VECT1, typename VECT2>
242  void get_vector(const VECT1 &V1, size_type cv, size_type i,
243  VECT2& V2, bool use_filter = true) const {
244  if (V1.size() == 0 && V2.size() == 0)
245  return;
246  GMM_ASSERT2(nb_tensor_elem_*nb_index(use_filter) == V1.size(),
247  "Invalid tensorial size for vector V1");
248  GMM_ASSERT2(is_equivalent_with_vector(tensor_size_, V2.size()),
249  "V2 is incompatible with im_data tensor size");
250  size_type ptid = index_of_point(cv,i,use_filter);
251  GMM_ASSERT2(ptid != size_type(-1), "Point index of gauss point not found");
252  gmm::copy(gmm::sub_vector(V1, gmm::sub_interval(ptid*nb_tensor_elem_,
253  nb_tensor_elem_)),
254  V2);
255  }
256 
257  /**get a matrix of an integration point
258  from a raw vector data, described by the tensor size.*/
259  template <typename VECT, typename MAT>
260  void get_matrix(const VECT &V1, size_type cv, size_type i,
261  MAT& M, bool use_filter = true) const {
262  if (V1.size() == 0 && M.size() == 0)
263  return;
264  GMM_ASSERT2(nb_tensor_elem_*nb_index(use_filter) == V1.size(),
265  "Invalid tensorial size for vector V1");
266  GMM_ASSERT2(is_equivalent_with_matrix(tensor_size_, M.nrows(), M.ncols()),
267  "M is incompatible with im_data tensor size");
268  size_type ptid = index_of_point(cv,i,use_filter);
269  GMM_ASSERT2(ptid != size_type(-1), "Point index of gauss point not found");
270  gmm::copy(gmm::sub_vector(V1, gmm::sub_interval(ptid*nb_tensor_elem_,
271  nb_tensor_elem_)),
272  M.as_vector());
273  }
274 
275  /**get a tensor of an integration point
276  from a raw vector data, described by the tensor size.*/
277  template <typename VECT, typename TENSOR>
278  void get_tensor(const VECT &V1, size_type cv, size_type i,
279  TENSOR& T, bool use_filter = true) const {
280  if (V1.size() == 0 && T.size() == 0)
281  return;
282  GMM_ASSERT2(nb_tensor_elem_*nb_index(use_filter) == V1.size(),
283  "Invalid tensorial size for vector V1");
284  GMM_ASSERT2(tensor_size_ == T.sizes(),
285  "T is incompatible with im_data tensor size");
286  size_type ptid = index_of_point(cv,i,use_filter);
287  GMM_ASSERT2(ptid != size_type(-1), "Point index of gauss point not found");
288  gmm::copy(gmm::sub_vector(V1, gmm::sub_interval(ptid*nb_tensor_elem_,
289  nb_tensor_elem_)),
290  T.as_vector());
291  }
292 
293  /**set a value of an integration point
294  from a raw vector data, described by the tensor size.*/
295  template <typename VECT>
296  typename VECT::value_type &set_value(VECT &V1, size_type cv, size_type i,
297  bool use_filter = true) const {
298  GMM_ASSERT2(nb_tensor_elem_*nb_index(use_filter) == V1.size(),
299  "Invalid tensorial size for vector V1");
300  GMM_ASSERT2(nb_tensor_elem_ == 1, "im_data is not of scalar type");
301  size_type ptid = index_of_point(cv,i,use_filter);
302  GMM_ASSERT2(ptid != size_type(-1), "Point index of gauss point not found");
303  return V1[ptid];
304  }
305 
306  /**set a vector of an integration point
307  from a raw vector data, described by the tensor size.*/
308  template <typename VECT1, typename VECT2>
309  void set_vector(VECT1 &V1, size_type cv, size_type i,
310  const VECT2& V2, bool use_filter = true) const {
311  if (V1.size() == 0 && V2.size() == 0)
312  return;
313  GMM_ASSERT2(nb_tensor_elem_*nb_index(use_filter) == V1.size(),
314  "Invalid tensorial size for vector V1");
315  GMM_ASSERT2(is_equivalent_with_vector(tensor_size_, V2.size()),
316  "V2 is incompatible with im_data tensor size");
317  size_type ptid = index_of_point(cv,i,use_filter);
318  GMM_ASSERT2(ptid != size_type(-1), "Point index of gauss point not found");
319  gmm::copy(V2,
320  gmm::sub_vector(V1, gmm::sub_interval(ptid*nb_tensor_elem_,
321  nb_tensor_elem_)));
322  }
323 
324  /**set a matrix of an integration point
325  from a raw vector data, described by the tensor size.*/
326  template <typename VECT, typename MAT>
327  void set_matrix(VECT &V1, size_type cv, size_type i,
328  const MAT& M, bool use_filter = true) const {
329  if (V1.size() == 0 && M.size() == 0)
330  return;
331  GMM_ASSERT2(nb_tensor_elem_*nb_index(use_filter) == V1.size(),
332  "Invalid tensorial size for vector V1");
333  GMM_ASSERT2(is_equivalent_with_matrix(tensor_size_, M.nrows(), M.ncols()),
334  "M is incompatible with im_data tensor size");
335  size_type ptid = index_of_point(cv,i,use_filter);
336  GMM_ASSERT2(ptid != size_type(-1), "Point index of gauss point not found");
337  gmm::copy(M.as_vector(),
338  gmm::sub_vector(V1, gmm::sub_interval(ptid*nb_tensor_elem_,
339  nb_tensor_elem_)));
340  }
341 
342  /**set a tensor of an integration point
343  from a raw vector data, described by the tensor size.*/
344  template <typename VECT, typename TENSOR>
345  void set_tensor(VECT &V1, size_type cv, size_type i,
346  const TENSOR& T, bool use_filter = true) const {
347  if (V1.size() == 0 && T.size() == 0)
348  return;
349  GMM_ASSERT2(nb_tensor_elem_*nb_index(use_filter) == V1.size(),
350  "Invalid tensorial size for vector V1");
351  GMM_ASSERT2(tensor_size_ == T.sizes(),
352  "T is incompatible with im_data tensor size");
353  size_type ptid = index_of_point(cv,i,use_filter);
354  GMM_ASSERT2(ptid != size_type(-1), "Point index of gauss point not found");
355  gmm::copy(T.as_vector(),
356  gmm::sub_vector(V1, gmm::sub_interval(ptid*nb_tensor_elem_,
357  nb_tensor_elem_)));
358  }
359 
360 
361  template <typename VECT1, typename VECT2>
362  void set_vector(VECT1 &V1, size_type ptid, const VECT2& V2) const {
363  GMM_ASSERT2(V1.size() != 0, "V1 of zero size");
364  GMM_ASSERT2(V2.size() != 0, "V2 of zero size");
365  GMM_ASSERT2(is_equivalent_with_vector(tensor_size_, V2.size()),
366  "V2 is incompatible with im_data tensor size");
367  gmm::copy(V2,
368  gmm::sub_vector(V1, gmm::sub_interval(ptid*nb_tensor_elem_,
369  nb_tensor_elem_)));
370  }
371 
372  template <typename VECT1, typename TENSOR>
373  void set_tensor(VECT1 &V1, size_type ptid, const TENSOR& T) const {
374  GMM_ASSERT2(V1.size() != 0, "V1 of zero size");
375  GMM_ASSERT2(T.size() != 0, "V2 of zero size");
376  GMM_ASSERT2(tensor_size_ == T.sizes(),
377  "T is incompatible with im_data tensor size");
378  gmm::copy(T.as_vector(),
379  gmm::sub_vector(V1, gmm::sub_interval(ptid*nb_tensor_elem_,
380  nb_tensor_elem_)));
381  }
382 
383  private:
384  const mesh_im &im_;
385 
386  size_type region_;
387 
388  mutable size_type nb_int_pts_intern;
389  mutable size_type nb_int_pts_onfaces;
390  mutable size_type nb_filtered_int_pts_intern;
391  mutable size_type nb_filtered_int_pts_onfaces;
392 
393  struct convex_data {
394  size_type first_int_pt_id; // index
395  size_type first_int_pt_fid; // filtered index
396  size_type nb_int_pts; // number of internal integration points
397  std::vector<size_type> first_int_pt_onface_id;
398  std::vector<size_type> first_int_pt_onface_fid;
399  std::vector<size_type> nb_int_pts_onface;
400 
401  convex_data()
402  : first_int_pt_id(-1), first_int_pt_fid(-1), nb_int_pts(0),
403  first_int_pt_onface_id(0), first_int_pt_onface_fid(0), nb_int_pts_onface(0)
404  {}
405  };
406 
407  mutable std::vector<convex_data> convexes;
408 
409  mutable gmm::uint64_type v_num_;
410 
411  bgeot::multi_index tensor_size_;
412  size_type nb_tensor_elem_;
413  lock_factory locks_;
414  };
415 }
416 #endif /* GETFEM_IM_DATA_H__ */
void update_from_context() const
called automatically when there is a change in dependencies
size_type index_of_point(size_type cv, size_type i, bool use_filter=false) const
Returns the index of an integration point with no filtering.
virtual pintegration_method int_method_of_element(size_type cv) const
return the integration method associated with an element (in no integration is associated, the function will crash! use the convex_index() of the mesh_im to check that a fem is associated to a given convex)
structure used to hold a set of convexes and/or convex faces.
void get_matrix(const VECT &V1, size_type cv, size_type i, MAT &M, bool use_filter=true) const
get a matrix of an integration point from a raw vector data, described by the tensor size...
void set_matrix(VECT &V1, size_type cv, size_type i, const MAT &M, bool use_filter=true) const
set a matrix of an integration point from a raw vector data, described by the tensor size...
base class for static stored objects
bool is_equivalent_with_vector(const bgeot::multi_index &sizes, size_type vector_size)
check if a given tensor size is equivalent to a vector
bool is_equivalent_with_matrix(const bgeot::multi_index &sizes, size_type nrows, size_type ncols)
check if a given tensor size is equivalent to a matrix
void extend_vector(const VECT &V1, VECT &V2) const
Extend a vector from filtered size to full size and copy the data to correct index.
void set_region(size_type region)
set filtered region id
short_type nb_faces_of_element(size_type cv) const
Number of (active) faces in element cv.
VECT::value_type get_value(const VECT &V1, size_type cv, size_type i, bool use_filter=true) const
get a scalar value of an integration point from a raw vector data, described by the tensor size...
void set_tensor(VECT &V1, size_type cv, size_type i, const TENSOR &T, bool use_filter=true) const
set a tensor of an integration point from a raw vector data, described by the tensor size...
Define the getfem::mesh_im class (integration of getfem::mesh_fem).
Describe a mesh (collection of convexes (elements) and points).
Definition: getfem_mesh.h:95
const mesh_im & linked_mesh_im() const
linked mesh im
Describe an integration method linked to a mesh.
void get_vector(const VECT1 &V1, size_type cv, size_type i, VECT2 &V2, bool use_filter=true) const
get a vector of an integration point from a raw vector data, described by the tensor size...
const mesh & linked_mesh() const
linked mesh
size_type nb_index(bool use_filter=false) const
Total numbers of index (integration points)
VECT::value_type & set_value(VECT &V1, size_type cv, size_type i, bool use_filter=true) const
set a value of an integration point from a raw vector data, described by the tensor size...
size_t size_type
used as the common size type in the library
Definition: bgeot_poly.h:49
void get_tensor(const VECT &V1, size_type cv, size_type i, TENSOR &T, bool use_filter=true) const
get a tensor of an integration point from a raw vector data, described by the tensor size...
"iterator" class for regions.
Deal with interdependencies of objects.
GEneric Tool for Finite Element Methods.
void set_vector(VECT1 &V1, size_type cv, size_type i, const VECT2 &V2, bool use_filter=true) const
set a vector of an integration point from a raw vector data, described by the tensor size...
gmm::uint16_type short_type
used as the common short type integer in the library
Definition: bgeot_config.h:79
size_type nb_filtered_index() const
Total numbers of filtered index (integration points)
size_type nb_filtered_points_of_element(size_type cv, short_type f) const
Number of points in element cv, on face f (or in the interior), which lie in filtered_region() ...
size_type filtered_index_of_point(size_type cv, size_type i) const
Returns the index of an integration point with filtering.
size_type filtered_index_of_first_point(size_type cv, short_type f=short_type(-1)) const
Returns the index of the first integration point with filtering.
size_type filtered_region() const
return filtered region id
const mesh & linked_mesh() const
Give a reference to the linked mesh of type mesh.
bool context_check() const
return true if update_from_context was called
void reduce_vector(const VECT &V1, VECT &V2) const
Filter a vector from full size to filtered size and copy the data to correct index.
size_type nb_filtered_points_of_element(size_type cv) const
Total number of points in element cv, which lie in filtered_region()
im_data(const mesh_im &mim_, bgeot::multi_index tensor_size, size_type filtered_region_=size_type(-1))
Constructor.
dal::bit_vector convex_index(bool use_filter=false) const
List of convexes.
im_data provides indexing to the integration points of a mesh im object.
const mesh_region region(size_type id) const
Return the region of index &#39;id&#39;.
Definition: getfem_mesh.h:414
dal::bit_vector filtered_convex_index() const
List of convex in filtered region.
size_type nb_tensor_elem() const
sum of tensor elements, M(3,3) will have 3*3=9 elements
size_type index_of_first_point(size_type cv, short_type f=short_type(-1), bool use_filter=false) const
Returns the index of the first integration point with no filtering.
size_type nb_points_of_element(size_type cv, bool use_filter=false) const
Total number of points in element cv.