GetFEM++  5.3
getfem_fem_global_function.cc
1 /*===========================================================================
2 
3  Copyright (C) 2004-2017 Yves Renard
4  Copyright (C) 2016 Konstantinos Poulios
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 ===========================================================================*/
22 
24 
25 namespace getfem {
26 
27 
28  void fem_global_function::init() {
29  is_pol = is_lag = is_standard_fem = false; es_degree = 5;
30  is_equiv = real_element_defined = true;
31  ntarget_dim = 1; // An extension for vectorial elements should be easy
32 
33  std::stringstream nm;
34  nm << "GLOBAL_FEM(" << (void*)this << ")";
35  debug_name_ = nm.str();
36 
37  GMM_ASSERT1(functions.size() > 0, "Empty list of base functions.");
38  dim_ = functions[0]->dim();
39  for (size_type i=1; i < functions.size(); ++i)
40  GMM_ASSERT1(dim_ == functions[i]->dim(),
41  "Incompatible function space dimensions.");
42 
44  }
45 
46 
47  fem_global_function::fem_global_function
48  (const std::vector<pglobal_function> &funcs, const mesh &m_)
49  : functions(funcs), m(m_), mim(dummy_mesh_im()), has_mesh_im(false) {
50 
51  DAL_STORED_OBJECT_DEBUG_CREATED(this, "Global function fem");
52  GMM_ASSERT1(&m != &dummy_mesh(), "A non-empty mesh object"
53  " is expected.");
54  this->add_dependency(m_);
55  init();
56  }
57 
58  fem_global_function::fem_global_function
59  (const std::vector<pglobal_function> &funcs, const mesh_im &mim_)
60  : functions(funcs), m(mim_.linked_mesh()), mim(mim_), has_mesh_im(true) {
61 
62  DAL_STORED_OBJECT_DEBUG_CREATED(this, "Global function fem");
63  GMM_ASSERT1(&mim != &dummy_mesh_im(), "A non-empty mesh_im object"
64  " is expected.");
65  this->add_dependency(mim_);
66  init();
67  }
68 
70 
71  if (precomps) {
72  for (const auto &cv_precomps : *precomps)
73  for (const auto &keyval : cv_precomps)
74  dal::del_dependency(precomps, keyval.first);
75  precomps->clear();
76  } else {
77  precomps = std::make_shared<precomp_pool>();
78  dal::pstatic_stored_object_key pkey
79  = std::make_shared<precomp_pool_key>(precomps);
80  dal::add_stored_object(pkey, precomps);
81  }
82 
83  size_type nb_total_dof(functions.size());
84  base_node bmin(dim()), bmax(dim());
85  bgeot::rtree boxtree;
86  for (size_type i=0; i < nb_total_dof; ++i) {
87  functions[i]->bounding_box(bmin, bmax);
88  boxtree.add_box(bmin, bmax, i);
89  }
90 
91  scalar_type EPS=1E-13;
92  size_type max_dof(0);
93  index_of_global_dof_.clear();
94  index_of_global_dof_.resize(m.nb_allocated_convex());
95  for (dal::bv_visitor cv(m.convex_index()); !cv.finished(); ++cv) {
96  GMM_ASSERT1(dim_ == m.structure_of_convex(cv)->dim(),
97  "Convexes of different dimension: to be done");
98  bgeot::pgeometric_trans pgt = m.trans_of_convex(cv);
99 
100  bounding_box(bmin, bmax, m.points_of_convex(cv), pgt);
101  for (auto&& xx : bmin) xx -= EPS;
102  for (auto&& xx : bmax) xx += EPS;
103 
104  bgeot::rtree::pbox_set boxlst;
105  boxtree.find_intersecting_boxes(bmin, bmax, boxlst);
106  index_of_global_dof_[cv].clear();
107 
108  if (has_mesh_im) {
109  pintegration_method pim = mim.int_method_of_element(cv);
110  GMM_ASSERT1(pim->type() == IM_APPROX, "You have to use approximated "
111  "integration in connection to a fem with global functions");
112  papprox_integration pai = pim->approx_method();
113 
114  for (const auto &box : boxlst) {
115  for (size_type k = 0; k < pai->nb_points(); ++k) {
116  base_node gpt = pgt->transform(pai->point(k),
117  m.points_of_convex(cv));
118  if (functions[box->id]->is_in_support(gpt)) {
119  index_of_global_dof_[cv].push_back(box->id);
120  break;
121  }
122  }
123  }
124  } else { // !has_mesh_im
125  for (const auto &box : boxlst)
126  index_of_global_dof_[cv].push_back(box->id);
127  }
128  max_dof = std::max(max_dof, index_of_global_dof_[cv].size());
129  }
130 
131  /** setup global dofs, with dummy coordinates */
132  base_node P(dim()); gmm::fill(P,1./20);
133  std::vector<base_node> node_tab_(max_dof, P);
134  pspt_override = bgeot::store_point_tab(node_tab_);
135  pspt_valid = false;
136  dof_types_.resize(nb_total_dof);
137  std::fill(dof_types_.begin(), dof_types_.end(),
138  global_dof(dim()));
139  }
140 
142  //return functions.size();
143  context_check();
144  return (cv < index_of_global_dof_.size()) ? index_of_global_dof_[cv].size()
145  : size_type(0);
146  }
147 
148  size_type fem_global_function::index_of_global_dof
149  (size_type cv, size_type i) const {
150  //return i;
151  context_check();
152  return (cv < index_of_global_dof_.size() &&
153  i < index_of_global_dof_[cv].size()) ? index_of_global_dof_[cv][i]
154  : size_type(-1);
155  }
156 
157  bgeot::pconvex_ref fem_global_function::ref_convex(size_type cv) const {
158  if (has_mesh_im)
159  return mim.int_method_of_element(cv)->approx_method()->ref_convex();
160  else
161  return bgeot::basic_convex_ref(m.trans_of_convex(cv)->convex_ref());
162  }
163 
166  if (m.convex_index().is_in(cv))
168  (dim(), nb_dof(cv), m.structure_of_convex(cv)->nb_faces()));
169  else GMM_ASSERT1(false, "Wrong convex number: " << cv);
170  }
171 
172  void fem_global_function::base_value(const base_node &, base_tensor &) const
173  { GMM_ASSERT1(false, "No base values, real only element."); }
174  void fem_global_function::grad_base_value(const base_node &,
175  base_tensor &) const
176  { GMM_ASSERT1(false, "No grad values, real only element."); }
177  void fem_global_function::hess_base_value(const base_node &,
178  base_tensor &) const
179  { GMM_ASSERT1(false, "No hess values, real only element."); }
180 
182  base_tensor &t, bool) const {
183  assert(target_dim() == 1);
184  size_type cv = c.convex_num();
185  size_type nbdof = nb_dof(cv);
186  t.adjust_sizes(nbdof, target_dim());
187  if (c.have_pfp() && c.ii() != size_type(-1)) {
188  GMM_ASSERT1(precomps, "Internal error");
189  if (precomps->size() == 0)
190  precomps->resize(m.nb_allocated_convex());
191  GMM_ASSERT1(precomps->size() == m.nb_allocated_convex(), "Internal error");
192  const bgeot::pstored_point_tab ptab = c.pfp()->get_ppoint_tab();
193  auto it = (*precomps)[cv].find(ptab);
194  if (it == (*precomps)[cv].end()) {
195  it = (*precomps)[cv].emplace(ptab, precomp_data()).first;
196  dal::add_dependency(precomps, ptab);
197  // we could have added the dependency to this->shared_from_this()
198  // instead, but there is a risk that this will shadow the same
199  // dependency through a different path, so that it becomes dangerous
200  // to delete the dependency later
201  }
202  if (it->second.val.size() == 0) {
203  it->second.val.resize(ptab->size());
204  base_matrix G;
205  bgeot::vectors_to_base_matrix(G, m.points_of_convex(cv));
206  for (size_type k = 0; k < ptab->size(); ++k) {
208  ctx(m.trans_of_convex(cv), shared_from_this(), (*ptab)[k], G, cv);
209  real_base_value(ctx, it->second.val[k]);
210  }
211  }
212  gmm::copy(it->second.val[c.ii()].as_vector(), t.as_vector());
213  } else
214  for (size_type i=0; i < nbdof; ++i) {
215  /*cerr << "fem_global_function: real_base_value(" << c.xreal() << ")\n";
216  if (c.have_G()) cerr << "G = " << c.G() << "\n";
217  else cerr << "no G\n";*/
218  t[i] = functions[index_of_global_dof_[cv][i]]->val(c);
219  }
220  }
221 
223  (const fem_interpolation_context& c, base_tensor &t, bool) const {
224  assert(target_dim() == 1);
225  size_type cv = c.convex_num();
226  size_type nbdof = nb_dof(cv);
227  t.adjust_sizes(nbdof, target_dim(), dim());
228  if (c.have_pfp() && c.ii() != size_type(-1)) {
229  GMM_ASSERT1(precomps, "Internal error");
230  if (precomps->size() == 0)
231  precomps->resize(m.nb_allocated_convex());
232  GMM_ASSERT1(precomps->size() == m.nb_allocated_convex(), "Internal error");
233  const bgeot::pstored_point_tab ptab = c.pfp()->get_ppoint_tab();
234  auto it = (*precomps)[cv].find(ptab);
235  if (it == (*precomps)[cv].end()) {
236  it = (*precomps)[cv].emplace(ptab, precomp_data()).first;
237  dal::add_dependency(precomps, ptab);
238  }
239  if (it->second.grad.size() == 0) {
240  it->second.grad.resize(ptab->size());
241  base_matrix G;
242  bgeot::vectors_to_base_matrix(G, m.points_of_convex(cv));
243  for (size_type k = 0; k < ptab->size(); ++k) {
245  ctx(m.trans_of_convex(cv), shared_from_this(), (*ptab)[k], G, cv);
246  real_grad_base_value(ctx, it->second.grad[k]);
247  }
248  }
249  gmm::copy(it->second.grad[c.ii()].as_vector(), t.as_vector());
250  } else {
251  base_small_vector G(dim());
252  for (size_type i=0; i < nbdof; ++i) {
253  functions[index_of_global_dof_[cv][i]]->grad(c,G);
254  for (size_type j=0; j < dim(); ++j)
255  t[j*nbdof + i] = G[j];
256  }
257  }
258  }
259 
261  (const fem_interpolation_context &c, base_tensor &t, bool) const {
262  assert(target_dim() == 1);
263  size_type cv = c.convex_num();
264  size_type nbdof = nb_dof(cv);
265  t.adjust_sizes(nbdof, target_dim(), gmm::sqr(dim()));
266  if (c.have_pfp() && c.ii() != size_type(-1)) {
267  GMM_ASSERT1(precomps, "Internal error");
268  if (precomps->size() == 0)
269  precomps->resize(m.nb_allocated_convex());
270  GMM_ASSERT1(precomps->size() == m.nb_allocated_convex(), "Internal error");
271  const bgeot::pstored_point_tab ptab = c.pfp()->get_ppoint_tab();
272  auto it = (*precomps)[cv].find(ptab);
273  if (it == (*precomps)[cv].end()) {
274  it = (*precomps)[cv].emplace(ptab, precomp_data()).first;
275  dal::add_dependency(precomps, ptab);
276  }
277  if (it->second.hess.size() == 0) {
278  it->second.hess.resize(ptab->size());
279  base_matrix G;
280  bgeot::vectors_to_base_matrix(G, m.points_of_convex(cv));
281  for (size_type k = 0; k < ptab->size(); ++k) {
283  ctx(m.trans_of_convex(cv), shared_from_this(), (*ptab)[k], G, cv);
284  real_hess_base_value(ctx, it->second.hess[k]);
285  }
286  }
287  gmm::copy(it->second.hess[c.ii()].as_vector(), t.as_vector());
288  } else {
289  base_matrix H(dim(),dim());
290  for (size_type i=0; i < nbdof; ++i) {
291  functions[index_of_global_dof_[cv][i]]->hess(c,H);
292  for (size_type jk=0; jk < size_type(dim()*dim()); ++jk)
293  t[jk*nbdof + i] = H[jk];
294  }
295  }
296  }
297 
298 
299  DAL_SIMPLE_KEY(special_fem_globf_key, pfem);
300 
301  pfem new_fem_global_function(const std::vector<pglobal_function> &funcs,
302  const mesh &m) {
303  pfem pf = std::make_shared<fem_global_function>(funcs, m);
304  dal::pstatic_stored_object_key
305  pk = std::make_shared<special_fem_globf_key>(pf);
306  dal::add_stored_object(pk, pf);
307  return pf;
308  }
309 
310  pfem new_fem_global_function(const std::vector<pglobal_function> &funcs,
311  const mesh_im &mim) {
312  pfem pf = std::make_shared<fem_global_function>(funcs, mim);
313  dal::pstatic_stored_object_key
314  pk = std::make_shared<special_fem_globf_key>(pf);
315  dal::add_stored_object(pk, pf);
316  return pf;
317  }
318 
319 }
320 
321 /* end of namespace getfem */
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)
pconvex_ref basic_convex_ref(pconvex_ref cvr)
return the associated order 1 reference convex.
const mesh_im & dummy_mesh_im()
Dummy mesh_im for default parameter of functions.
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...
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
bool have_pfp() const
true if a fem_precomp_ has been supplied.
Definition: getfem_fem.h:752
Describe a mesh (collection of convexes (elements) and points).
Definition: getfem_mesh.h:95
pconvex_structure structure_of_convex(size_type ic) const
Return the pconvex_structure of the convex ic.
Describe an integration method linked to a mesh.
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...
void hess_base_value(const base_node &, base_tensor &) const
Give the value of all hessians (on ref.
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_...
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.
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...
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 del_dependency(pstatic_stored_object o1, pstatic_stored_object o2)
remove a dependency.
Define mesh_fem whose base functions are global function given by the user.
void add_dependency(pstatic_stored_object o1, pstatic_stored_object o2)
Add a dependency, object o1 will depend on object o2.
GEneric Tool for Finite Element Methods.
pfem_precomp pfp() const
get the current fem_precomp_
Definition: getfem_fem.h:786
std::shared_ptr< const getfem::virtual_fem > pfem
type of pointer on a fem description
Definition: getfem_fem.h:239
size_type nb_allocated_convex() const
The number of convex indexes from 0 to the index of the last convex.
virtual const bgeot::convex< base_node > & node_convex(size_type cv) const
Gives the convex representing the nodes on the reference element.
virtual void update_from_context() const
this function has to be defined and should update the object when the context is modified.
virtual bgeot::pconvex_ref ref_convex(size_type cv) const
Return the convex of the reference element.
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 size_type nb_dof(size_type cv) const
Number of degrees of freedom.
pfem new_fem_global_function(const std::vector< pglobal_function > &funcs, const mesh &m)
create a new global function FEM.
pdof_description global_dof(dim_type d)
Description of a global dof, i.e.
Definition: getfem_fem.cc:521
Balanced tree of n-dimensional rectangles.
Definition: bgeot_rtree.h:66
void grad_base_value(const base_node &, base_tensor &) const
Give the value of all gradients (on ref.
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