GetFEM  5.5
getfem_im_data.cc
1 /*===========================================================================
2 
3  Copyright (C) 2012-2026 Liang Jin Lim.
4 
5  This file is a part of GetFEM
6 
7  GetFEM is free software; you can redistribute it and/or modify it
8  under the terms of the GNU Lesser General Public License as published
9  by the Free Software Foundation; either version 3 of the License, or
10  (at your option) any later version along with the GCC Runtime Library
11  Exception either version 3.1 or (at your option) any later version.
12  This program is distributed in the hope that it will be useful, but
13  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15  License and GCC Runtime Library Exception for more details.
16  You should have received a copy of the GNU Lesser General Public License
17  along with this program. If not, see https://www.gnu.org/licenses/.
18 
19 ===========================================================================*/
20 
21 #include "getfem/getfem_im_data.h"
22 #include "getfem/getfem_omp.h"
23 
24 namespace getfem
25 {
26 
28  bgeot::multi_index tsize,
29  size_type filtered_region_,
30  bgeot::multi_index actual_tsize)
31  : im_(mim), region_(filtered_region_),
32  nb_int_pts_intern(0), nb_int_pts_onfaces(0),
33  nb_filtered_int_pts_intern(0), nb_filtered_int_pts_onfaces(0),
34  locks_()
35  {
36  set_tensor_size(tsize);
37  set_actual_tensor_size(actual_tsize);
38  add_dependency(im_);
40  }
41 
42  im_data::im_data(const getfem::mesh_im& mim, size_type filtered_region_)
43  : im_(mim), region_(filtered_region_),
44  nb_int_pts_intern(0), nb_int_pts_onfaces(0),
45  nb_filtered_int_pts_intern(0), nb_filtered_int_pts_onfaces(0),
46  locks_()
47  {
48  tensor_size_.resize(1);
49  tensor_size_[0] = 1;
50  actual_tensor_size_ = tensor_size_;
51  nb_tensor_elem_ = 1;
52  add_dependency(im_);
54  }
55 
56  size_type im_data::nb_index(bool use_filter) const {
57  context_check();
58  if (use_filter)
59  return nb_filtered_int_pts_intern + nb_filtered_int_pts_onfaces;
60  else
61  return nb_int_pts_intern + nb_int_pts_onfaces;
62  }
63 
64  size_type im_data::nb_points_of_element(size_type cv, bool use_filter) const {
65  context_check();
66  if (cv < convexes.size()) {
67  size_type nb_int_pts(0);
68  if (use_filter) {
69  for (short_type f=0, nb_faces=nb_faces_of_element(cv);
70  f < nb_faces; ++f)
71  if (convexes[cv].first_int_pt_onface_fid[f] != size_type(-1))
72  nb_int_pts += convexes[cv].nb_int_pts_onface[f];
73  if (convexes[cv].first_int_pt_fid != size_type(-1)) // convex in filtered_region()
74  nb_int_pts += convexes[cv].nb_int_pts;
75  }
76  else {
77  for (auto nb_pts : convexes[cv].nb_int_pts_onface)
78  nb_int_pts += nb_pts;
79  if (nb_int_pts_intern > 0) // has_convexes
80  nb_int_pts += convexes[cv].nb_int_pts;
81  }
82  return nb_int_pts;
83  }
84  return 0;
85  }
86 
88  bool use_filter) const {
89  context_check();
90  if (cv < convexes.size()) {
91  if (f == short_type(-1)) {
92  if (!use_filter || convexes[cv].first_int_pt_fid != size_type(-1))
93  return convexes[cv].nb_int_pts;
94  }
95  else if (f < convexes[cv].nb_int_pts_onface.size()) {
96  if (!use_filter || convexes[cv].first_int_pt_onface_fid[f] != size_type(-1))
97  return convexes[cv].nb_int_pts_onface[f];
98  }
99  }
100  return 0;
101  }
102 
104  context_check();
105  if (cv < convexes.size())
106  return short_type(convexes[cv].first_int_pt_onface_id.size());
107  return 0;
108  }
109 
111  bool use_filter) const {
112  context_check();
113  if (cv < convexes.size()) {
114  if (i < convexes[cv].nb_int_pts) { // internal point
115  size_type int_pt_id = use_filter ? convexes[cv].first_int_pt_fid
116  : convexes[cv].first_int_pt_id;
117  if (int_pt_id != size_type(-1))
118  return int_pt_id + i;
119  }
120  else if (nb_faces_of_element(cv) != 0) {
121  const getfem::papprox_integration pim = approx_int_method_of_element(cv);
122  for (short_type f=0, nb_faces=pim->nb_convex_faces();
123  f < nb_faces; ++f)
124  if (i < pim->repart()[f+1]) {
125  size_type int_pt_id = use_filter ? convexes[cv].first_int_pt_onface_fid[f]
126  : convexes[cv].first_int_pt_onface_id[f];
127  if (int_pt_id != size_type(-1))
128  return int_pt_id + i - pim->ind_first_point_on_face(f);
129  break;
130  }
131  }
132  }
133  return size_type(-1);
134  }
135 
137  { return index_of_point(cv, i, true); }
138 
140  bool use_filter) const {
141  context_check();
142  if (cv < convexes.size()) {
143  if (f == short_type(-1)) {
144  return use_filter ? convexes[cv].first_int_pt_fid
145  : convexes[cv].first_int_pt_id;
146  }
147  else if (f < nb_faces_of_element(cv)) {
148  return use_filter ? convexes[cv].first_int_pt_onface_fid[f]
149  : convexes[cv].first_int_pt_onface_id[f];
150  }
151  }
152  return size_type(-1);
153  }
154 
156  { return index_of_first_point(cv, f, true); }
157 
158  dal::bit_vector im_data::convex_index(bool use_filter) const {
159  context_check();
160  dal::bit_vector ind = im_.convex_index();
161  if (use_filter && filtered_region() != size_type(-1))
162  ind &= linked_mesh().region(filtered_region()).index();
163  return ind;
164  }
165 
167  region_ = rg;
169  }
170 
172  local_guard lock = locks_.get_lock();
173  bool no_region = (filtered_region() == size_type(-1));
174  const getfem::mesh_region &rg = no_region
177  bool has_convexes = (no_region || !rg.is_only_faces());
178  bool has_faces = (!no_region && !rg.is_only_convexes());
179 
180  size_type nb_cv = im_.convex_index().last_true() + 1;
181  convexes.clear();
182  convexes.resize(nb_cv);
183 
184  for (dal::bv_visitor cv(im_.convex_index()); !cv.finished(); ++cv)
185  convexes[cv].nb_int_pts
186  = im_.int_method_of_element(cv)->approx_method()->nb_points_on_convex();
187 
188  nb_int_pts_intern = 0;
189  nb_filtered_int_pts_intern = 0;
190  if (has_convexes)
191  // The global indexing of integration points follows the indexing of convexes
192  for (dal::bv_visitor cv(im_.convex_index()); !cv.finished(); ++cv) {
193  convexes[cv].first_int_pt_id = nb_int_pts_intern;
194  nb_int_pts_intern += convexes[cv].nb_int_pts;
195  if (no_region || rg.is_in(cv)) {
196  convexes[cv].first_int_pt_fid = nb_filtered_int_pts_intern;
197  nb_filtered_int_pts_intern += convexes[cv].nb_int_pts;
198  }
199  }
200 
201  nb_int_pts_onfaces = 0;
202  nb_filtered_int_pts_onfaces = 0;
203  if (has_faces) {
204  for (dal::bv_visitor cv(im_.convex_index()); !cv.finished(); ++cv) {
205  short_type nb_faces = im_.linked_mesh().nb_faces_of_convex(cv);
206  convexes[cv].first_int_pt_onface_id.assign(nb_faces, size_type(-1));
207  convexes[cv].first_int_pt_onface_fid.assign(nb_faces, size_type(-1));
208  convexes[cv].nb_int_pts_onface.assign(nb_faces, size_type(-1));
209  const getfem::papprox_integration pim(approx_int_method_of_element(cv));
210  for (short_type f = 0; f < nb_faces; ++f) {
211  convexes[cv].first_int_pt_onface_id[f] = nb_int_pts_intern +
212  nb_int_pts_onfaces;
213  size_type nb_pts = pim->nb_points_on_face(f);
214  nb_int_pts_onfaces += nb_pts;
215  if (rg.is_in(cv, f)) {
216  convexes[cv].first_int_pt_onface_fid[f] = nb_filtered_int_pts_intern +
217  nb_filtered_int_pts_onfaces;
218  nb_filtered_int_pts_onfaces += nb_pts;
219  }
220  convexes[cv].nb_int_pts_onface[f] = nb_pts;
221  }
222  }
223  }
224  v_num_ = act_counter();
225  touch();
226  }
227 
229  return nb_tensor_elem_;
230  }
231 
232  void im_data::set_tensor_size(const bgeot::multi_index& tsize) {
233  if (actual_tensor_size_ == tensor_size_) actual_tensor_size_ = tsize;
234  tensor_size_ = tsize;
235  nb_tensor_elem_ = tensor_size_.total_size();
236  }
237 
238  void im_data::set_actual_tensor_size(const bgeot::multi_index& tsize) {
239  actual_tensor_size_ = tsize.empty() ? tensor_size_ : tsize;
240  }
241 
242  bool is_equivalent_with_vector(const bgeot::multi_index &sizes, size_type vector_size) {
243  bool checked = false;
244  size_type size = 1;
245  for (size_type i = 0; i < sizes.size(); ++i) {
246  if (sizes[i] > 1 && checked) return false;
247  if (sizes[i] > 1) {
248  checked = true;
249  size = sizes[i];
250  if (size != vector_size) return false;
251  }
252  }
253  return (vector_size == size);
254  }
255 
256  bool is_equivalent_with_matrix(const bgeot::multi_index &sizes, size_type nrows, size_type ncols) {
257  if (nrows == 1 || ncols == 1) {
258  return is_equivalent_with_vector(sizes, nrows + ncols - 1);
259  }
260  size_type tensor_row = 1;
261  size_type tensor_col = 1;
262  bool first_checked = false;
263  bool second_checked = false;
264  for (size_type i = 0; i < sizes.size(); ++i) {
265  if (sizes[i] > 1 && !first_checked) {
266  first_checked = true;
267  tensor_row = sizes[i];
268  if (tensor_row != nrows) return false;
269  } else if (sizes[i] > 1 && !second_checked) {
270  second_checked = true;
271  tensor_col = sizes[i];
272  if (tensor_col != ncols) return false;
273  }
274  else if (sizes[i] > 1 && first_checked && second_checked) return false;
275  }
276  return (nrows == tensor_row && ncols == tensor_col);
277  }
278 }
short_type nb_faces_of_convex(size_type ic) const
Return the number of faces of convex ic.
bool context_check() const
return true if update_from_context was called
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.
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.
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.
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_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.
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.
const dal::bit_vector & convex_index(void) const
Get the set of convexes where an integration method has been assigned.
structure used to hold a set of convexes and/or convex faces.
static mesh_region all_convexes()
provide a default value for the mesh_region parameters of assembly procedures etc.
bool is_only_faces() const
Return true if the region do contain only convex faces.
bool is_only_convexes() const
Return true if the region do not contain any convex face.
const dal::bit_vector & index() const
Index of the region convexes, or the convexes from the partition on the current thread.
const mesh_region region(size_type id) const
Return the region of index 'id'.
Definition: getfem_mesh.h:420
Provides indexing of integration points for mesh_im.
Tools for multithreaded, OpenMP and Boost based parallelization.
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