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