GetFEM++  5.3
getfem_interpolated_fem.cc
1 /*===========================================================================
2 
3  Copyright (C) 2004-2017 Yves Renard
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 
23 
24 namespace getfem {
25 
26  void interpolated_fem::build_rtree(void) const {
27  base_node min, max;
28  scalar_type EPS=1E-13;
29  boxtree.clear();
30  for (dal::bv_visitor cv(mf.convex_index()); !cv.finished(); ++cv) {
31  bounding_box(min, max, mf.linked_mesh().points_of_convex(cv),
32  mf.linked_mesh().trans_of_convex(cv));
33  for (unsigned k=0; k < min.size(); ++k) { min[k]-=EPS; max[k]+=EPS; }
34  boxtree.add_box(min, max, cv);
35  }
36  }
37 
38  bool interpolated_fem::find_a_point(base_node pt, base_node &ptr,
39  size_type &cv) const {
40  bool gt_invertible;
41  if (pif) { base_node ptreal = pt; pif->val(ptreal, pt); }
42  if (cv_stored != size_type(-1) && gic.invert(pt, ptr, gt_invertible))
43  { cv = cv_stored; if (gt_invertible) return true; }
44  boxtree.find_boxes_at_point(pt, boxlst);
45  bgeot::rtree::pbox_set::const_iterator it = boxlst.begin(),
46  ite = boxlst.end();
47  for (; it != ite; ++it) {
49  (mf.linked_mesh().convex((*it)->id),
50  mf.linked_mesh().trans_of_convex((*it)->id));
51  cv_stored = (*it)->id;
52  if (gic.invert(pt, ptr, gt_invertible)) {
53  cv = (*it)->id; return true;
54  }
55  }
56  return false;
57  }
58 
60  fictx_cv = cv_stored = size_type(-1);
61  dim_ = dim_type(-1);
62  build_rtree();
63 
64  GMM_ASSERT1(!mf.is_reduced(),
65  "Interpolated fem works only on non reduced mesh_fems");
66 
67  std::vector<elt_interpolation_data> vv(mim.convex_index().last_true() + 1);
68  elements.swap(vv);
69  base_node gpt;
70  ind_dof.resize(mf.nb_basic_dof());
71  dal::bit_vector alldofs;
72  size_type max_dof = 0;
73  if (mim.convex_index().card() == 0) return;
74  for (dal::bv_visitor cv(mim.convex_index()); !cv.finished(); ++cv) {
75  if (dim_ == dim_type(-1))
76  dim_ = mim.linked_mesh().structure_of_convex(cv)->dim();
77 
78  GMM_ASSERT1(dim_ == mim.linked_mesh().structure_of_convex(cv)->dim(),
79  "Convexes of different dimension: to be done");
80  pintegration_method pim = mim.int_method_of_element(cv);
81  GMM_ASSERT1(pim->type() == IM_APPROX, "You have to use approximated "
82  "integration to interpolate a fem");
83  papprox_integration pai = pim->approx_method();
84  bgeot::pgeometric_trans pgt = mim.linked_mesh().trans_of_convex(cv);
85  elements[cv].gausspt.resize(pai->nb_points());
86  dal::bit_vector dofs;
87  size_type last_cv = size_type(-1);
88  for (size_type k = 0; k < pai->nb_points(); ++k) {
89  gausspt_interpolation_data &gpid = elements[cv].gausspt[k];
90  /* todo: use a geotrans_interpolation_context */
91  gpt = pgt->transform(pai->point(k),
92  mim.linked_mesh().points_of_convex(cv));
93  gpid.iflags = find_a_point(gpt, gpid.ptref, gpid.elt) ? 1 : 0;
94  if (gpid.iflags && last_cv != gpid.elt) {
95  size_type nbd = mf.nb_basic_dof_of_element(gpid.elt);
96  for (size_type i = 0; i < nbd; ++i) {
97  size_type idof = mf.ind_basic_dof_of_element(gpid.elt)[i];
98  if (!(blocked_dof[idof])) dofs.add(idof);
99  }
100  last_cv = gpid.elt;
101  }
102  }
103  elements[cv].nb_dof = dofs.card();
104  elements[cv].pim = pim;
105  max_dof = std::max(max_dof, dofs.card());
106  elements[cv].inddof.resize(dofs.card());
107  size_type cnt = 0;
108  for (dal::bv_visitor idof(dofs); !idof.finished(); ++idof)
109  { elements[cv].inddof[cnt] = idof; ind_dof[idof] = cnt++; }
110  for (size_type k = 0; k < pai->nb_points(); ++k) {
111  gausspt_interpolation_data &gpid = elements[cv].gausspt[k];
112  if (gpid.iflags) {
113  size_type nbd = mf.nb_basic_dof_of_element(gpid.elt);
114  gpid.local_dof.resize(nbd);
115  for (size_type i = 0; i < nbd; ++i) {
116  size_type ndof = mf.ind_basic_dof_of_element(gpid.elt)[i];
117  gpid.local_dof[i] = dofs.is_in(ndof) ? ind_dof[ndof]
118  : size_type(-1);
119  }
120  }
121  }
122  alldofs |= dofs;
123  }
124  /** setup global dofs, with dummy coordinates */
125  base_node P(dim()); gmm::fill(P,1./20);
126  std::vector<base_node> node_tab_(max_dof, P);
127  pspt_override = bgeot::store_point_tab(node_tab_);
128  pspt_valid = false;
129  dof_types_.resize(max_dof);
130  std::fill(dof_types_.begin(), dof_types_.end(),
131  global_dof(dim()));
132 
133  /* ind_dof should be kept full of -1 ( real_base_value and
134  grad_base_value expect that)
135  */
136  std::fill(ind_dof.begin(), ind_dof.end(), size_type(-1));
137  }
138 
140  { context_check();
141  if (mim.linked_mesh().convex_index().is_in(cv))
142  return elements[cv].nb_dof;
143  else GMM_ASSERT1(false, "Wrong convex number: " << cv);
144  }
145 
146  size_type interpolated_fem::index_of_global_dof
147  (size_type cv, size_type i) const
148  { return elements[cv].inddof[i]; }
149 
150  bgeot::pconvex_ref interpolated_fem::ref_convex(size_type cv) const
151  { return mim.int_method_of_element(cv)->approx_method()->ref_convex(); }
152 
154  (size_type cv) const
155  {
156  if (mim.linked_mesh().convex_index().is_in(cv))
158  (dim(), nb_dof(cv),
159  mim.linked_mesh().structure_of_convex(cv)->nb_faces()));
160  else GMM_ASSERT1(false, "Wrong convex number: " << cv);
161  }
162 
163  void interpolated_fem::base_value(const base_node &, base_tensor &) const
164  { GMM_ASSERT1(false, "No base values, real only element."); }
165  void interpolated_fem::grad_base_value(const base_node &,
166  base_tensor &) const
167  { GMM_ASSERT1(false, "No grad values, real only element."); }
168  void interpolated_fem::hess_base_value(const base_node &,
169  base_tensor &) const
170  { GMM_ASSERT1(false, "No hess values, real only element."); }
171 
172  inline void interpolated_fem::actualize_fictx(pfem pf, size_type cv,
173  const base_node &ptr) const {
174  if (fictx_cv != cv) {
175  mf.linked_mesh().points_of_convex(cv, G);
177  (mf.linked_mesh().trans_of_convex(cv), pf, base_node(), G, cv,
178  short_type(-1));
179  fictx_cv = cv;
180  }
181  fictx.set_xref(ptr);
182  }
183 
185  base_tensor &t, bool) const {
186  elt_interpolation_data &e = elements.at(c.convex_num());
187  size_type cv;
188 
189  mi2[1] = target_dim(); mi2[0] = short_type(e.nb_dof);
190  t.adjust_sizes(mi2);
191  std::fill(t.begin(), t.end(), scalar_type(0));
192  if (e.nb_dof == 0) return;
193 
194  if (c.have_pgp() &&
195  (c.pgp()->get_ppoint_tab()
196  == e.pim->approx_method()->pintegration_points())) {
197  gausspt_interpolation_data &gpid = e.gausspt.at(c.ii());
198  if (gpid.iflags & 1) {
199  cv = gpid.elt;
200  pfem pf = mf.fem_of_element(cv);
201  unsigned rdim = target_dim() / pf->target_dim(), mdim = (rdim==1) ? 0 : 1;
202  if (gpid.iflags & 2) { t = gpid.base_val; return; }
203  actualize_fictx(pf, cv, gpid.ptref);
204  pf->real_base_value(fictx, taux);
205  for (size_type i = 0; i < pf->nb_dof(cv); ++i)
206  if (gpid.local_dof[i*rdim] != size_type(-1))
207  for (size_type j = 0; j < target_dim(); ++j)
208  t(gpid.local_dof[i*rdim+j*mdim],j) = taux(i, j*(1-mdim));
209  if (store_values) { gpid.base_val = t; gpid.iflags |= 2; }
210  }
211  }
212  else {
213  if (find_a_point(c.xreal(), ptref, cv)) {
214  pfem pf = mf.fem_of_element(cv);
215  unsigned rdim = target_dim() / pf->target_dim(), mdim = (rdim==1) ? 0 : 1;
216  actualize_fictx(pf, cv, ptref);
217  pf->real_base_value(fictx, taux);
218  for (size_type i = 0; i < e.nb_dof; ++i) {
219  ind_dof.at(e.inddof[i]) = i;
220  }
221  for (size_type i = 0; i < pf->nb_dof(cv); ++i)
222  for (size_type j = 0; j < target_dim(); ++j)
223  if (ind_dof.at(mf.ind_basic_dof_of_element(cv)[i*rdim+j*mdim])
224  != size_type(-1)) {
225  t(ind_dof[mf.ind_basic_dof_of_element(cv)[i*rdim+j*mdim]], j)
226  = taux(i, j*(1-mdim));
227  }
228  for (size_type i = 0; i < elements[c.convex_num()].nb_dof; ++i)
229  ind_dof[e.inddof[i]] = size_type(-1);
230  }
231  }
232 
233  }
234 
236  (const fem_interpolation_context& c, base_tensor &t, bool) const {
237  size_type N0 = mf.linked_mesh().dim();
238  elt_interpolation_data &e = elements.at(c.convex_num());
239  size_type nbdof = e.nb_dof, cv;
240 
241  mi3[2] = short_type(N0); mi3[1] = target_dim(); mi3[0] = short_type(nbdof);
242  t.adjust_sizes(mi3);
243  std::fill(t.begin(), t.end(), scalar_type(0));
244  if (nbdof == 0) return;
245 
246  if (c.have_pgp() &&
247  (c.pgp()->get_ppoint_tab()
248  == e.pim->approx_method()->pintegration_points())) {
249  gausspt_interpolation_data &gpid = e.gausspt.at(c.ii());
250  if (gpid.iflags & 1) {
251  cv = gpid.elt;
252  pfem pf = mf.fem_of_element(cv);
253  unsigned rdim = target_dim() / pf->target_dim(), mdim = (rdim==1) ? 0 : 1;
254  if (gpid.iflags & 4) { t = gpid.grad_val; return; }
255  actualize_fictx(pf, cv, gpid.ptref);
256  pf->real_grad_base_value(fictx, taux);
257 
258  if (pif) {
259  pif->grad(c.xreal(), trans);
260  for (size_type i = 0; i < pf->nb_dof(cv); ++i)
261  if (gpid.local_dof[i*rdim] != size_type(-1))
262  for (size_type j = 0; j < target_dim(); ++j)
263  for (size_type k = 0; k < N0; ++k) {
264  scalar_type ee(0);
265  for (size_type l = 0; l < N0; ++l)
266  ee += trans(l, k) * taux(i, j*(1-mdim), l);
267  t(gpid.local_dof[i*rdim+j*mdim], j, k) = ee;
268  }
269  }
270  else {
271  for (size_type i = 0; i < pf->nb_dof(cv); ++i)
272  if (gpid.local_dof[i*rdim] != size_type(-1))
273  for (size_type j = 0; j < target_dim(); ++j)
274  for (size_type k = 0; k < N0; ++k)
275  t(gpid.local_dof[i*rdim+j*mdim], j, k)
276  = taux(i, j*(1-mdim), k);
277  if (store_values) { gpid.grad_val = t; gpid.iflags |= 4; }
278  }
279  }
280  }
281  else {
282  cerr << "NON PGP OU MAUVAIS PTS sz=" << elements.size() << ", cv="
283  << c.convex_num() << " ";
284  cerr << "ii=" << c.ii() << ", sz=" << e.gausspt.size() << "\n";
285 
286  if (find_a_point(c.xreal(), ptref, cv)) {
287  pfem pf = mf.fem_of_element(cv);
288  unsigned rdim = target_dim() / pf->target_dim(), mdim = (rdim==1) ? 0 : 1;
289  actualize_fictx(pf, cv, ptref);
290  pf->real_grad_base_value(fictx, taux);
291  for (size_type i = 0; i < nbdof; ++i)
292  ind_dof.at(e.inddof.at(i)) = i;
293  if (pif) {
294  pif->grad(c.xreal(), trans);
295  for (size_type i = 0; i < pf->nb_dof(cv); ++i)
296  for (size_type j = 0; j < target_dim(); ++j)
297  for (size_type k = 0; k < N0; ++k)
298  if (ind_dof[mf.ind_basic_dof_of_element(cv)[i*rdim+j*mdim]]
299  != size_type(-1)) {
300  scalar_type ee(0);
301  for (size_type l = 0; l < N0; ++l)
302  ee += trans(l, k) * taux(i, j*(1-mdim), l);
303  t(ind_dof[mf.ind_basic_dof_of_element(cv)[i*rdim+j*mdim]],j,k)=ee;
304  }
305  }
306  else {
307  for (size_type i = 0; i < pf->nb_dof(cv); ++i)
308  for (size_type j = 0; j < target_dim(); ++j)
309  for (size_type k = 0; k < N0; ++k)
310  if (ind_dof[mf.ind_basic_dof_of_element(cv)[i*rdim+j*mdim]]
311  != size_type(-1))
312  t(ind_dof[mf.ind_basic_dof_of_element(cv)[i*rdim+j*mdim]],j,k)
313  = taux(i,j*(1-mdim),k);
314  }
315  for (size_type i = 0; i < nbdof; ++i)
316  ind_dof[e.inddof[i]] = size_type(-1);
317  }
318  }
319  }
320 
322  (const fem_interpolation_context&, base_tensor &, bool) const
323  { GMM_ASSERT1(false, "Sorry, to be done."); }
324 
325 
326  dal::bit_vector interpolated_fem::interpolated_convexes() const {
327  dal::bit_vector bv;
328  for (dal::bv_visitor cv(mim.linked_mesh().convex_index()); !cv.finished();
329  ++cv) {
330  for (unsigned ii=0; ii < elements.at(cv).gausspt.size(); ++ii) {
331  if (elements[cv].gausspt[ii].iflags)
332  bv.add(elements[cv].gausspt[ii].elt);
333  }
334  }
335  return bv;
336  }
337 
338  void interpolated_fem::gauss_pts_stats(unsigned &ming, unsigned &maxg,
339  scalar_type &meang) const {
340  std::vector<unsigned> v(mf.linked_mesh().nb_allocated_convex());
341  for (dal::bv_visitor cv(mim.linked_mesh().convex_index());
342  !cv.finished(); ++cv) {
343  for (unsigned ii=0; ii < elements.at(cv).gausspt.size(); ++ii) {
344  if (elements[cv].gausspt[ii].iflags)
345  v[elements[cv].gausspt[ii].elt]++;
346  }
347  }
348  ming = 100000; maxg = 0; meang = 0;
349  for (dal::bv_visitor cv(mf.linked_mesh().convex_index());
350  !cv.finished(); ++cv) {
351  ming = std::min(ming, v[cv]);
352  maxg = std::max(maxg, v[cv]);
353  meang += v[cv];
354  }
355  meang /= scalar_type(mf.linked_mesh().convex_index().card());
356  }
357 
358  size_type interpolated_fem::memsize() const {
359  size_type sz = 0;
360  sz += blocked_dof.memsize();
361  sz += sizeof(*this);
362  sz += elements.capacity() * sizeof(elt_interpolation_data);
363  for (unsigned i=0; i < elements.size(); ++i) {
364  sz += elements[i].gausspt.capacity()*sizeof(gausspt_interpolation_data);
365  sz += elements[i].inddof.capacity() * sizeof(size_type);
366  for (unsigned j=0; j < elements[i].gausspt.size(); ++j) {
367  sz += elements[i].gausspt[j].local_dof.capacity() * sizeof(size_type);
368  }
369  }
370  return sz;
371  }
372 
373  interpolated_fem::interpolated_fem(const mesh_fem &mef,
374  const mesh_im &meim,
375  pinterpolated_func pif_,
376  dal::bit_vector blocked_dof_,
377  bool store_val)
378  : mf(mef), mim(meim), pif(pif_), store_values(store_val),
379  blocked_dof(blocked_dof_), mi2(2), mi3(3) {
380  DAL_STORED_OBJECT_DEBUG_CREATED(this, "Interpolated fem");
381  this->add_dependency(mf);
382  this->add_dependency(mim);
383  is_pol = is_lag = is_standard_fem = false; es_degree = 5;
384  is_equiv = real_element_defined = true;
385  gmm::resize(trans, mf.linked_mesh().dim(), mf.linked_mesh().dim());
386  ntarget_dim = mef.get_qdim();
388  }
389 
390  DAL_SIMPLE_KEY(special_intfem_key, pfem);
391 
392  pfem new_interpolated_fem(const mesh_fem &mef, const mesh_im &mim,
393  pinterpolated_func pif,
394  dal::bit_vector blocked_dof, bool store_val) {
395  pfem pf = std::make_shared<interpolated_fem>
396  (mef, mim, pif, blocked_dof, store_val);
397  dal::pstatic_stored_object_key pk=std::make_shared<special_intfem_key>(pf);
398  dal::add_stored_object(pk, pf);
399  return pf;
400  }
401 
402 
403 } /* end of namespace getfem. */
404 
virtual size_type nb_basic_dof_of_element(size_type cv) const
Return the number of degrees of freedom attached to a given convex.
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)
void gauss_pts_stats(unsigned &ming, unsigned &maxg, scalar_type &meang) const
return the min/max/mean number of gauss points in the convexes of the interpolated mesh_fem ...
void real_base_value(const fem_interpolation_context &c, base_tensor &t, bool=true) const
Give the value of all components of the base functions at the current point of the fem_interpolation_...
virtual const bgeot::convex< base_node > & node_convex(size_type cv) const
Gives the convex representing the nodes on the reference element.
size_type convex_num() const
get the current convex number
Definition: getfem_fem.cc:52
dim_type dim() const
dimension of the reference element.
Definition: getfem_fem.h:306
virtual size_type nb_dof(size_type cv) const
Number of degrees of freedom.
virtual pfem fem_of_element(size_type cv) const
Return the basic fem associated with an element (if no fem is associated, the function will crash! us...
ref_convex convex(size_type ic) const
return a bgeot::convex object for the convex number ic.
Definition: getfem_mesh.h:189
pconvex_structure structure_of_convex(size_type ic) const
Return the pconvex_structure of the convex ic.
does the inversion of the geometric transformation for a given convex
Describe an integration method linked to a mesh.
void grad_base_value(const base_node &, base_tensor &) const
Give the value of all gradients (on ref.
void hess_base_value(const base_node &, base_tensor &) const
Give the value of all hessians (on ref.
const base_node & xreal() const
coordinates of the current point, in the real convex.
size_t size_type
used as the common size type in the library
Definition: bgeot_poly.h:49
void add_stored_object(pstatic_stored_object_key k, pstatic_stored_object o, permanence perm)
Add an object with two optional dependencies.
virtual size_type nb_basic_dof() const
Return the total number of basic degrees of freedom (before the optional reduction).
virtual dim_type get_qdim() const
Return the Q dimension.
bool invert(const base_node &n, base_node &n_ref, scalar_type IN_EPS=1e-12)
given the node on the real element, returns the node on the reference element (even if it is outside ...
structure passed as the argument of fem interpolation functions.
Definition: getfem_fem.h:741
dim_type target_dim() const
dimension of the target space.
Definition: getfem_fem.h:309
bool is_reduced() const
Return true if a reduction matrix is applied to the dofs.
GEneric Tool for Finite Element Methods.
std::shared_ptr< const getfem::virtual_fem > pfem
type of pointer on a fem description
Definition: getfem_fem.h:239
Describe a finite element method linked to a mesh.
gmm::uint16_type short_type
used as the common short type integer in the library
Definition: bgeot_config.h:79
size_type nb_allocated_convex() const
The number of convex indexes from 0 to the index of the last convex.
dal::bit_vector interpolated_convexes() const
return the list of convexes of the interpolated mesh_fem which contain at least one gauss point (shou...
pfem new_interpolated_fem(const mesh_fem &mef, const mesh_im &mim, pinterpolated_func pif=0, dal::bit_vector blocked_dof=dal::bit_vector(), bool store_val=true)
create a new interpolated FEM.
const dal::bit_vector & convex_index(void) const
Get the set of convexes where an integration method has been assigned.
virtual void update_from_context(void) const
this function has to be defined and should update the object when the context is modified.
FEM which interpolates a mesh_fem on a different mesh.
void set_xref(const base_node &P)
change the current point (coordinates given in the reference convex)
const mesh & linked_mesh() const
Return a reference to the underlying mesh.
const mesh & linked_mesh() const
Give a reference to the linked mesh of type mesh.
pconvex_ref generic_dummy_convex_ref(dim_type nc, size_type n, short_type nf)
generic convex with n global nodes
bool context_check() const
return true if update_from_context was called
virtual bgeot::pconvex_ref ref_convex(size_type cv) const
Return the convex of the reference element.
const dal::bit_vector & convex_index() const
Get the set of convexes where a finite element has been assigned.
void base_value(const base_node &, base_tensor &) const
Give the value of all components of the base functions at the point x of the reference element...
pdof_description global_dof(dim_type d)
Description of a global dof, i.e.
Definition: getfem_fem.cc:521
virtual ind_dof_ct ind_basic_dof_of_element(size_type cv) const
Give an array of the dof numbers a of convex.
const dal::bit_vector & convex_index() const
Return the list of valid convex IDs.
std::shared_ptr< const bgeot::geometric_trans > pgeometric_trans
pointer type for a geometric transformation
void real_hess_base_value(const fem_interpolation_context &, base_tensor &, bool=true) const
Give the hessian of all components of the base functions at the current point of the fem_interpolatio...
void real_grad_base_value(const fem_interpolation_context &c, base_tensor &t, bool=true) const
Give the gradient of all components of the base functions at the current point of the fem_interpolati...