GetFEM++  5.3
getfem_im_data.cc
1 /*===========================================================================
2 
3  Copyright (C) 2012-2017 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, write to the Free Software Foundation,
18  Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19 
20 ===========================================================================*/
21 
22 #include "getfem/getfem_im_data.h"
23 #include "getfem/getfem_omp.h"
24 
25 namespace getfem
26 {
27 
29  bgeot::multi_index tsize,
30  size_type filtered_region_)
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  add_dependency(im_);
39  }
40 
41  im_data::im_data(const getfem::mesh_im& mim, size_type filtered_region_)
42  : im_(mim), region_(filtered_region_),
43  nb_int_pts_intern(0), nb_int_pts_onfaces(0),
44  nb_filtered_int_pts_intern(0), nb_filtered_int_pts_onfaces(0),
45  locks_()
46  {
47  tensor_size_.resize(1);
48  tensor_size_[0] = 1;
49  nb_tensor_elem_ = 1;
50  add_dependency(im_);
52  }
53 
54  size_type im_data::nb_index(bool use_filter) const {
55  context_check();
56  if (use_filter)
57  return nb_filtered_int_pts_intern + nb_filtered_int_pts_onfaces;
58  else
59  return nb_int_pts_intern + nb_int_pts_onfaces;
60  }
61 
62  size_type im_data::nb_points_of_element(size_type cv, bool use_filter) const {
63  context_check();
64  if (cv < convexes.size()) {
65  size_type nb_int_pts(0);
66  if (use_filter) {
67  for (short_type f=0, nb_faces=nb_faces_of_element(cv);
68  f < nb_faces; ++f)
69  if (convexes[cv].first_int_pt_onface_fid[f] != size_type(-1))
70  nb_int_pts += convexes[cv].nb_int_pts_onface[f];
71  if (convexes[cv].first_int_pt_fid != size_type(-1)) // convex in filtered_region()
72  nb_int_pts += convexes[cv].nb_int_pts;
73  }
74  else {
75  for (auto nb_pts : convexes[cv].nb_int_pts_onface)
76  nb_int_pts += nb_pts;
77  if (nb_int_pts_intern > 0) // has_convexes
78  nb_int_pts += convexes[cv].nb_int_pts;
79  }
80  return nb_int_pts;
81  }
82  return 0;
83  }
84 
86  bool use_filter) const {
87  context_check();
88  if (cv < convexes.size()) {
89  if (f == short_type(-1)) {
90  if (!use_filter || convexes[cv].first_int_pt_fid != size_type(-1))
91  return convexes[cv].nb_int_pts;
92  }
93  else if (f < convexes[cv].nb_int_pts_onface.size()) {
94  if (!use_filter || convexes[cv].first_int_pt_onface_fid[f] != size_type(-1))
95  return convexes[cv].nb_int_pts_onface[f];
96  }
97  }
98  return 0;
99  }
100 
102  context_check();
103  if (cv < convexes.size())
104  return short_type(convexes[cv].first_int_pt_onface_id.size());
105  return 0;
106  }
107 
109  bool use_filter) const {
110  context_check();
111  if (cv < convexes.size()) {
112  if (i < convexes[cv].nb_int_pts) { // internal point
113  size_type int_pt_id = use_filter ? convexes[cv].first_int_pt_fid
114  : convexes[cv].first_int_pt_id;
115  if (int_pt_id != size_type(-1))
116  return int_pt_id + i;
117  }
118  else if (nb_faces_of_element(cv) != 0) {
119  const getfem::papprox_integration pim = approx_int_method_of_element(cv);
120  for (short_type f=0, nb_faces=pim->nb_convex_faces();
121  f < nb_faces; ++f)
122  if (i < pim->repart()[f+1]) {
123  size_type int_pt_id = use_filter ? convexes[cv].first_int_pt_onface_fid[f]
124  : convexes[cv].first_int_pt_onface_id[f];
125  if (int_pt_id != size_type(-1))
126  return int_pt_id + i - pim->ind_first_point_on_face(f);
127  break;
128  }
129  }
130  }
131  return size_type(-1);
132  }
133 
135  { return index_of_point(cv, i, true); }
136 
138  bool use_filter) const {
139  context_check();
140  if (cv < convexes.size()) {
141  if (f == short_type(-1)) {
142  return use_filter ? convexes[cv].first_int_pt_fid
143  : convexes[cv].first_int_pt_id;
144  }
145  else if (f < nb_faces_of_element(cv)) {
146  return use_filter ? convexes[cv].first_int_pt_onface_fid[f]
147  : convexes[cv].first_int_pt_onface_id[f];
148  }
149  }
150  return size_type(-1);
151  }
152 
154  { return index_of_first_point(cv, f, true); }
155 
156  dal::bit_vector im_data::convex_index(bool use_filter) const {
157  context_check();
158  dal::bit_vector ind = im_.convex_index();
159  if (use_filter && filtered_region() != size_type(-1))
160  ind &= linked_mesh().region(filtered_region()).index();
161  return ind;
162  }
163 
165  region_ = rg;
167  }
168 
170  local_guard lock = locks_.get_lock();
171  bool no_region = (filtered_region() == size_type(-1));
172  const getfem::mesh_region &rg = no_region
175  bool has_convexes = (no_region || !rg.is_only_faces());
176  bool has_faces = (!no_region && !rg.is_only_convexes());
177 
178  size_type nb_cv = im_.convex_index().last_true() + 1;
179  convexes.clear();
180  convexes.resize(nb_cv);
181 
182  for (dal::bv_visitor cv(im_.convex_index()); !cv.finished(); ++cv)
183  convexes[cv].nb_int_pts
184  = im_.int_method_of_element(cv)->approx_method()->nb_points_on_convex();
185 
186  nb_int_pts_intern = 0;
187  nb_filtered_int_pts_intern = 0;
188  if (has_convexes)
189  // The global indexing of integration points follows the indexing of convexes
190  for (dal::bv_visitor cv(im_.convex_index()); !cv.finished(); ++cv) {
191  convexes[cv].first_int_pt_id = nb_int_pts_intern;
192  nb_int_pts_intern += convexes[cv].nb_int_pts;
193  if (no_region || rg.is_in(cv)) {
194  convexes[cv].first_int_pt_fid = nb_filtered_int_pts_intern;
195  nb_filtered_int_pts_intern += convexes[cv].nb_int_pts;
196  }
197  }
198 
199  nb_int_pts_onfaces = 0;
200  nb_filtered_int_pts_onfaces = 0;
201  if (has_faces) {
202  for (dal::bv_visitor cv(im_.convex_index()); !cv.finished(); ++cv) {
203  short_type nb_faces = im_.linked_mesh().nb_faces_of_convex(cv);
204  convexes[cv].first_int_pt_onface_id.assign(nb_faces, size_type(-1));
205  convexes[cv].first_int_pt_onface_fid.assign(nb_faces, size_type(-1));
206  convexes[cv].nb_int_pts_onface.assign(nb_faces, size_type(-1));
207  const getfem::papprox_integration pim(approx_int_method_of_element(cv));
208  for (short_type f = 0; f < nb_faces; ++f) {
209  convexes[cv].first_int_pt_onface_id[f] = nb_int_pts_intern +
210  nb_int_pts_onfaces;
211  size_type nb_pts = pim->nb_points_on_face(f);
212  nb_int_pts_onfaces += nb_pts;
213  if (rg.is_in(cv, f)) {
214  convexes[cv].first_int_pt_onface_fid[f] = nb_filtered_int_pts_intern +
215  nb_filtered_int_pts_onfaces;
216  nb_filtered_int_pts_onfaces += nb_pts;
217  }
218  convexes[cv].nb_int_pts_onface[f] = nb_pts;
219  }
220  }
221  }
222  v_num_ = act_counter();
223  touch();
224  }
225 
227  return nb_tensor_elem_;
228  }
229 
230  void im_data::set_tensor_size(const bgeot::multi_index& tsize) {
231  tensor_size_ = tsize;
232  nb_tensor_elem_ = tensor_size_.total_size();
233  }
234 
235  bool is_equivalent_with_vector(const bgeot::multi_index &sizes, size_type vector_size) {
236  bool checked = false;
237  size_type size = 1;
238  for (size_type i = 0; i < sizes.size(); ++i) {
239  if (sizes[i] > 1 && checked) return false;
240  if (sizes[i] > 1) {
241  checked = true;
242  size = sizes[i];
243  if (size != vector_size) return false;
244  }
245  }
246  return (vector_size == size);
247  }
248 
249  bool is_equivalent_with_matrix(const bgeot::multi_index &sizes, size_type nrows, size_type ncols) {
250  if (nrows == 1 || ncols == 1) {
251  return is_equivalent_with_vector(sizes, nrows + ncols - 1);
252  }
253  size_type tensor_row = 1;
254  size_type tensor_col = 1;
255  bool first_checked = false;
256  bool second_checked = false;
257  for (size_type i = 0; i < sizes.size(); ++i) {
258  if (sizes[i] > 1 && !first_checked) {
259  first_checked = true;
260  tensor_row = sizes[i];
261  if (tensor_row != nrows) return false;
262  } else if (sizes[i] > 1 && !second_checked) {
263  second_checked = true;
264  tensor_col = sizes[i];
265  if (tensor_col != ncols) return false;
266  }
267  else if (sizes[i] > 1 && first_checked && second_checked) return false;
268  }
269  return (nrows == tensor_row && ncols == tensor_col);
270  }
271 }
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.
static mesh_region all_convexes()
provide a default value for the mesh_region parameters of assembly procedures etc.
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
Provides indexing of integration points for mesh_im.
const dal::bit_vector & index() const
Index of the region convexes, or the convexes from the partition on the current thread.
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.
Describe an integration method linked to a mesh.
Tools for multithreaded, OpenMP and Boost based parallelization.
const mesh & linked_mesh() const
linked mesh
size_type nb_index(bool use_filter=false) const
Total numbers of index (integration points)
size_t size_type
used as the common size type in the library
Definition: bgeot_poly.h:49
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.
GEneric Tool for Finite Element Methods.
gmm::uint16_type short_type
used as the common short type integer in the library
Definition: bgeot_config.h:79
size_type filtered_index_of_point(size_type cv, size_type i) const
Returns the index of an integration point with filtering.
const dal::bit_vector & convex_index(void) const
Get the set of convexes where an integration method has been assigned.
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
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.
short_type nb_faces_of_convex(size_type ic) const
Return the number of faces of convex ic.
const mesh_region region(size_type id) const
Return the region of index &#39;id&#39;.
Definition: getfem_mesh.h:414
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.