GetFEM++  5.3
getfem_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 
25 
26 namespace getfem {
27 
28 
29  // Partial implementation of abstract class global_function_simple
30 
31  scalar_type global_function_simple::val
32  (const fem_interpolation_context &c) const {
33  base_node pt = c.xreal();
34  GMM_ASSERT1(pt.size() == dim_, "Point of wrong size (" << pt.size() << ") "
35  << "passed to a global function of dim = "<< dim_ <<".");
36  return this->val(pt);
37  }
38 
39  void global_function_simple::grad
40  (const fem_interpolation_context &c, base_small_vector &g) const {
41  base_node pt = c.xreal();
42  GMM_ASSERT1(pt.size() == dim_, "Point of wrong size (" << pt.size() << ") "
43  << "passed to a global function of dim = "<< dim_ <<".");
44  this->grad(pt, g);
45  }
46 
47  void global_function_simple::hess
48  (const fem_interpolation_context &c, base_matrix &h) const {
49  base_node pt = c.xreal();
50  GMM_ASSERT1(pt.size() == dim_, "Point of wrong size (" << pt.size() << ") "
51  << "passed to a global function of dim = "<< dim_ <<".");
52  this->hess(pt, h);
53  }
54 
55  // Implementation of global_function_parser
56 
57  scalar_type global_function_parser::val(const base_node &pt) const {
58  const bgeot::base_tensor &t = tensor_val(pt);
59  GMM_ASSERT1(t.size() == 1, "Wrong size of expression result "
60  << f_val.expression());
61  return t[0];
62  }
63 
64  const base_tensor &global_function_parser::tensor_val(const base_node &pt) const {
65  gmm::copy(pt, pt_);
66  return f_val.eval();
67  }
68 
69  void global_function_parser::grad(const base_node &pt, base_small_vector &g) const {
70  g.resize(dim_);
71  gmm::copy(pt, pt_);
72  const bgeot::base_tensor &t = f_grad.eval();
73  GMM_ASSERT1(t.size() == dim_, "Wrong size of expression result "
74  << f_grad.expression());
75  gmm::copy(t.as_vector(), g);
76 
77  }
78 
79  void global_function_parser::hess(const base_node &pt, base_matrix &h) const {
80  h.resize(dim_, dim_);
81  gmm::copy(pt, pt_);
82  const bgeot::base_tensor &t = f_hess.eval();
83  GMM_ASSERT1(t.size() == size_type(dim_*dim_),
84  "Wrong size of expression result " << f_hess.expression());
85  gmm::copy(t.as_vector(), h.as_vector());
86  }
87 
88  global_function_parser::global_function_parser(dim_type dim__,
89  const std::string &sval,
90  const std::string &sgrad,
91  const std::string &shess)
92  : global_function_simple(dim__),
93  f_val(gw, sval), f_grad(gw, sgrad), f_hess(gw, shess) {
94 
95  size_type N(dim_);
96  pt_.resize(N);
97  gmm::fill(pt_, scalar_type(0));
98  gw.add_fixed_size_variable("X", gmm::sub_interval(0, N), pt_);
99  if (N >= 1) gw.add_macro("x", "X(1)");
100  if (N >= 2) gw.add_macro("y", "X(2)");
101  if (N >= 3) gw.add_macro("z", "X(3)");
102  if (N >= 4) gw.add_macro("w", "X(4)");
103 
104  f_val.compile();
105  f_grad.compile();
106  f_hess.compile();
107  }
108 
109  // Implementation of global_function_sum
110 
111  scalar_type global_function_sum::val
112  (const fem_interpolation_context &c) const {
113  scalar_type res(0);
114  for (const auto &f : functions)
115  res += f->val(c);
116  return res;
117  }
118 
119  void global_function_sum::grad
120  (const fem_interpolation_context &c, base_small_vector &g) const {
121  g.resize(dim_);
122  gmm::clear(g);
123  base_small_vector gg(dim_);
124  for (const auto &f : functions) {
125  f->grad(c, gg);
126  gmm::add(gg, g);
127  }
128  }
129 
130  void global_function_sum::hess
131  (const fem_interpolation_context &c, base_matrix &h) const {
132  h.resize(dim_, dim_);
133  gmm::clear(h);
134  base_matrix hh(dim_, dim_);
135  for (const auto &f : functions) {
136  f->hess(c, hh);
137  gmm::add(hh.as_vector(), h.as_vector());
138  }
139  }
140 
141  bool global_function_sum::is_in_support(const base_node &p) const {
142  for (const auto &f : functions)
143  if (f->is_in_support(p)) return true;
144  return false;
145  }
146 
147  void global_function_sum::bounding_box
148  (base_node &bmin_, base_node &bmax_) const {
149  if (functions.size() > 0)
150  functions[0]->bounding_box(bmin_, bmax_);
151  base_node bmin0(dim()), bmax0(dim());
152  for (const auto &f : functions) {
153  f->bounding_box(bmin0, bmax0);
154  for (size_type i=0; i < dim(); ++i) {
155  if (bmin0[i] < bmin_[i]) bmin_[i] = bmin0[i];
156  if (bmax0[i] > bmax_[i]) bmax_[i] = bmax0[i];
157  }
158  }
159  }
160 
161  global_function_sum::global_function_sum(const std::vector<pglobal_function> &funcs)
162  : global_function((funcs.size() > 0) ? funcs[0]->dim() : 0), functions(funcs) {
163  for (const auto &f : functions)
164  GMM_ASSERT1(f->dim() == dim(), "Incompatible dimensions among the provided"
165  " global functions");
166  }
167 
168  global_function_sum::global_function_sum(pglobal_function f1, pglobal_function f2)
169  : global_function(f1->dim()), functions(2) {
170  functions[0] = f1;
171  functions[1] = f2;
172  GMM_ASSERT1(f1->dim() == dim() && f2->dim() == dim(),
173  "Incompatible dimensions between the provided global functions");
174  }
175 
176  global_function_sum::global_function_sum(pglobal_function f1, pglobal_function f2,
177  pglobal_function f3)
178  : global_function(f1->dim()), functions(3) {
179  functions[0] = f1;
180  functions[1] = f2;
181  functions[2] = f3;
182  GMM_ASSERT1(f1->dim() == dim() && f2->dim() == dim() && f3->dim() == dim(),
183  "Incompatible dimensions between the provided global functions");
184  }
185 
186  global_function_sum::global_function_sum(pglobal_function f1, pglobal_function f2,
187  pglobal_function f3, pglobal_function f4)
188  : global_function(f1->dim()), functions(4) {
189  functions[0] = f1;
190  functions[1] = f2;
191  functions[2] = f3;
192  functions[3] = f4;
193  GMM_ASSERT1(f1->dim() == dim() && f2->dim() == dim() && f3->dim() == dim(),
194  "Incompatible dimensions between the provided global functions");
195  }
196 
197 
198  // Implementation of global_function_product
199 
200  scalar_type global_function_product::val
201  (const fem_interpolation_context &c) const {
202  return f1->val(c) * f2->val(c);
203  }
204 
205  void global_function_product::grad
206  (const fem_interpolation_context &c, base_small_vector &g) const {
207  g.resize(dim_);
208  base_small_vector gg(dim_);
209  f1->grad(c, gg);
210  gmm::copy(gmm::scaled(gg, f2->val(c)), g);
211  f2->grad(c, gg);
212  gmm::add(gmm::scaled(gg, f1->val(c)), g);
213  }
214 
215  void global_function_product::hess
216  (const fem_interpolation_context &c, base_matrix &h) const {
217  h.resize(dim_, dim_);
218  gmm::clear(h);
219  base_matrix hh(dim_, dim_);
220  f1->hess(c, hh);
221  gmm::copy(gmm::scaled(hh, f2->val(c)), h);
222  f2->hess(c, hh);
223  gmm::add(gmm::scaled(hh, f1->val(c)), h);
224  base_small_vector g1(dim_), g2(dim_);
225  f1->grad(c, g1);
226  f2->grad(c, g2);
227  gmm::rank_one_update(h, g1, g2);
228  gmm::rank_one_update(h, g2, g1);
229  }
230 
231  bool global_function_product::is_in_support(const base_node &p) const {
232  return f1->is_in_support(p) && f2->is_in_support(p);
233  }
234 
235  void global_function_product::bounding_box
236  (base_node &bmin_, base_node &bmax_) const {
237  base_node bmin0(dim()), bmax0(dim());
238  f1->bounding_box(bmin0, bmax0);
239  f2->bounding_box(bmin_, bmax_);
240  for (size_type i=0; i < dim(); ++i) {
241  if (bmin0[i] > bmin_[i]) bmin_[i] = bmin0[i];
242  if (bmax0[i] < bmax_[i]) bmax_[i] = bmax0[i];
243  if (bmin_[i] > bmax_[i])
244  GMM_WARNING1("Global function product with vanishing basis function");
245  }
246  }
247 
248  global_function_product::global_function_product(pglobal_function f1_, pglobal_function f2_)
249  : global_function(f1_->dim()), f1(f1_), f2(f2_) {
250  GMM_ASSERT1(f2->dim() == dim(), "Incompatible dimensions between the provided"
251  " global functions");
252  }
253 
254 
255  // Implementation of global_function_bounded
256 
257  bool global_function_bounded::is_in_support(const base_node &pt) const {
258  if (has_expr) {
259  gmm::copy(pt, pt_);
260  const bgeot::base_tensor &t = f_val.eval();
261  GMM_ASSERT1(t.size() == 1, "Wrong size of expression result "
262  << f_val.expression());
263  return (t[0] > scalar_type(0));
264  }
265  return true;
266  }
267 
268  global_function_bounded::global_function_bounded(pglobal_function f_,
269  const base_node &bmin_,
270  const base_node &bmax_,
271  const std::string &is_in_expr)
272  : global_function(f_->dim()), f(f_), bmin(bmin_), bmax(bmax_),
273  f_val(gw, is_in_expr) {
274 
275  has_expr = !is_in_expr.empty();
276  if (has_expr) {
277  size_type N(dim_);
278  pt_.resize(N);
279  gmm::fill(pt_, scalar_type(0));
280  gw.add_fixed_size_variable("X", gmm::sub_interval(0, N), pt_);
281  if (N >= 1) gw.add_macro("x", "X(1)");
282  if (N >= 2) gw.add_macro("y", "X(2)");
283  if (N >= 3) gw.add_macro("z", "X(3)");
284  if (N >= 4) gw.add_macro("w", "X(4)");
285  f_val.compile();
286  }
287  }
288 
289  // Implementation of some useful xy functions
290 
291  parser_xy_function::parser_xy_function(const std::string &sval,
292  const std::string &sgrad,
293  const std::string &shess)
294  : f_val(gw, sval), f_grad(gw, sgrad), f_hess(gw, shess),
295  ptx(1), pty(1), ptr(1), ptt(1) {
296 
297  gw.add_fixed_size_constant("x", ptx);
298  gw.add_fixed_size_constant("y", pty);
299  gw.add_fixed_size_constant("r", ptr);
300  gw.add_fixed_size_constant("theta", ptt);
301 
302  f_val.compile();
303  f_grad.compile();
304  f_hess.compile();
305  }
306 
307  scalar_type
308  parser_xy_function::val(scalar_type x, scalar_type y) const {
309  ptx[0] = double(x); // x
310  pty[0] = double(y); // y
311  ptr[0] = double(sqrt(fabs(x*x+y*y))); // r
312  ptt[0] = double(atan2(y,x)); // theta
313 
314  const bgeot::base_tensor &t = f_val.eval();
315  GMM_ASSERT1(t.size() == 1, "Wrong size of expression result "
316  << f_val.expression());
317  return t[0];
318  }
319 
320  base_small_vector
321  parser_xy_function::grad(scalar_type x, scalar_type y) const {
322  ptx[0] = double(x); // x
323  pty[0] = double(y); // y
324  ptr[0] = double(sqrt(fabs(x*x+y*y))); // r
325  ptt[0] = double(atan2(y,x)); // theta
326 
327  base_small_vector res(2);
328  const bgeot::base_tensor &t = f_grad.eval();
329  GMM_ASSERT1(t.size() == 2, "Wrong size of expression result "
330  << f_grad.expression());
331  gmm::copy(t.as_vector(), res);
332  return res;
333  }
334 
335  base_matrix
336  parser_xy_function::hess(scalar_type x, scalar_type y) const {
337  ptx[0] = double(x); // x
338  pty[0] = double(y); // y
339  ptr[0] = double(sqrt(fabs(x*x+y*y))); // r
340  ptt[0] = double(atan2(y,x)); // theta
341 
342  base_matrix res(2,2);
343  const bgeot::base_tensor &t = f_hess.eval();
344  GMM_ASSERT1(t.size() == 4, "Wrong size of expression result "
345  << f_hess.expression());
346  gmm::copy(t.as_vector(), res.as_vector());
347  return res;
348  }
349 
350  /* the basic singular functions for 2D cracks */
351  scalar_type
352  crack_singular_xy_function::val(scalar_type x, scalar_type y) const {
353  scalar_type sgny = (y < 0 ? -1.0 : 1.0);
354  scalar_type r = sqrt(x*x + y*y);
355  if (r < 1e-10) return 0;
356 
357  /* The absolute value is unfortunately necessary, otherwise, sqrt(-1e-16)
358  can be required ...
359  */
360  scalar_type sin2 = sqrt(gmm::abs(.5-x/(2*r))) * sgny;
361  scalar_type cos2 = sqrt(gmm::abs(.5+x/(2*r)));
362 
363  scalar_type res = 0;
364  switch(l){
365 
366  /* First order enrichement displacement field (linear elasticity) */
367 
368  case 0 : res = sqrt(r)*sin2; break;
369  case 1 : res = sqrt(r)*cos2; break;
370  case 2 : res = sin2*y/sqrt(r); break;
371  case 3 : res = cos2*y/sqrt(r); break;
372 
373  /* Second order enrichement of displacement field (linear elasticity) */
374 
375  case 4 : res = sqrt(r)*r*sin2; break;
376  case 5 : res = sqrt(r)*r*cos2; break;
377  case 6 : res = sin2*cos2*cos2*r*sqrt(r); break;
378  case 7 : res = cos2*cos2*cos2*r*sqrt(r); break;
379 
380  /* First order enrichement of pressure field (linear elasticity) mixed formulation */
381 
382  case 8 : res = -sin2/sqrt(r); break;
383  case 9 : res = cos2/sqrt(r); break;
384 
385  /* Second order enrichement of pressure field (linear elasticity) mixed formulation */
386 
387  case 10 : res = sin2*sqrt(r); break; // cos2*cos2
388  case 11 : res = cos2*sqrt(r); break;
389 
390  /* First order enrichement of displacement field (nonlinear elasticity)[Rodney Stephenson Journal of elasticity VOL.12 No. 1, January 1982] */
391 
392  case 12 : res = r*sin2*sin2; break;
393  case 13 : res = sqrt(r)*sin2; break;
394 
395 /* First order enrichement of pressure field (nonlinear elasticity) */
396 
397  case 14 : res = sin2/r; break;
398  case 15 : res = cos2/r; break;
399 
400  default: GMM_ASSERT2(false, "arg");
401  }
402  return res;
403  }
404 
405 
406  base_small_vector
407  crack_singular_xy_function::grad(scalar_type x, scalar_type y) const {
408  scalar_type sgny = (y < 0 ? -1.0 : 1.0);
409  scalar_type r = sqrt(x*x + y*y);
410 
411  if (r < 1e-10) {
412  GMM_WARNING0("Warning, point close to the singularity (r=" << r << ")");
413  }
414 
415  /* The absolute value is unfortunately necessary, otherwise, sqrt(-1e-16)
416  can be required ...
417  */
418  scalar_type sin2 = sqrt(gmm::abs(.5-x/(2*r))) * sgny;
419  scalar_type cos2 = sqrt(gmm::abs(.5+x/(2*r)));
420 
421  base_small_vector res(2);
422  switch(l){
423  /* First order enrichement displacement field (linear elasticity) */
424  case 0 :
425  res[0] = -sin2/(2*sqrt(r));
426  res[1] = cos2/(2*sqrt(r));
427  break;
428  case 1 :
429  res[0] = cos2/(2*sqrt(r));
430  res[1] = sin2/(2*sqrt(r));
431  break;
432  case 2 :
433  res[0] = cos2*((-5*cos2*cos2) + 1. + 4*(cos2*cos2*cos2*cos2))/sqrt(r);
434  res[1] = sin2*((-3*cos2*cos2) + 1. + 4*(cos2*cos2*cos2*cos2))/sqrt(r);
435  break;
436  case 3 :
437  res[0] = -cos2*cos2*sin2*((4*cos2*cos2) - 3.)/sqrt(r);
438  res[1] = cos2*((4*cos2*cos2*cos2*cos2) + 2. - (5*cos2*cos2))/sqrt(r);
439  break;
440  /* Second order enrichement of displacement field (linear elasticity) */
441 
442  case 4 :
443  res[0] = sin2 *((4*cos2*cos2)-3.)*sqrt(r)/2.;
444  res[1] = cos2*(5. - (4*cos2*cos2))*sqrt(r)/2. ;
445  break;
446  case 5 :
447  res[0] = cos2*((4*cos2*cos2)-1.)*sqrt(r)/2.;
448  res[1] = sin2*((4*cos2*cos2)+1.)*sqrt(r)/2. ;
449  break;
450 
451  case 6 :
452  res[0] = sin2*cos2*cos2*sqrt(r)/2.;
453  res[1] = cos2*(2. - (cos2*cos2))*sqrt(r)/2.;
454  break;
455  case 7 :
456  res[0] = 3*cos2*cos2*cos2*sqrt(r)/2.;
457  res[1] = 3*sin2*cos2*cos2*sqrt(r)/2.;
458  break;
459 
460  /* First order enrichement of pressure field (linear elasticity) mixed formulation */
461 
462  case 8 :
463  res[0] =sin2*((4*cos2*cos2)-1.)/(2*sqrt(r)*r);
464  res[1] =-cos2*((4*cos2*cos2)-3.)/(2*sqrt(r)*r);
465  break;
466  case 9 :
467  res[0] =-cos2*((2*cos2*cos2) - 3.)/(2*sqrt(r)*r);
468  res[1] =-sin2*((4*cos2*cos2)-1.)/(2*sqrt(r)*r);
469  break;
470 
471  /* Second order enrichement of pressure field (linear elasticity) mixed formulation */
472  case 10 :
473  res[0] = -sin2/(2*sqrt(r));
474  res[1] = cos2/(2*sqrt(r));
475  break;
476  case 11 :
477  res[0] = cos2/(2*sqrt(r));
478  res[1] = sin2/(2*sqrt(r));
479  break;
480 
481  /* First order enrichement of displacement field (nonlinear elasticity)[Rodney Stephenson Journal of elasticity VOL.12 No. 1, January 1982] */
482 
483  case 12 :
484  res[0] = sin2*sin2;
485  res[1] = 0.5*cos2*sin2;
486  break;
487  case 13 :
488  res[0] = -sin2/(2*sqrt(r));
489  res[1] = cos2/(2*sqrt(r));
490  break;
491 
492 /* First order enrichement of pressure field (****Nonlinear elasticity*****) */
493 
494 
495  case 14 :
496  res[0] = -sin2/r;
497  res[1] = cos2/(2*r);
498  break;
499  case 15 :
500  res[0] = -cos2/r;
501  res[1] = -sin2/(2*r);
502  break;
503 
504 
505  default: GMM_ASSERT2(false, "oups");
506  }
507  return res;
508  }
509 
510  base_matrix crack_singular_xy_function::hess(scalar_type x, scalar_type y) const {
511  scalar_type sgny = (y < 0 ? -1.0 : 1.0);
512  scalar_type r = sqrt(x*x + y*y);
513 
514  if (r < 1e-10) {
515  GMM_WARNING0("Warning, point close to the singularity (r=" << r << ")");
516  }
517 
518  /* The absolute value is unfortunately necessary, otherwise, sqrt(-1e-16)
519  can be required ...
520  */
521  scalar_type sin2 = sqrt(gmm::abs(.5-x/(2*r))) * sgny;
522  scalar_type cos2 = sqrt(gmm::abs(.5+x/(2*r)));
523 
524  base_matrix res(2,2);
525  switch(l){
526  case 0 :
527  res(0,0) = (-sin2*x*x + 2.0*cos2*x*y + sin2*y*y) / (4*pow(r, 3.5));
528  res(0,1) = (-cos2*x*x - 2.0*sin2*x*y + cos2*y*y) / (4*pow(r, 3.5));
529  res(1,0) = res(0, 1);
530  res(1,1) = (sin2*x*x - 2.0*cos2*x*y - sin2*y*y) / (4*pow(r, 3.5));
531  break;
532  case 1 :
533  res(0,0) = (-cos2*x*x - 2.0*sin2*x*y + cos2*y*y) / (4*pow(r, 3.5));
534  res(0,1) = (sin2*x*x - 2.0*cos2*x*y - sin2*y*y) / (4*pow(r, 3.5));
535  res(1,0) = res(0, 1);
536  res(1,1) = (cos2*x*x + 2.0*sin2*x*y - cos2*y*y) / (4*pow(r, 3.5));
537  break;
538  case 2 :
539  res(0,0) = 3.0*y*(sin2*x*x + 2.0*cos2*x*y - sin2*y*y) / (4*pow(r, 4.5));
540  res(0,1) = (-2.0*sin2*x*x*x - 5.0*cos2*y*x*x + 4.0*sin2*y*y*x + cos2*y*y*y)
541  / (4*pow(r, 4.5));
542  res(1,0) = res(0, 1);
543  res(1,1) = (4.0*cos2*x*x*x - 7.0*sin2*y*x*x - 2.0*cos2*y*y*x - sin2*y*y*y)
544  / (4*pow(r, 4.5));
545  break;
546  case 3 :
547  res(0,0) = 3.0*y*(cos2*x*x - 2.0*sin2*x*y - cos2*y*y) / (4*pow(r, 4.5));
548  res(0,1) = (-2.0*cos2*x*x*x + 5.0*sin2*y*x*x + 4.0*cos2*y*y*x - sin2*y*y*y)
549  / (4*pow(r, 4.5));
550  res(1,0) = res(0, 1);
551  res(1,1) = (-4.0*sin2*x*x*x - 7.0*cos2*y*x*x + 2.0*sin2*y*y*x - cos2*y*y*y)
552  / (4*pow(r, 4.5));
553  break;
554  default: GMM_ASSERT2(false, "oups");
555  }
556  return res;
557  }
558 
559  scalar_type
560  cutoff_xy_function::val(scalar_type x, scalar_type y) const {
561  scalar_type res = 1;
562  switch (fun) {
563  case EXPONENTIAL_CUTOFF: {
564  res = (a4>0) ? exp(-a4 * gmm::sqr(x*x+y*y)) : 1;
565  break;
566  }
567  case POLYNOMIAL_CUTOFF: {
568  assert(r0 > r1);
569  scalar_type r = gmm::sqrt(x*x+y*y);
570 
571  if (r <= r1) res = 1;
572  else if (r >= r0) res = 0;
573  else {
574  // scalar_type c = 6./(r0*r0*r0 - r1*r1*r1 + 3*r1*r0*(r1-r0));
575  // scalar_type k = -(c/6.)*(-pow(r0,3.) + 3*r1*pow(r0,2.));
576  // res = (c/3.)*pow(r,3.) - (c*(r0 + r1)/2.)*pow(r,2.) +
577  // c*r0*r1*r + k;
578  scalar_type c = 1./pow(r0-r1,3.0);
579  res = c*(r*(r*(2.0*r-3.0*(r0+r1))+6.0*r1*r0) + r0*r0*(r0-3.0*r1));
580  }
581  break;
582  }
583  case POLYNOMIAL2_CUTOFF: {
584  assert(r0 > r1);
585  scalar_type r = gmm::sqrt(x*x+y*y);
586  if (r <= r1) res = scalar_type(1);
587  else if (r >= r0) res = scalar_type(0);
588  else {
589 // scalar_type c = 1./((-1./30.)*(pow(r1,5) - pow(r0,5))
590 // + (1./6.)*(pow(r1,4)*r0 - r1*pow(r0,4))
591 // - (1./3.)*(pow(r1,3)*pow(r0,2) -
592 // pow(r1,2)*pow(r0,3)));
593 // scalar_type k = 1. - c*((-1./30.)*pow(r1,5) +
594 // (1./6.)*pow(r1,4)*r0 -
595 // (1./3.)*pow(r1,3)*pow(r0,2));
596 // res = c*( (-1./5.)*pow(r,5) + (1./2.)* (r1+r0)*pow(r,4) -
597 // (1./3.)*(pow(r1,2)+pow(r0,2) + 4.*r0*r1)*pow(r,3) +
598 // r0*r1*(r0+r1)*pow(r,2) - pow(r0,2)*pow(r1,2)*r) + k;
599  res = (r*(r*(r*(r*(-6.0*r + 15.0*(r0+r1))
600  - 10.0*(r0*r0 + 4.0*r1*r0 + r1*r1))
601  + 30.0 * r0*r1*(r0+r1)) - 30.0*r1*r1*r0*r0)
602  + r0*r0*r0*(r0*r0-5.0*r1*r0+10*r1*r1)) / pow(r0-r1, 5.0);
603  }
604  break;
605  }
606  default : res = 1;
607  }
608  return res;
609  }
610 
611  base_small_vector
612  cutoff_xy_function::grad(scalar_type x, scalar_type y) const {
613  base_small_vector res(2);
614  switch (fun) {
615  case EXPONENTIAL_CUTOFF: {
616  scalar_type r2 = x*x+y*y, ratio = -4.*exp(-a4*r2*r2)*a4*r2;
617  res[0] = ratio*x;
618  res[1] = ratio*y;
619  break;
620  }
621  case POLYNOMIAL_CUTOFF: {
622  scalar_type r = gmm::sqrt(x*x+y*y);
623  scalar_type ratio = 0;
624 
625  if ( r > r1 && r < r0 ) {
626  // scalar_type c = 6./(pow(r0,3.) - pow(r1,3.) + 3*r1*r0*(r1-r0));
627  // ratio = c*(r - r0)*(r - r1);
628  ratio = 6.*(r - r0)*(r - r1)/pow(r0-r1, 3.);
629  }
630  res[0] = ratio*x/r;
631  res[1] = ratio*y/r;
632  break;
633  }
634  case POLYNOMIAL2_CUTOFF: {
635  scalar_type r = gmm::sqrt(x*x+y*y);
636  scalar_type ratio = 0;
637  if (r > r1 && r < r0) {
638 // scalar_type c = 1./((-1./30.)*(pow(r1,5) - pow(r0,5))
639 // + (1./6.)*(pow(r1,4)*r0 - r1*pow(r0,4))
640 // - (1./3.)*(pow(r1,3)*pow(r0,2)
641 // - pow(r1,2)*pow(r0,3)));
642 // ratio = - c*gmm::sqr(r-r0)*gmm::sqr(r-r1);
643  ratio = -30.0*gmm::sqr(r-r0)*gmm::sqr(r-r1) / pow(r0-r1, 5.0);
644  }
645  res[0] = ratio*x/r;
646  res[1] = ratio*y/r;
647  break;
648  }
649  default :
650  res[0] = 0;
651  res[1] = 0;
652  }
653  return res;
654  }
655 
656  base_matrix
657  cutoff_xy_function::hess(scalar_type x, scalar_type y) const {
658  base_matrix res(2,2);
659  switch (fun) {
660  case EXPONENTIAL_CUTOFF: {
661  scalar_type r2 = x*x+y*y, r4 = r2*r2;
662  res(0,0) = 4.0*a4*(-3.0*x*x - y*y + 4.0*a4*x*x*r4)*exp(-a4*r4);
663  res(1,0) = 8.0*a4*x*y*(-1.0 + 2.0*a4*r4)*exp(-a4*r4);
664  res(0,1) = res(1,0);
665  res(1,1) = 4.0*a4*(-3.0*y*y - x*x + 4.0*a4*y*y*r4)*exp(-a4*r4);
666  break;
667  }
668  case POLYNOMIAL_CUTOFF: {
669  scalar_type r2 = x*x+y*y, r = gmm::sqrt(r2), c=6./(pow(r0-r1,3.)*r*r2);
670  if ( r > r1 && r < r0 ) {
671  res(0,0) = c*(x*x*r2 + r1*r0*y*y - r*r2*(r0+r1) + r2*r2);
672  res(1,0) = c*x*y*(r2 - r1*r0);
673  res(0,1) = res(1,0);
674  res(1,1) = c*(y*y*r2 + r1*r0*x*x - r*r2*(r0+r1) + r2*r2);
675  }
676  break;
677  }
678  case POLYNOMIAL2_CUTOFF: {
679  scalar_type r2 = x*x+y*y, r = gmm::sqrt(r2), r3 = r*r2;
680  if (r > r1 && r < r0) {
681  scalar_type dp = -30.0*(r1-r)*(r1-r)*(r0-r)*(r0-r) / pow(r0-r1, 5.0);
682  scalar_type ddp = 60.0*(r1-r)*(r0-r)*(r0+r1-2.0*r) / pow(r0-r1, 5.0);
683  scalar_type rx= x/r, ry= y/r, rxx= y*y/r3, rxy= -x*y/r3, ryy= x*x/r3;
684  res(0,0) = ddp*rx*rx + dp*rxx;
685  res(1,0) = ddp*rx*ry + dp*rxy;
686  res(0,1) = res(1,0);
687  res(1,1) = ddp*ry*ry + dp*ryy;
688  }
689  break;
690  }
691  }
692  return res;
693  }
694 
695  cutoff_xy_function::cutoff_xy_function(int fun_num, scalar_type r,
696  scalar_type r1_, scalar_type r0_)
697  {
698  fun = fun_num;
699  r1 = r1_; r0 = r0_;
700  a4 = 0;
701  if (r > 0) a4 = pow(2.7/r,4.);
702  }
703 
704 
705  struct global_function_on_levelsets_2D_ :
706  public global_function, public context_dependencies {
707  const std::vector<level_set> dummy_lsets;
708  const std::vector<level_set> &lsets;
709  const level_set &ls;
710  mutable pmesher_signed_distance mls_x, mls_y;
711  mutable size_type cv;
712 
713  pxy_function fn;
714 
715  void update_mls(size_type cv_, size_type n) const {
716  if (cv_ != cv) {
717  cv=cv_;
718  if (lsets.size() == 0) {
719  mls_x = ls.mls_of_convex(cv, 1);
720  mls_y = ls.mls_of_convex(cv, 0);
721  } else {
722  base_node pt(n);
723  scalar_type d = scalar_type(-2);
724  for (const auto &ls_ : lsets) {
725  pmesher_signed_distance mls_xx, mls_yy;
726  mls_xx = ls_.mls_of_convex(cv, 1);
727  mls_yy = ls_.mls_of_convex(cv, 0);
728  scalar_type x = (*mls_xx)(pt), y = (*mls_yy)(pt);
729  scalar_type d2 = gmm::sqr(x) + gmm::sqr(y);
730  if (d < scalar_type(-1) || d2 < d) {
731  d = d2;
732  mls_x = mls_xx;
733  mls_y = mls_yy;
734  }
735  }
736  }
737  }
738  }
739 
740  virtual scalar_type val(const fem_interpolation_context& c) const {
741  update_mls(c.convex_num(), c.xref().size());
742  scalar_type x = (*mls_x)(c.xref());
743  scalar_type y = (*mls_y)(c.xref());
744  if (c.xfem_side() > 0 && y <= 1E-13) y = 1E-13;
745  if (c.xfem_side() < 0 && y >= -1E-13) y = -1E-13;
746  return fn->val(x,y);
747  }
748  virtual void grad(const fem_interpolation_context& c,
749  base_small_vector &g) const {
750  size_type P = c.xref().size();
751  base_small_vector dx(P), dy(P), dfr(2);
752 
753  update_mls(c.convex_num(), P);
754  scalar_type x = mls_x->grad(c.xref(), dx);
755  scalar_type y = mls_y->grad(c.xref(), dy);
756  if (c.xfem_side() > 0 && y <= 0) y = 1E-13;
757  if (c.xfem_side() < 0 && y >= 0) y = -1E-13;
758 
759  base_small_vector gfn = fn->grad(x,y);
760  gmm::mult(c.B(), gfn[0]*dx + gfn[1]*dy, g);
761  }
762  virtual void hess(const fem_interpolation_context&c,
763  base_matrix &h) const {
764  size_type P = c.xref().size(), N = c.N();
765  base_small_vector dx(P), dy(P), dfr(2), dx_real(N), dy_real(N);
766 
767  update_mls(c.convex_num(), P);
768  scalar_type x = mls_x->grad(c.xref(), dx);
769  scalar_type y = mls_y->grad(c.xref(), dy);
770  if (c.xfem_side() > 0 && y <= 0) y = 1E-13;
771  if (c.xfem_side() < 0 && y >= 0) y = -1E-13;
772 
773  base_small_vector gfn = fn->grad(x,y);
774  base_matrix hfn = fn->hess(x,y);
775 
776  base_matrix hx, hy, hx_real(N*N, 1), hy_real(N*N, 1);
777  mls_x->hess(c.xref(), hx);
778  mls_x->hess(c.xref(), hy);
779  gmm::reshape(hx, P*P, 1);
780  gmm::reshape(hy, P*P, 1);
781 
782  gmm::mult(c.B3(), hx, hx_real);
783  gmm::mult(c.B32(), gmm::scaled(dx, -1.0), gmm::mat_col(hx_real, 0));
784  gmm::mult(c.B3(), hy, hy_real);
785  gmm::mult(c.B32(), gmm::scaled(dy, -1.0), gmm::mat_col(hy_real, 0));
786  gmm::mult(c.B(), dx, dx_real);
787  gmm::mult(c.B(), dy, dy_real);
788 
789  for (size_type i = 0; i < N; ++i)
790  for (size_type j = 0; j < N; ++j) {
791  h(i, j) = hfn(0,0) * dx_real[i] * dx_real[j]
792  + hfn(0,1) * dx_real[i] * dy_real[j]
793  + hfn(1,0) * dy_real[i] * dx_real[j]
794  + hfn(1,1) * dy_real[i] * dy_real[j]
795  + gfn[0] * hx_real(i * N + j, 0) + gfn[1] * hy_real(i*N+j,0);
796  }
797  }
798 
799  void update_from_context() const { cv = size_type(-1); }
800 
801  global_function_on_levelsets_2D_(const std::vector<level_set> &lsets_,
802  const pxy_function &fn_)
803  : global_function(2), dummy_lsets(0, dummy_level_set()),
804  lsets(lsets_), ls(dummy_level_set()), fn(fn_) {
805  GMM_ASSERT1(lsets.size() > 0, "The list of level sets should"
806  " contain at least one level set.");
807  cv = size_type(-1);
808  for (size_type i = 0; i < lsets.size(); ++i)
809  this->add_dependency(lsets[i]);
810  }
811 
812  global_function_on_levelsets_2D_(const level_set &ls_,
813  const pxy_function &fn_)
814  : global_function(2), dummy_lsets(0, dummy_level_set()),
815  lsets(dummy_lsets), ls(ls_), fn(fn_) {
816  cv = size_type(-1);
817  }
818 
819  };
820 
821  pglobal_function
822  global_function_on_level_sets(const std::vector<level_set> &lsets,
823  const pxy_function &fn) {
824  return std::make_shared<global_function_on_levelsets_2D_>(lsets, fn);
825  }
826 
827  pglobal_function
828  global_function_on_level_set(const level_set &ls,
829  const pxy_function &fn) {
830  return std::make_shared<global_function_on_levelsets_2D_>(ls, fn);
831  }
832 
833  // interpolator on mesh_fem
834 
835  interpolator_on_mesh_fem::interpolator_on_mesh_fem
836  (const mesh_fem &mf_, const std::vector<scalar_type> &U_)
837  : mf(mf_), U(U_) {
838 
839  if (mf.is_reduced()) {
840  gmm::resize(U, mf.nb_basic_dof());
841  gmm::mult(mf.extension_matrix(), U_, U);
842  }
843  base_node bmin, bmax;
844  scalar_type EPS=1E-13;
845  cv_stored = size_type(-1);
846  boxtree.clear();
847  for (dal::bv_visitor cv(mf.convex_index()); !cv.finished(); ++cv) {
848  bounding_box(bmin, bmax, mf.linked_mesh().points_of_convex(cv),
849  mf.linked_mesh().trans_of_convex(cv));
850  for (auto&& val : bmin) val -= EPS;
851  for (auto&& val : bmax) val += EPS;
852  boxtree.add_box(bmin, bmax, cv);
853  }
854  }
855 
856  bool interpolator_on_mesh_fem::find_a_point(const base_node &pt,
857  base_node &ptr,
858  size_type &cv) const {
859  bool gt_invertible;
860  if (cv_stored != size_type(-1) && gic.invert(pt, ptr, gt_invertible)) {
861  cv = cv_stored;
862  if (gt_invertible)
863  return true;
864  }
865 
866  boxtree.find_boxes_at_point(pt, boxlst);
867  for (const auto &box : boxlst) {
869  (mf.linked_mesh().convex(box->id),
870  mf.linked_mesh().trans_of_convex(box->id));
871  cv_stored = box->id;
872  if (gic.invert(pt, ptr, gt_invertible)) {
873  cv = box->id;
874  return true;
875  }
876  }
877  return false;
878  }
879 
880  bool interpolator_on_mesh_fem::eval(const base_node &pt, base_vector &val,
881  base_matrix &grad) const {
882  base_node ptref;
883  size_type cv;
884  base_vector coeff;
885  dim_type q = mf.get_qdim(), N = mf.linked_mesh().dim();
886  if (find_a_point(pt, ptref, cv)) {
887  pfem pf = mf.fem_of_element(cv);
889  mf.linked_mesh().trans_of_convex(cv);
890  base_matrix G;
891  vectors_to_base_matrix(G, mf.linked_mesh().points_of_convex(cv));
892  fem_interpolation_context fic(pgt, pf, ptref, G, cv, short_type(-1));
893  slice_vector_on_basic_dof_of_element(mf, U, cv, coeff);
894  // coeff.resize(mf.nb_basic_dof_of_element(cv));
895  // gmm::copy(gmm::sub_vector
896  // (U,gmm::sub_index(mf.ind_basic_dof_of_element(cv))), coeff);
897  val.resize(q);
898  pf->interpolation(fic, coeff, val, q);
899  grad.resize(q, N);
900  pf->interpolation_grad(fic, coeff, grad, q);
901  return true;
902  } else
903  return false;
904  }
905 }
906 
907 /* end of namespace getfem */
void slice_vector_on_basic_dof_of_element(const mesh_fem &mf, const VEC1 &vec, size_type cv, VEC2 &coeff, size_type qmult1=size_type(-1), size_type qmult2=size_type(-1))
Given a mesh_fem.
Definition of global functions to be used as base or enrichment functions in fem. ...
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
does the inversion of the geometric transformation for a given convex
size_t size_type
used as the common size type in the library
Definition: bgeot_poly.h:49
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 ...
GEneric Tool for Finite Element Methods.
void reshape(M &v, size_type m, size_type n)
*/
Definition: gmm_blas.h:250
std::shared_ptr< const getfem::virtual_fem > pfem
type of pointer on a fem description
Definition: getfem_fem.h:239
void clear(L &l)
clear (fill with zeros) a vector or matrix.
Definition: gmm_blas.h:59
gmm::uint16_type short_type
used as the common short type integer in the library
Definition: bgeot_config.h:79
const mesh & linked_mesh() const
Return a reference to the underlying mesh.
Define level-sets.
void resize(M &v, size_type m, size_type n)
*/
Definition: gmm_blas.h:231
std::shared_ptr< const bgeot::geometric_trans > pgeometric_trans
pointer type for a geometric transformation