GetFEM  5.4.3
getfem_im_data.h
Go to the documentation of this file.
1 /* -*- c++ -*- (enables emacs c++ mode) */
2 /*===========================================================================
3 
4  Copyright (C) 2012-2020 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  * @param Actual_tensor_size the actual size of the tensor the data represents.
79  Used for example, for a Voigt annotated data.
80  */
81  im_data(const mesh_im& mim_, bgeot::multi_index tensor_size,
82  size_type filtered_region_ = size_type(-1),
83  bgeot::multi_index actual_tensor_size = {});
84 
85  /**
86  * Constructor. The tensor size by default is a scalar value.
87  * @param mim Reference mesh_im object
88  * @param filtered_region index not in the region will be filtered
89  * out. If filtered_region can contain only convexes or only
90  * faces or both convexes and faces.
91  */
92  im_data(const mesh_im& mim_, size_type filtered_region_ = size_type(-1));
93 
94  /**set filtered region id*/
95  void set_region(size_type region);
96 
97  /**return filtered region id*/
98  inline size_type filtered_region() const {return region_;}
99 
100  /**Returns the index of an integration point with no filtering*/
102  bool use_filter = false) const;
103 
104  /**Returns the index of an integration point with filtering*/
106 
107  /**Returns the index of the first integration point with no filtering*/
109  bool use_filter = false) const;
110 
111  /**Returns the index of the first integration point with filtering*/
113 
114  /**Total numbers of index (integration points)*/
115  size_type nb_index(bool use_filter=false) const;
116 
117  /**Total numbers of filtered index (integration points)*/
119  { return nb_index(true); }
120 
121  /**Total number of points in element cv*/
122  size_type nb_points_of_element(size_type cv, bool use_filter=false) const;
123 
124  /**Number of points in element cv, on face f (or in the interior)*/
125  size_type nb_points_of_element(size_type cv, short_type f, bool use_filter=false) const;
126 
127  /**Total number of points in element cv, which lie in filtered_region()*/
129  { return nb_points_of_element(cv, true); }
130 
131  /**Number of points in element cv, on face f (or in the interior),
132  which lie in filtered_region()*/
134  { return nb_points_of_element(cv, f, true); }
135 
136  /**Number of (active) faces in element cv*/
138 
139  /**sum of tensor elements, M(3,3) will have 3*3=9 elements*/
140  size_type nb_tensor_elem() const;
141 
142  /**List of convexes*/
143  dal::bit_vector convex_index(bool use_filter=false) const;
144 
145  /**List of convex in filtered region*/
146  dal::bit_vector filtered_convex_index() const
147  { return convex_index(true); }
148 
149  /**called automatically when there is a change in dependencies*/
150  void update_from_context () const;
151 
152  /**linked mesh im*/
153  inline const mesh_im &linked_mesh_im() const { return im_; }
154 
155  /**implicit conversion to mesh im*/
156  inline operator const mesh_im &() const { return im_; }
157 
158  /**linked mesh*/
159  inline const mesh &linked_mesh () const { return im_.linked_mesh(); }
160 
161  getfem::papprox_integration approx_int_method_of_element(size_type cv) const
162  { return im_.int_method_of_element(cv)->approx_method(); }
163 
164  inline const bgeot::multi_index& tensor_size() const { return tensor_size_; }
165 
166  void set_tensor_size(const bgeot::multi_index& tensor_size);
167 
168  inline const bgeot::multi_index& actual_tensor_size() const { return actual_tensor_size_; }
169 
170  void set_actual_tensor_size(const bgeot::multi_index &tensor_size);
171 
172  inline gmm::uint64_type version_number() const { context_check(); return v_num_; }
173 
174  /**Extend a vector from filtered size to full size and copy the data to correct index*/
175  template <typename VECT>
176  void extend_vector(const VECT &V1, VECT &V2) const {
177  if (V1.size() == 0 && V2.size() == 0)
178  return;
179  size_type nb_data = V1.size()/nb_filtered_index();
180  GMM_ASSERT2(V1.size() == nb_data*nb_filtered_index(), "Invalid size of vector V1");
181  GMM_ASSERT2(V2.size() == nb_data*nb_index(), "Invalid size of vector V2");
182  if (nb_filtered_index() == nb_index()) {
183  gmm::copy(V1, V2);
184  return;
185  }
186 
188  for (getfem::mr_visitor v(rg); !v.finished(); ++v) {
189  size_type nb_pts = nb_points_of_element(v.cv(), v.f());
190  size_type first_id = (v.f() == short_type(-1))
191  ? convexes[v.cv()].first_int_pt_id
192  : convexes[v.cv()].first_int_pt_onface_id[v.f()];
193  size_type first_fid = (v.f() == short_type(-1))
194  ? convexes[v.cv()].first_int_pt_fid
195  : convexes[v.cv()].first_int_pt_onface_fid[v.f()];
196  if (first_fid != size_type(-1))
197  gmm::copy(
198  gmm::sub_vector(V1, gmm::sub_interval(first_fid*nb_data, nb_pts*nb_data)),
199  gmm::sub_vector(V2, gmm::sub_interval(first_id*nb_data, nb_pts*nb_data)));
200  }
201  }
202 
203  /**Filter a vector from full size to filtered size and copy the data to correct index*/
204  template <typename VECT>
205  void reduce_vector(const VECT &V1, VECT &V2) const {
206  if (V1.size() == 0 && V2.size() == 0)
207  return;
208  size_type nb_data = V1.size()/nb_index();
209  GMM_ASSERT2(V1.size() == nb_data*nb_index(), "Invalid size of vector V1");
210  GMM_ASSERT2(V2.size() == nb_data*nb_filtered_index(),
211  "Invalid size of vector V2");
212  if (nb_filtered_index() == nb_index()) {
213  gmm::copy(V1, V2);
214  return;
215  }
216 
218  for (getfem::mr_visitor v(rg); !v.finished(); ++v) {
219  size_type nb_pts = nb_points_of_element(v.cv(), v.f());
220  size_type first_id = (v.f() == short_type(-1))
221  ? convexes[v.cv()].first_int_pt_id
222  : convexes[v.cv()].first_int_pt_onface_id[v.f()];
223  size_type first_fid = (v.f() == short_type(-1))
224  ? convexes[v.cv()].first_int_pt_fid
225  : convexes[v.cv()].first_int_pt_onface_fid[v.f()];
226  if (first_fid != size_type(-1))
227  gmm::copy(
228  gmm::sub_vector(V1, gmm::sub_interval(first_id*nb_data, nb_pts*nb_data)),
229  gmm::sub_vector(V2, gmm::sub_interval(first_fid*nb_data, nb_pts*nb_data)));
230  }
231  }
232 
233  /**get a scalar value of an integration point
234  from a raw vector data, described by the tensor size.*/
235  template <typename VECT>
236  typename VECT::value_type get_value(const VECT &V1, size_type cv,
237  size_type i, bool use_filter = true) const {
238  GMM_ASSERT2(nb_tensor_elem_*nb_index(use_filter) == V1.size(),
239  "Invalid tensorial size for vector V1");
240  GMM_ASSERT2(nb_tensor_elem_ == 1, "im_data is not of scalar type");
241  size_type ptid = index_of_point(cv,i,use_filter);
242  GMM_ASSERT2(ptid != size_type(-1), "Point index of gauss point not found");
243  return V1[ptid];
244  }
245 
246  /**get a vector of an integration point
247  from a raw vector data, described by the tensor size.*/
248  template <typename VECT1, typename VECT2>
249  void get_vector(const VECT1 &V1, size_type cv, size_type i,
250  VECT2& V2, bool use_filter = true) const {
251  if (V1.size() == 0 && V2.size() == 0)
252  return;
253  GMM_ASSERT2(nb_tensor_elem_*nb_index(use_filter) == V1.size(),
254  "Invalid tensorial size for vector V1");
255  GMM_ASSERT2(is_equivalent_with_vector(tensor_size_, V2.size()),
256  "V2 is incompatible with im_data tensor size");
257  size_type ptid = index_of_point(cv,i,use_filter);
258  GMM_ASSERT2(ptid != size_type(-1), "Point index of gauss point not found");
259  gmm::copy(gmm::sub_vector(V1, gmm::sub_interval(ptid*nb_tensor_elem_,
260  nb_tensor_elem_)),
261  V2);
262  }
263 
264  /**get a matrix of an integration point
265  from a raw vector data, described by the tensor size.*/
266  template <typename VECT, typename MAT>
267  void get_matrix(const VECT &V1, size_type cv, size_type i,
268  MAT& M, bool use_filter = true) const {
269  if (V1.size() == 0 && M.size() == 0)
270  return;
271  GMM_ASSERT2(nb_tensor_elem_*nb_index(use_filter) == V1.size(),
272  "Invalid tensorial size for vector V1");
273  GMM_ASSERT2(is_equivalent_with_matrix(tensor_size_, M.nrows(), M.ncols()),
274  "M is incompatible with im_data tensor size");
275  size_type ptid = index_of_point(cv,i,use_filter);
276  GMM_ASSERT2(ptid != size_type(-1), "Point index of gauss point not found");
277  gmm::copy(gmm::sub_vector(V1, gmm::sub_interval(ptid*nb_tensor_elem_,
278  nb_tensor_elem_)),
279  M.as_vector());
280  }
281 
282  /**get a tensor of an integration point
283  from a raw vector data, described by the tensor size.*/
284  template <typename VECT, typename TENSOR>
285  void get_tensor(const VECT &V1, size_type cv, size_type i,
286  TENSOR& T, bool use_filter = true) const {
287  if (V1.size() == 0 && T.size() == 0)
288  return;
289  GMM_ASSERT2(nb_tensor_elem_*nb_index(use_filter) == V1.size(),
290  "Invalid tensorial size for vector V1");
291  GMM_ASSERT2(tensor_size_ == T.sizes(),
292  "T is incompatible with im_data tensor size");
293  size_type ptid = index_of_point(cv,i,use_filter);
294  GMM_ASSERT2(ptid != size_type(-1), "Point index of gauss point not found");
295  gmm::copy(gmm::sub_vector(V1, gmm::sub_interval(ptid*nb_tensor_elem_,
296  nb_tensor_elem_)),
297  T.as_vector());
298  }
299 
300  /**set a value of an integration point
301  from a raw vector data, described by the tensor size.*/
302  template <typename VECT>
303  typename VECT::value_type &set_value(VECT &V1, size_type cv, size_type i,
304  bool use_filter = true) const {
305  GMM_ASSERT2(nb_tensor_elem_*nb_index(use_filter) == V1.size(),
306  "Invalid tensorial size for vector V1");
307  GMM_ASSERT2(nb_tensor_elem_ == 1, "im_data is not of scalar type");
308  size_type ptid = index_of_point(cv,i,use_filter);
309  GMM_ASSERT2(ptid != size_type(-1), "Point index of gauss point not found");
310  return V1[ptid];
311  }
312 
313  /**set a vector of an integration point
314  from a raw vector data, described by the tensor size.*/
315  template <typename VECT1, typename VECT2>
316  void set_vector(VECT1 &V1, size_type cv, size_type i,
317  const VECT2& V2, bool use_filter = true) const {
318  if (V1.size() == 0 && V2.size() == 0)
319  return;
320  GMM_ASSERT2(nb_tensor_elem_*nb_index(use_filter) == V1.size(),
321  "Invalid tensorial size for vector V1");
322  GMM_ASSERT2(is_equivalent_with_vector(tensor_size_, V2.size()),
323  "V2 is incompatible with im_data tensor size");
324  size_type ptid = index_of_point(cv,i,use_filter);
325  GMM_ASSERT2(ptid != size_type(-1), "Point index of gauss point not found");
326  gmm::copy(V2,
327  gmm::sub_vector(V1, gmm::sub_interval(ptid*nb_tensor_elem_,
328  nb_tensor_elem_)));
329  }
330 
331  /**set a matrix of an integration point
332  from a raw vector data, described by the tensor size.*/
333  template <typename VECT, typename MAT>
334  void set_matrix(VECT &V1, size_type cv, size_type i,
335  const MAT& M, bool use_filter = true) const {
336  if (V1.size() == 0 && M.size() == 0)
337  return;
338  GMM_ASSERT2(nb_tensor_elem_*nb_index(use_filter) == V1.size(),
339  "Invalid tensorial size for vector V1");
340  GMM_ASSERT2(is_equivalent_with_matrix(tensor_size_, M.nrows(), M.ncols()),
341  "M is incompatible with im_data tensor size");
342  size_type ptid = index_of_point(cv,i,use_filter);
343  GMM_ASSERT2(ptid != size_type(-1), "Point index of gauss point not found");
344  gmm::copy(M.as_vector(),
345  gmm::sub_vector(V1, gmm::sub_interval(ptid*nb_tensor_elem_,
346  nb_tensor_elem_)));
347  }
348 
349  /**set a tensor of an integration point
350  from a raw vector data, described by the tensor size.*/
351  template <typename VECT, typename TENSOR>
352  void set_tensor(VECT &V1, size_type cv, size_type i,
353  const TENSOR& T, bool use_filter = true) const {
354  if (V1.size() == 0 && T.size() == 0)
355  return;
356  GMM_ASSERT2(nb_tensor_elem_*nb_index(use_filter) == V1.size(),
357  "Invalid tensorial size for vector V1");
358  GMM_ASSERT2(tensor_size_ == T.sizes(),
359  "T is incompatible with im_data tensor size");
360  size_type ptid = index_of_point(cv,i,use_filter);
361  GMM_ASSERT2(ptid != size_type(-1), "Point index of gauss point not found");
362  gmm::copy(T.as_vector(),
363  gmm::sub_vector(V1, gmm::sub_interval(ptid*nb_tensor_elem_,
364  nb_tensor_elem_)));
365  }
366 
367 
368  template <typename VECT1, typename VECT2>
369  void set_vector(VECT1 &V1, size_type ptid, const VECT2& V2) const {
370  GMM_ASSERT2(V1.size() != 0, "V1 of zero size");
371  GMM_ASSERT2(V2.size() != 0, "V2 of zero size");
372  GMM_ASSERT2(is_equivalent_with_vector(tensor_size_, V2.size()),
373  "V2 is incompatible with im_data tensor size");
374  gmm::copy(V2,
375  gmm::sub_vector(V1, gmm::sub_interval(ptid*nb_tensor_elem_,
376  nb_tensor_elem_)));
377  }
378 
379  template <typename VECT1, typename TENSOR>
380  void set_tensor(VECT1 &V1, size_type ptid, const TENSOR& T) const {
381  GMM_ASSERT2(V1.size() != 0, "V1 of zero size");
382  GMM_ASSERT2(T.size() != 0, "V2 of zero size");
383  GMM_ASSERT2(tensor_size_ == T.sizes(),
384  "T is incompatible with im_data tensor size");
385  gmm::copy(T.as_vector(),
386  gmm::sub_vector(V1, gmm::sub_interval(ptid*nb_tensor_elem_,
387  nb_tensor_elem_)));
388  }
389 
390  private:
391  const mesh_im &im_;
392 
393  size_type region_;
394 
395  mutable size_type nb_int_pts_intern;
396  mutable size_type nb_int_pts_onfaces;
397  mutable size_type nb_filtered_int_pts_intern;
398  mutable size_type nb_filtered_int_pts_onfaces;
399 
400  struct convex_data {
401  size_type first_int_pt_id; // index
402  size_type first_int_pt_fid; // filtered index
403  size_type nb_int_pts; // number of internal integration points
404  std::vector<size_type> first_int_pt_onface_id;
405  std::vector<size_type> first_int_pt_onface_fid;
406  std::vector<size_type> nb_int_pts_onface;
407 
408  convex_data()
409  : first_int_pt_id(-1), first_int_pt_fid(-1), nb_int_pts(0),
410  first_int_pt_onface_id(0), first_int_pt_onface_fid(0), nb_int_pts_onface(0)
411  {}
412  };
413 
414  mutable std::vector<convex_data> convexes;
415 
416  mutable gmm::uint64_type v_num_;
417 
418  bgeot::multi_index tensor_size_;
419  bgeot::multi_index actual_tensor_size_;
420  size_type nb_tensor_elem_;
421  lock_factory locks_;
422  };
423 }
424 #endif /* GETFEM_IM_DATA_H__ */
base class for static stored objects
Deal with interdependencies of objects.
bool context_check() const
return true if update_from_context was called
im_data provides indexing to the integration points of a mesh im object.
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.
const mesh & linked_mesh() const
linked mesh
im_data(const mesh_im &mim_, bgeot::multi_index tensor_size, size_type filtered_region_=size_type(-1), bgeot::multi_index actual_tensor_size={})
Constructor.
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.
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.
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.
size_type filtered_region() const
return filtered region id
size_type nb_points_of_element(size_type cv, bool use_filter=false) const
Total number of points in element cv.
size_type nb_filtered_points_of_element(size_type cv) const
Total number of points in element cv, which lie in filtered_region()
dal::bit_vector filtered_convex_index() const
List of convex in filtered region.
void update_from_context() const
called automatically when there is a change in dependencies
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.
const mesh_im & linked_mesh_im() const
linked mesh im
size_type filtered_index_of_point(size_type cv, size_type i) const
Returns the index of an integration point with filtering.
void set_region(size_type region)
set filtered region id
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()
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.
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.
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.
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_index(bool use_filter=false) const
Total numbers of index (integration points)
short_type nb_faces_of_element(size_type cv) const
Number of (active) faces in element cv.
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.
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.
size_type nb_filtered_index() const
Total numbers of filtered index (integration points)
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.
size_type nb_tensor_elem() const
sum of tensor elements, M(3,3) will have 3*3=9 elements
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.
dal::bit_vector convex_index(bool use_filter=false) const
List of convexes.
Describe an integration method linked to a mesh.
virtual pintegration_method int_method_of_element(size_type cv) const
return the integration method associated with an element (in no integration is associated,...
const mesh & linked_mesh() const
Give a reference to the linked mesh of type mesh.
"iterator" class for regions.
structure used to hold a set of convexes and/or convex faces.
Describe a mesh (collection of convexes (elements) and points).
Definition: getfem_mesh.h:99
const mesh_region region(size_type id) const
Return the region of index 'id'.
Definition: getfem_mesh.h:421
Define the getfem::mesh_im class (integration of getfem::mesh_fem).
gmm::uint16_type short_type
used as the common short type integer in the library
Definition: bgeot_config.h:73
size_t size_type
used as the common size type in the library
Definition: bgeot_poly.h:49
GEneric Tool for Finite Element Methods.
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
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