GetFEM  5.4.3
getfem_fem.cc
Go to the documentation of this file.
1 /*===========================================================================
2 
3  Copyright (C) 1999-2024 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 
22 /** @file getfem_fem.cc
23  @author Yves Renard <Yves.Renard@insa-lyon.fr>
24  @date December 21, 1999.
25  @brief implementation of various finite elements.
26  */
27 
28 #include "getfem/bgeot_torus.h"
29 #include "getfem/dal_singleton.h"
30 #include "getfem/dal_tree_sorted.h"
31 #include "gmm/gmm_algobase.h"
33 #include "getfem/getfem_fem.h"
35 #include "getfem/getfem_omp.h"
36 #include "getfem/getfem_torus.h"
38 
39 namespace getfem {
40 
42  using bgeot::base_rational_fraction;
43 
44  const base_matrix& fem_interpolation_context::M() const {
45  if (gmm::mat_nrows(M_) == 0) {
46  GMM_ASSERT2(have_pgt() && have_G() && have_pf(), "cannot compute M");
47  M_.resize(pf_->nb_dof(convex_num()), pf_->nb_base(convex_num()));
48  pf_->mat_trans(M_,G(),pgt());
49  }
50  return M_;
51  }
52 
54  GMM_ASSERT3(convex_num_ != size_type(-1), "");
55  return convex_num_;
56  }
57 
58  bool fem_interpolation_context::is_convex_num_valid() const {
59  return convex_num_ != size_type(-1);
60  }
61 
63  GMM_ASSERT3(face_num_ != short_type(-1),
64  "Face number is asked but not defined");
65  return face_num_;
66  }
67 
69  return (face_num_ != short_type(-1));
70  }
71 
72  // Comment regarding fem defined on the real element:
73  // Precomputed values, gradients and hessians of fem defined on the real
74  // element are not dealt with within fem_interpolation_context.
75  // In that case, any precomputations can be performed within the fem
76  // itself, which has to store the corresponding values internally.
77  // The methods real_base_value, real_grad_base_value or real_hess_base_value
78  // of the fem have the possibility to check if the passed ctx has a pfp
79  // and extract the corresponding internally stored results based on
80  // ctx.convex_num(), ctx.pfp()->get_ppoint_tab() and ctx.ii().
81  // In that case, the storage available in ctx.pfp()->c, ctx.pfp()->pc
82  // and ctx.pfp()->hpc is not used.
83 
84 
85  // Specific multiplication for fem_interpolation_context use.
86  static inline void spec_mat_tmult_(const base_tensor &g, const base_matrix &B,
87  base_tensor &t) {
88  size_type P = B.nrows(), N = B.ncols();
89  size_type M = t.adjust_sizes_changing_last(g, P);
90  bgeot::mat_tmult(&(*(g.begin())), &(*(B.begin())), &(*(t.begin())),M,N,P);
91  }
92 
93  void fem_interpolation_context::pfp_base_value(base_tensor& t,
94  const pfem_precomp &pfp__) {
95  const pfem &pf__ = pfp__->get_pfem();
96  GMM_ASSERT1(ii_ != size_type(-1), "Internal error");
97 
98  if (pf__->is_standard())
99  t = pfp__->val(ii());
100  else {
101  if (pf__->is_on_real_element())
102  pf__->real_base_value(*this, t);
103  else {
104  switch(pf__->vectorial_type()) {
105  case virtual_fem::VECTORIAL_NOTRANSFORM_TYPE:
106  t = pfp__->val(ii()); break;
107  case virtual_fem::VECTORIAL_PRIMAL_TYPE:
108  t.mat_transp_reduction(pfp__->val(ii()), K(), 1); break;
109  case virtual_fem::VECTORIAL_DUAL_TYPE:
110  t.mat_transp_reduction(pfp__->val(ii()), B(), 1); break;
111  }
112  if (!(pf__->is_equivalent())) {
113  set_pfp(pfp__);
114  { base_tensor u = t; t.mat_transp_reduction(u, M(), 0); }
115  }
116  }
117  }
118  }
119 
120 
122  bool withM) const {
123  if (pfp_ && ii_ != size_type(-1) && pf_->is_standard())
124  t = pfp_->val(ii());
125  else {
126  if (pf_->is_on_real_element())
127  pf_->real_base_value(*this, t);
128  else {
129  if (pfp_ && ii_ != size_type(-1)) {
130  switch(pf_->vectorial_type()) {
131  case virtual_fem::VECTORIAL_NOTRANSFORM_TYPE:
132  t = pfp_->val(ii()); break;
133  case virtual_fem::VECTORIAL_PRIMAL_TYPE:
134  t.mat_transp_reduction(pfp_->val(ii()), K(), 1); break;
135  case virtual_fem::VECTORIAL_DUAL_TYPE:
136  t.mat_transp_reduction(pfp_->val(ii()), B(), 1); break;
137  }
138  }
139  else {
140  switch(pf_->vectorial_type()) {
141  case virtual_fem::VECTORIAL_NOTRANSFORM_TYPE:
142  pf_->base_value(xref(), t); break;
143  case virtual_fem::VECTORIAL_PRIMAL_TYPE:
144  {
145  base_tensor u; pf_->base_value(xref(), u);
146  t.mat_transp_reduction(u,K(),1);
147  } break;
148  case virtual_fem::VECTORIAL_DUAL_TYPE:
149  {
150  base_tensor u; pf_->base_value(xref(), u);
151  t.mat_transp_reduction(u,B(),1);
152  } break;
153  }
154  }
155  if (withM && !(pf_->is_equivalent()))
156  { base_tensor u = t; t.mat_transp_reduction(u, M(), 0); }
157  }
158  }
159  }
160 
161  void fem_interpolation_context::pfp_grad_base_value
162  (base_tensor& t, const pfem_precomp &pfp__) {
163  const pfem &pf__ = pfp__->get_pfem();
164  GMM_ASSERT1(ii_ != size_type(-1), "Internal error");
165 
166  if (pf__->is_standard()) {
167  // t.mat_transp_reduction(pfp__->grad(ii()), B(), 2);
168  spec_mat_tmult_(pfp__->grad(ii()), B(), t);
169  } else {
170  if (pf__->is_on_real_element())
171  pf__->real_grad_base_value(*this, t);
172  else {
173  switch(pf__->vectorial_type()) {
174  case virtual_fem::VECTORIAL_PRIMAL_TYPE:
175  {
176  base_tensor u;
177  // u.mat_transp_reduction(pfp__->grad(ii()), B(), 2);
178  spec_mat_tmult_(pfp__->grad(ii()), B(), u);
179  t.mat_transp_reduction(u, K(), 1);
180  }
181  break;
182  case virtual_fem::VECTORIAL_DUAL_TYPE:
183  {
184  base_tensor u;
185  // u.mat_transp_reduction(pfp__->grad(ii()), B(), 2);
186  spec_mat_tmult_(pfp__->grad(ii()), B(), u);
187  t.mat_transp_reduction(u, B(), 1);
188  }
189  break;
190  default:
191  // t.mat_transp_reduction(pfp__->grad(ii()), B(), 2);
192  spec_mat_tmult_(pfp__->grad(ii()), B(), t);
193  }
194  if (!(pf__->is_equivalent())) {
195  set_pfp(pfp__);
196  base_tensor u = t; t.mat_transp_reduction(u, M(), 0);
197  }
198  }
199  }
200  }
201 
202 
204  bool withM) const {
205  if (pfp_ && ii_ != size_type(-1) && pf_->is_standard()) {
206  // t.mat_transp_reduction(pfp_->grad(ii()), B(), 2);
207  spec_mat_tmult_(pfp_->grad(ii()), B(), t);
208  } else {
209  if (pf()->is_on_real_element())
210  pf()->real_grad_base_value(*this, t);
211  else {
212  if (have_pfp() && ii() != size_type(-1)) {
213  switch(pf()->vectorial_type()) {
214  case virtual_fem::VECTORIAL_PRIMAL_TYPE:
215  {
216  base_tensor u;
217  // u.mat_transp_reduction(pfp_->grad(ii()), B(), 2);
218  spec_mat_tmult_(pfp_->grad(ii()), B(), u);
219  t.mat_transp_reduction(u, K(), 1);
220  }
221  break;
222  case virtual_fem::VECTORIAL_DUAL_TYPE:
223  {
224  base_tensor u;
225  // u.mat_transp_reduction(pfp_->grad(ii()), B(), 2);
226  spec_mat_tmult_(pfp_->grad(ii()), B(), u);
227  t.mat_transp_reduction(u, B(), 1);
228  }
229  break;
230  default:
231  // t.mat_transp_reduction(pfp_->grad(ii()), B(), 2);
232  spec_mat_tmult_(pfp_->grad(ii()), B(), t);
233  }
234 
235  } else {
236  base_tensor u;
237  pf()->grad_base_value(xref(), u);
238  if (u.size()) { /* only if the FEM can provide grad_base_value */
239  // t.mat_transp_reduction(u, B(), 2);
240  spec_mat_tmult_(u, B(), t);
241  switch(pf()->vectorial_type()) {
242  case virtual_fem::VECTORIAL_PRIMAL_TYPE:
243  u = t; t.mat_transp_reduction(u, K(), 1); break;
244  case virtual_fem::VECTORIAL_DUAL_TYPE:
245  u = t; t.mat_transp_reduction(u, B(), 1); break;
246  default: break;
247  }
248  }
249  }
250  if (withM && !(pf()->is_equivalent()))
251  { base_tensor u = t; t.mat_transp_reduction(u, M(), 0); }
252  }
253  }
254  }
255 
257  bool withM) const {
258  if (pf()->is_on_real_element())
259  pf()->real_hess_base_value(*this, t);
260  else {
261  base_tensor tt;
262  if (have_pfp() && ii() != size_type(-1))
263  tt = pfp()->hess(ii());
264  else
265  pf()->hess_base_value(xref(), tt);
266 
267  switch(pf()->vectorial_type()) {
268  case virtual_fem::VECTORIAL_PRIMAL_TYPE:
269  { base_tensor u = tt; tt.mat_transp_reduction(u, K(), 1); } break;
270  case virtual_fem::VECTORIAL_DUAL_TYPE:
271  { base_tensor u = tt; tt.mat_transp_reduction(u, B(), 1); } break;
272  default: break;
273  }
274 
275  if (tt.size()) { /* only if the FEM can provide hess_base_value */
276  tt.adjust_sizes(tt.sizes()[0], tt.sizes()[1], gmm::sqr(tt.sizes()[2]));
277  t.mat_transp_reduction(tt, B3(), 2);
278  if (!pgt()->is_linear()) {
279  if (have_pfp()) {
280  tt.mat_transp_reduction(pfp()->grad(ii()), B32(), 2);
281  } else {
282  base_tensor u;
283  pf()->grad_base_value(xref(), u);
284  tt.mat_transp_reduction(u, B32(), 2);
285  }
286  t -= tt;
287  }
288  if (!(pf()->is_equivalent()) && withM)
289  { tt = t; t.mat_transp_reduction(tt, M(), 0); }
290  }
291  }
292  }
293 
294  void fem_interpolation_context::set_pfp(pfem_precomp newpfp) {
295  if (pfp_ != newpfp) {
296  pfp_ = newpfp;
297  if (pfp_) { pf_ = pfp()->get_pfem(); }
298  else pf_ = 0;
299  M_.resize(0,0);
300  }
301  }
302 
303  void fem_interpolation_context::set_pf(pfem newpf) {
304  if (pf_ != newpf || have_pfp()) {
305  set_pfp(0);
306  pf_ = newpf;
307  }
308  }
309 
311  base_tensor &t, bool withM) const
312  { c.base_value(t, withM); }
313 
315  base_tensor &t, bool withM) const
316  { c.grad_base_value(t, withM);}
317 
319  base_tensor &t, bool withM) const
320  { c.hess_base_value(t, withM); }
321 
322  /* ******************************************************************** */
323  /* Class for description of an interpolation dof. */
324  /* ******************************************************************** */
325 
326  enum ddl_type { LAGRANGE, NORMAL_DERIVATIVE, DERIVATIVE, MEAN_VALUE,
327  BUBBLE1, LAGRANGE_NONCONFORMING, GLOBAL_DOF,
328  SECOND_DERIVATIVE, NORMAL_COMPONENT, EDGE_COMPONENT,
329  IPK_CENTER};
330 
331  struct ddl_elem {
332  ddl_type t;
333  gmm::int16_type hier_degree;
334  short_type hier_raff;
335  size_type spec;
336  bool operator < (const ddl_elem &l) const {
337  if (t < l.t) return true;
338  if (t > l.t) return false;
339  if (hier_degree < l.hier_degree) return true;
340  if (hier_degree > l.hier_degree) return false;
341  if (hier_raff < l.hier_raff) return true;
342  if (hier_raff > l.hier_raff) return false;
343  if (spec < l.spec) return true;
344  return false;
345  }
346  ddl_elem(ddl_type s = LAGRANGE, gmm::int16_type k = -1, short_type l = 0,
347  size_type spec_ = 0)
348  : t(s), hier_degree(k), hier_raff(l), spec(spec_) {}
349  };
350 
351  struct dof_description {
352  std::vector<ddl_elem> ddl_desc;
353  bool linkable;
354  dim_type coord_index;
355  size_type xfem_index;
356  bool all_faces;
357 
358  dof_description()
359  { linkable = true; all_faces = false; coord_index = 0; xfem_index = 0; }
360  };
361 
362  struct dof_description_comp__ {
363  int operator()(const dof_description &m, const dof_description &n) const;
364  };
365 
366  // ATTENTION : en cas de modif, changer aussi dof_description_compare,
367  // product_dof, et dof_hierarchical_compatibility.
368  int dof_description_comp__::operator()(const dof_description &m,
369  const dof_description &n) const {
370  int nn = gmm::lexicographical_less<std::vector<ddl_elem> >()
371  (m.ddl_desc, n.ddl_desc);
372  if (nn < 0) return -1;
373  if (nn > 0) return 1;
374  nn = int(m.linkable) - int(n.linkable);
375  if (nn < 0) return -1;
376  if (nn > 0) return 1;
377  nn = int(m.coord_index) - int(n.coord_index);
378  if (nn < 0) return -1;
379  if (nn > 0) return 1;
380  nn = int(m.xfem_index) - int(n.xfem_index);
381  if (nn < 0) return -1;
382  if (nn > 0) return 1;
383  nn = int(m.all_faces) - int(n.all_faces);
384  if (nn < 0) return -1;
385  if (nn > 0) return 1;
386  return 0;
387  }
388 
389  typedef dal::dynamic_tree_sorted<dof_description, dof_description_comp__> dof_d_tab;
390 
392  THREAD_SAFE_STATIC dim_type n_old = dim_type(-2);
393  THREAD_SAFE_STATIC pdof_description p_old = nullptr;
394  if (n != n_old) {
395  dof_d_tab& tab = dal::singleton<dof_d_tab>::instance();
396  dof_description l;
397  l.ddl_desc.resize(n);
398  std::fill(l.ddl_desc.begin(), l.ddl_desc.end(), ddl_elem(LAGRANGE));
399  p_old = &(tab[tab.add_norepeat(l)]);
400  n_old = n;
401  }
402  return p_old;
403  }
404 
405  pdof_description lagrange_0_dof(dim_type n) {
406  THREAD_SAFE_STATIC dim_type n_old = dim_type(-2);
407  THREAD_SAFE_STATIC pdof_description p_old = nullptr;
408  if (n != n_old) {
409  dof_d_tab& tab = dal::singleton<dof_d_tab>::instance();
410  dof_description l;
411  l.all_faces = true;
412  l.ddl_desc.resize(n);
413  l.linkable = false;
414  std::fill(l.ddl_desc.begin(), l.ddl_desc.end(), ddl_elem(LAGRANGE));
415  p_old = &(tab[tab.add_norepeat(l)]);
416  n_old = n;
417  }
418  return p_old;
419  }
420 
421  pdof_description deg_hierarchical_dof(pdof_description p, int deg) {
422  dof_d_tab& tab = dal::singleton<dof_d_tab>::instance();
423  dof_description l = *p;
424  for (size_type i = 0; i < l.ddl_desc.size(); ++i)
425  l.ddl_desc[i].hier_degree = gmm::int16_type(deg);
426  return &(tab[tab.add_norepeat(l)]);
427  }
428 
429  size_type reserve_xfem_index() {
430  static size_type ind = 100;
431  return ind += 1000;
432  }
433 
435  dof_d_tab& tab = dal::singleton<dof_d_tab>::instance();
436  dof_description l = *p; l.xfem_index = ind;
437  return &(tab[tab.add_norepeat(l)]);
438  }
439 
440  pdof_description ipk_center_dof(dim_type n, size_type k_ind) {
441  THREAD_SAFE_STATIC dim_type n_old = dim_type(-2);
442  THREAD_SAFE_STATIC pdof_description p_old = nullptr;
443  if (n != n_old) {
444  dof_d_tab& tab = dal::singleton<dof_d_tab>::instance();
445  dof_description l;
446  l.ddl_desc.resize(n);
447  std::fill(l.ddl_desc.begin(), l.ddl_desc.end(),
448  ddl_elem(IPK_CENTER, -1, 0, k_ind));
449  p_old = &(tab[tab.add_norepeat(l)]);
450  n_old = n;
451  }
452  return p_old;
453  }
454 
455 
456 
457  pdof_description to_coord_dof(pdof_description p, dim_type ct) {
458  dof_d_tab& tab = dal::singleton<dof_d_tab>::instance();
459  dof_description l = *p;
460  l.coord_index = ct;
461  return &(tab[tab.add_norepeat(l)]);
462  }
463 
464  pdof_description raff_hierarchical_dof(pdof_description p, short_type deg) {
465  dof_d_tab& tab = dal::singleton<dof_d_tab>::instance();
466  dof_description l = *p;
467  for (size_type i = 0; i < l.ddl_desc.size(); ++i)
468  l.ddl_desc[i].hier_raff = deg;
469  return &(tab[tab.add_norepeat(l)]);
470  }
471 
472  pdof_description lagrange_nonconforming_dof(dim_type n) {
473  dof_d_tab& tab = dal::singleton<dof_d_tab>::instance();
474  dof_description l; l.linkable = false;
475  l.ddl_desc.resize(n);
476  std::fill(l.ddl_desc.begin(), l.ddl_desc.end(), ddl_elem(LAGRANGE));
477  return &(tab[tab.add_norepeat(l)]);
478  }
479 
480  pdof_description bubble1_dof(dim_type n) {
481  dof_d_tab& tab = dal::singleton<dof_d_tab>::instance();
482  dof_description l;
483  l.ddl_desc.resize(n);
484  std::fill(l.ddl_desc.begin(), l.ddl_desc.end(), ddl_elem(BUBBLE1));
485  return &(tab[tab.add_norepeat(l)]);
486  }
487 
488  pdof_description derivative_dof(dim_type n, dim_type num_der) {
489  dof_d_tab& tab = dal::singleton<dof_d_tab>::instance();
490  dof_description l;
491  l.ddl_desc.resize(n);
492  std::fill(l.ddl_desc.begin(), l.ddl_desc.end(), ddl_elem(LAGRANGE));
493  l.ddl_desc.at(num_der) = ddl_elem(DERIVATIVE);
494  return &(tab[tab.add_norepeat(l)]);
495  }
496 
497  pdof_description second_derivative_dof(dim_type n, dim_type num_der1,
498  dim_type num_der2) {
499  dof_d_tab& tab = dal::singleton<dof_d_tab>::instance();
500  dof_description l;
501  l.ddl_desc.resize(n);
502  std::fill(l.ddl_desc.begin(), l.ddl_desc.end(), ddl_elem(LAGRANGE));
503  l.ddl_desc[num_der1] = ddl_elem(SECOND_DERIVATIVE);
504  l.ddl_desc[num_der2] = ddl_elem(SECOND_DERIVATIVE);
505  return &(tab[tab.add_norepeat(l)]);
506  }
507 
509  dof_d_tab& tab = dal::singleton<dof_d_tab>::instance();
510  dof_description l;
511  l.ddl_desc.resize(n);
512  std::fill(l.ddl_desc.begin(), l.ddl_desc.end(),
513  ddl_elem(NORMAL_DERIVATIVE));
514  return &(tab[tab.add_norepeat(l)]);
515  }
516 
517  pdof_description normal_component_dof(dim_type n) {
518  dof_d_tab& tab = dal::singleton<dof_d_tab>::instance();
519  dof_description l;
520  l.ddl_desc.resize(n);
521  std::fill(l.ddl_desc.begin(), l.ddl_desc.end(),
522  ddl_elem(NORMAL_COMPONENT));
523  return &(tab[tab.add_norepeat(l)]);
524  }
525 
526  pdof_description edge_component_dof(dim_type n) {
527  dof_d_tab& tab = dal::singleton<dof_d_tab>::instance();
528  dof_description l;
529  l.ddl_desc.resize(n);
530  std::fill(l.ddl_desc.begin(), l.ddl_desc.end(),
531  ddl_elem(EDGE_COMPONENT));
532  return &(tab[tab.add_norepeat(l)]);
533  }
534 
536  dof_d_tab& tab = dal::singleton<dof_d_tab>::instance();
537  dof_description l;
538  l.ddl_desc.resize(n);
539  std::fill(l.ddl_desc.begin(), l.ddl_desc.end(), ddl_elem(MEAN_VALUE));
540  return &(tab[tab.add_norepeat(l)]);
541  }
542 
544  dof_d_tab& tab = dal::singleton<dof_d_tab>::instance();
545  dof_description l;
546  l.all_faces = true;
547  l.ddl_desc.resize(n);
548  l.linkable = false;
549  std::fill(l.ddl_desc.begin(), l.ddl_desc.end(),ddl_elem(GLOBAL_DOF));
550  return &(tab[tab.add_norepeat(l)]);
551  }
552 
554  dof_d_tab& tab = dal::singleton<dof_d_tab>::instance();
555  size_type nb1 = a->ddl_desc.size(), nb2 = b->ddl_desc.size();
556  dof_description l;
557  l.linkable = a->linkable && b->linkable;
558  l.coord_index = std::max(a->coord_index, b->coord_index); // logique ?
559  l.xfem_index = a->xfem_index;
560  l.all_faces = a->all_faces || b->all_faces;
561  GMM_ASSERT2(a->xfem_index == b->xfem_index, "Invalid product of dof");
562  l.ddl_desc.resize(nb1+nb2);
563  std::copy(a->ddl_desc.begin(), a->ddl_desc.end(), l.ddl_desc.begin());
564  std::copy(b->ddl_desc.begin(), b->ddl_desc.end(), l.ddl_desc.begin()+nb1);
565 
566  {
567  gmm::int16_type deg = -1;
568  for (size_type i = 0; i < l.ddl_desc.size(); ++i)
569  deg = std::max(deg, l.ddl_desc[i].hier_degree);
570  for (size_type i = 0; i < l.ddl_desc.size(); ++i)
571  l.ddl_desc[i].hier_degree = deg;
572  }
573  {
574  short_type deg = 0;
575  for (size_type i = 0; i < l.ddl_desc.size(); ++i)
576  deg = std::max(deg, l.ddl_desc[i].hier_raff);
577  for (size_type i = 0; i < l.ddl_desc.size(); ++i)
578  l.ddl_desc[i].hier_raff = deg;
579  }
580  return &(tab[tab.add_norepeat(l)]);
581  }
582 
583  // ATTENTION : en cas de modif, changer aussi
584  // dof_description_comp__::operator,
585  // product_dof, et dof_hierarchical_compatibility.
586  // et dof_description_compare
587  int dof_weak_compatibility(pdof_description a, pdof_description b) {
588  int nn;
589  std::vector<ddl_elem>::const_iterator
590  ita = a->ddl_desc.begin(), itae = a->ddl_desc.end(),
591  itb = b->ddl_desc.begin(), itbe = b->ddl_desc.end();
592  for (; ita != itae && itb != itbe; ++ita, ++itb)
593  {
594  if ((nn = int(ita->t) - int (itb->t)) != 0) return nn;
595  if ((nn = int(ita->hier_degree) - int (itb->hier_degree)) != 0)
596  return nn;
597  }
598  for (; ita != itae; ++ita) if (ita->t != LAGRANGE) return 1;
599  for (; itb != itbe; ++itb) if (itb->t != LAGRANGE) return -1;
600  return 0;
601  }
602 
603 
604  // ATTENTION : en cas de modif, changer aussi
605  // dof_description_comp__::operator,
606  // product_dof, et dof_hierarchical_compatibility.
608  if (a == b) return 0;
609  int nn;
610  if ((nn = int(a->coord_index) - int(b->coord_index)) != 0) return nn;
611  if ((nn = int(a->linkable) - int(b->linkable)) != 0) return nn;
612  if ((nn = int(a->xfem_index) - int(b->xfem_index)) != 0) return nn;
613  return dof_weak_compatibility(a,b);
614  }
615 
617  { return a->linkable; }
618 
620  { return (dof_linkable(a) && dof_description_compare(a, b) == 0); }
621 
623  { return a->xfem_index; }
624 
625  dim_type coord_index_of_dof(pdof_description a)
626  { return a->coord_index; }
627 
628  bool dof_hierarchical_compatibility(pdof_description a, pdof_description b)
629  {
630  if (a->coord_index != b->coord_index) return false;
631  if (a->linkable != b->linkable) return false;
632  if (a->xfem_index != b->xfem_index) return false;
633  std::vector<ddl_elem>::const_iterator
634  ita = a->ddl_desc.begin(), itae = a->ddl_desc.end(),
635  itb = b->ddl_desc.begin(), itbe = b->ddl_desc.end();
636  for (; ita != itae && itb != itbe; ++ita, ++itb)
637  { if (ita->t != itb->t) return false; }
638  for (; ita != itae; ++ita) if (ita->t != LAGRANGE) return false;
639  for (; itb != itbe; ++itb) if (itb->t != LAGRANGE) return false;
640  return true;
641  }
642 
643 
644  /* ******************************************************************** */
645  /* Members methods of virtual_fem . */
646  /* ******************************************************************** */
647 
648 
649  void virtual_fem::add_node(const pdof_description &d, const base_node &pt,
650  const dal::bit_vector &faces) {
651  short_type nb = cv_node.nb_points();
652  cv_node.points().resize(nb+1);
653  cv_node.points()[nb] = pt;
654  dof_types_.resize(nb+1);
655  face_tab.resize(nb+1);
656  dof_types_[nb] = d;
657  cvs_node->add_point_adaptative(nb, short_type(-1));
658  for (dal::bv_visitor f(faces); !f.finished(); ++f) {
659  cvs_node->add_point_adaptative(nb, short_type(f));
660  face_tab[nb].push_back(short_type(f));
661  }
662  pspt_valid = false;
663  }
664 
665 
666  void virtual_fem::add_node(const pdof_description &d, const base_node &pt) {
667  dal::bit_vector faces;
668  for (short_type f = 0; f < cvs_node->nb_faces(); ++f)
669  if (d->all_faces || gmm::abs(cvr->is_in_face(f, pt)) < 1.0E-7)
670  faces.add(f);
671  add_node(d, pt, faces);
672  }
673 
674  void virtual_fem::init_cvs_node() {
675  cvs_node->init_for_adaptative(cvr->structure());
676  cv_node = bgeot::convex<base_node>(cvs_node);
677  face_tab.resize(0);
678  pspt_valid = false;
679  }
680 
681  void virtual_fem::unfreeze_cvs_node() {
682  cv_node.structure() = cvs_node;
683  pspt_valid = false;
684  }
685 
686  const std::vector<short_type> &
687  virtual_fem::faces_of_dof(size_type /*cv*/, size_type i) const {
688  static const std::vector<short_type> no_faces;
689  return (i < face_tab.size()) ? face_tab[i] : no_faces;
690  }
691 
692  void virtual_fem::copy(const virtual_fem &f) {
693  dof_types_ = f.dof_types_;
694  cvs_node = bgeot::new_convex_structure();
695  *cvs_node = *f.cvs_node; // deep copy
696  cv_node = f.cv_node;
697  cv_node.structure() = cvs_node;
698  pspt = 0;
699  pspt_valid = false;
700  cvr = f.cvr;
701  dim_ = f.dim_;
702  ntarget_dim = f.ntarget_dim;
703  vtype = f.vtype;
704  is_equiv = f.is_equiv;
705  is_lag = f.is_lag;
706  is_pol = f.is_pol;
707  is_polycomp = f.is_polycomp;
708  real_element_defined = f.real_element_defined;
709  is_standard_fem = f.is_standard_fem;
710  es_degree = f.es_degree;
711  hier_raff = f.hier_raff;
712  debug_name_ = f.debug_name_;
713  face_tab = f.face_tab;
714  }
715 
716  /* ******************************************************************** */
717  /* PK class. */
718  /* ******************************************************************** */
719 
720  class PK_fem_ : public fem<base_poly> {
721  public :
722  void calc_base_func(base_poly &p, size_type i, short_type K) const;
723  PK_fem_(dim_type nc, short_type k);
724  ~PK_fem_() {}
725  };
726 
727  void PK_fem_::calc_base_func(base_poly &p, size_type i, short_type K) const {
728  dim_type N = dim();
729  base_poly l0(N, 0), l1(N, 0);
731  l0.one(); l1.one(); p = l0;
732 
733  if (K != 0) {
734  for (short_type nn = 0; nn < N; ++nn) l0 -= base_poly(N, 1, nn);
735 
736  w[0] = K;
737  for (short_type nn = 1; nn <= N; ++nn) {
738  w[nn]=short_type(floor(0.5+bgeot::to_scalar((cv_node.points()[i])[nn-1]*opt_long_scalar_type(K))));
739  w[0]=short_type(w[0] - w[nn]);
740  }
741 
742  for (int nn = 0; nn <= N; ++nn)
743  for (int j = 0; j < w[nn]; ++j) {
744  if (nn == 0)
745  p *= (l0 * (opt_long_scalar_type(K) / opt_long_scalar_type(j+1)))
746  - (l1 * (opt_long_scalar_type(j) / opt_long_scalar_type(j+1)));
747  else
748  p *= (base_poly(N,1,short_type(nn-1)) * (opt_long_scalar_type(K)/opt_long_scalar_type(j+1)))
749  - (l1 * (opt_long_scalar_type(j) / opt_long_scalar_type(j+1)));
750  }
751  }
752  }
753 
754  PK_fem_::PK_fem_(dim_type nc, short_type k) {
755  cvr = bgeot::simplex_of_reference(nc);
756  dim_ = cvr->structure()->dim();
757  is_standard_fem = is_equiv = is_pol = is_lag = true;
758  es_degree = k;
759 
760  init_cvs_node();
761  bgeot::pconvex_ref cvn = bgeot::simplex_of_reference(nc, k);
762  size_type R = cvn->nb_points();
763  for (size_type i = 0; i < R; ++i)
764  add_node(k==0 ? lagrange_0_dof(nc) : lagrange_dof(nc), cvn->points()[i]);
765 
766  base_.resize(R);
767  for (size_type r = 0; r < R; r++) calc_base_func(base_[r], r, k);
768  }
769 
770  static pfem PK_fem(fem_param_list &params,
771  std::vector<dal::pstatic_stored_object> &dependencies) {
772  GMM_ASSERT1(params.size() == 2, "Bad number of parameters : "
773  << params.size() << " should be 2.");
774  GMM_ASSERT1(params[0].type() == 0 && params[1].type() == 0,
775  "Bad type of parameters");
776  int n = dim_type(::floor(params[0].num() + 0.01));
777  int k = short_type(::floor(params[1].num() + 0.01));
778  GMM_ASSERT1(n > 0 && n < 100 && k >= 0 && k <= 150 &&
779  double(n) == params[0].num() && double(k) == params[1].num(),
780  "Bad parameters");
781  pfem p = std::make_shared<PK_fem_>(dim_type(n), short_type(k));
782  dependencies.push_back(p->ref_convex(0));
783  dependencies.push_back(p->node_tab(0));
784  return p;
785  }
786 
787 
788  /* ******************************************************************** */
789  /* Tensorial product of fem (for polynomial fem). */
790  /* ******************************************************************** */
791 
792  struct tproduct_femi : public fem<base_poly> {
793  tproduct_femi(ppolyfem fi1, ppolyfem fi2);
794  };
795 
796  tproduct_femi::tproduct_femi(ppolyfem fi1, ppolyfem fi2) {
797  if (fi2->target_dim() != 1) std::swap(fi1, fi2);
798  GMM_ASSERT1(fi2->target_dim() == 1, "dimensions mismatch");
799 
800  is_pol = true;
801  is_equiv = fi1->is_equivalent() && fi2->is_equivalent();
802  GMM_ASSERT1(is_equiv,
803  "Product of non equivalent elements not available, sorry.");
804  is_lag = fi1->is_lagrange() && fi2->is_lagrange();
805  is_standard_fem = fi1->is_standard() && fi2->is_standard();
806  es_degree = short_type(fi1->estimated_degree() + fi2->estimated_degree());
807 
809  = bgeot::convex_direct_product(fi1->node_convex(0), fi2->node_convex(0));
810  cvr = bgeot::convex_ref_product(fi1->ref_convex(0), fi2->ref_convex(0));
811  dim_ = cvr->structure()->dim();
812  init_cvs_node();
813 
814  ntarget_dim = fi2->target_dim();
815  base_.resize(cv.nb_points() * ntarget_dim);
816  size_type i, j, r;
817  for (j = 0, r = 0; j < fi2->nb_dof(0); ++j)
818  for (i = 0; i < fi1->nb_dof(0); ++i, ++r)
819  add_node(product_dof(fi1->dof_types()[i], fi2->dof_types()[j]),
820  cv.points()[r]);
821 
822  for (j = 0, r = 0; j < fi2->nb_base_components(0); j++)
823  for (i = 0; i < fi1->nb_base_components(0); i++, ++r) {
824  base_[r] = fi1->base()[i];
825  base_[r].direct_product(fi2->base()[j]);
826  }
827  }
828 
829  static pfem product_fem(fem_param_list &params,
830  std::vector<dal::pstatic_stored_object> &dependencies) {
831  GMM_ASSERT1(params.size() == 2, "Bad number of parameters : "
832  << params.size() << " should be 2.");
833  GMM_ASSERT1(params[0].type() == 1 && params[1].type() == 1,
834  "Bad type of parameters");
835  pfem pf1 = params[0].method();
836  pfem pf2 = params[1].method();
837  GMM_ASSERT1(pf1->is_polynomial() && pf2->is_polynomial(),
838  "Both arguments to FEM_PRODUCT must be polynomial FEM");
839  pfem p = std::make_shared<tproduct_femi>(ppolyfem(pf1.get()),
840  ppolyfem(pf2.get()));
841  dependencies.push_back(p->ref_convex(0));
842  dependencies.push_back(p->node_tab(0));
843  return p;
844  }
845 
846  /* ******************************************************************** */
847  /* Generic Hierarchical fem (for polynomial fem). To be interfaced. */
848  /* ******************************************************************** */
849 
850  struct thierach_femi : public fem<base_poly> {
851  thierach_femi(ppolyfem fi1, ppolyfem fi2);
852  };
853 
854  thierach_femi::thierach_femi(ppolyfem fi1, ppolyfem fi2)
855  : fem<base_poly>(*fi1) {
856  grad_computed_ = false;
857  hess_computed_ = false;
858  GMM_ASSERT1(fi2->target_dim()==fi1->target_dim(), "dimensions mismatch.");
859  GMM_ASSERT1(fi2->basic_structure(0) == fi1->basic_structure(0),
860  "Incompatible elements.");
861  GMM_ASSERT1(fi1->is_equivalent() && fi2->is_equivalent(), "Sorry, "
862  "no hierachical construction for non tau-equivalent fems.");
863  es_degree = fi2->estimated_degree();
864  is_lag = false;
865  unfreeze_cvs_node();
866  for (size_type i = 0; i < fi2->nb_dof(0); ++i) {
867  bool found = false;
868  for (size_type j = 0; j < fi1->nb_dof(0); ++j) {
869  if ( gmm::vect_dist2(fi2->node_of_dof(0,i),
870  fi1->node_of_dof(0,j)) < 1e-13
871  && dof_hierarchical_compatibility(fi2->dof_types()[i],
872  fi1->dof_types()[j]))
873  { found = true; break; }
874  }
875  if (!found) {
876  add_node(deg_hierarchical_dof(fi2->dof_types()[i],
877  fi1->estimated_degree()),
878  fi2->node_of_dof(0,i));
879  base_.resize(nb_dof(0));
880  base_[nb_dof(0)-1] = (fi2->base())[i];
881  }
882  }
883  }
884 
885  struct thierach_femi_comp : public fem<bgeot::polynomial_composite> {
886  thierach_femi_comp(ppolycompfem fi1, ppolycompfem fi2);
887  };
888 
889  thierach_femi_comp::thierach_femi_comp(ppolycompfem fi1, ppolycompfem fi2)
890  : fem<bgeot::polynomial_composite>(*fi1) {
891  GMM_ASSERT1(fi2->target_dim()==fi1->target_dim(), "dimensions mismatch.");
892  GMM_ASSERT1(fi2->basic_structure(0) == fi1->basic_structure(0),
893  "Incompatible elements.");
894  GMM_ASSERT1(fi1->is_equivalent() && fi2->is_equivalent(), "Sorry, "
895  "no hierachical construction for non tau-equivalent fems.");
896 
897  es_degree = std::max(fi2->estimated_degree(), fi1->estimated_degree());
898 
899  is_lag = false;
900  hier_raff = short_type(fi1->hierarchical_raff() + 1);
901  unfreeze_cvs_node();
902  for (size_type i = 0; i < fi2->nb_dof(0); ++i) {
903  bool found = false;
904  for (size_type j = 0; j < fi1->nb_dof(0); ++j) {
905  if ( gmm::vect_dist2(fi2->node_of_dof(0,i),
906  fi1->node_of_dof(0,j)) < 1e-13
907  && dof_hierarchical_compatibility(fi2->dof_types()[i],
908  fi1->dof_types()[j]))
909  { found = true; break; }
910  }
911  if (!found) {
912  add_node(raff_hierarchical_dof(fi2->dof_types()[i], hier_raff),
913  fi2->node_of_dof(0,i));
914  base_.resize(nb_dof(0));
915  base_[nb_dof(0)-1] = (fi2->base())[i];
916  }
917  }
918  }
919 
920  static pfem gen_hierarchical_fem
921  (fem_param_list &params, std::vector<dal::pstatic_stored_object> &deps) {
922  GMM_ASSERT1(params.size() == 2, "Bad number of parameters : "
923  << params.size() << " should be 2.");
924  GMM_ASSERT1(params[0].type() == 1 && params[1].type() == 1,
925  "Bad type of parameters");
926  pfem pf1 = params[0].method();
927  pfem pf2 = params[1].method();
928  if (pf1->is_polynomial() && pf2->is_polynomial())
929  return std::make_shared<thierach_femi>(ppolyfem(pf1.get()),
930  ppolyfem(pf2.get()));
931  GMM_ASSERT1(pf1->is_polynomialcomp() && pf2->is_polynomialcomp(),
932  "Bad parameters");
933  pfem p = std::make_shared<thierach_femi_comp>(ppolycompfem(pf1.get()),
934  ppolycompfem(pf2.get()));
935  deps.push_back(p->ref_convex(0));
936  deps.push_back(p->node_tab(0));
937  return p;
938  }
939 
940  /* ******************************************************************** */
941  /* PK hierarchical fem. */
942  /* ******************************************************************** */
943 
944  static pfem PK_hierarch_fem(fem_param_list &params,
945  std::vector<dal::pstatic_stored_object> &) {
946  GMM_ASSERT1(params.size() == 2, "Bad number of parameters : "
947  << params.size() << " should be 2.");
948  GMM_ASSERT1(params[0].type() == 0 && params[1].type() == 0,
949  "Bad type of parameters");
950  int n = int(::floor(params[0].num() + 0.01));
951  int k = int(::floor(params[1].num() + 0.01)), s;
952  GMM_ASSERT1(n > 0 && n < 100 && k > 0 && k <= 150 &&
953  double(n) == params[0].num() && double(k) == params[1].num(),
954  "Bad parameters");
955  std::stringstream name;
956  if (k == 1)
957  name << "FEM_PK(" << n << ",1)";
958  else {
959  for (s = 2; s <= k; ++s) if ((k % s) == 0) break;
960  name << "FEM_GEN_HIERARCHICAL(FEM_PK_HIERARCHICAL(" << n << ","
961  << k/s << "), FEM_PK(" << n << "," << k << "))";
962  }
963  return fem_descriptor(name.str());
964  }
965 
966  static pfem QK_hierarch_fem(fem_param_list &params,
967  std::vector<dal::pstatic_stored_object> &) {
968  GMM_ASSERT1(params.size() == 2, "Bad number of parameters : "
969  << params.size() << " should be 2.");
970  GMM_ASSERT1(params[0].type() == 0 && params[1].type() == 0,
971  "Bad type of parameters");
972  int n = int(::floor(params[0].num() + 0.01));
973  int k = int(::floor(params[1].num() + 0.01));
974  GMM_ASSERT1(n > 0 && n < 100 && k > 0 && k <= 150 &&
975  double(n) == params[0].num() && double(k) == params[1].num(),
976  "Bad parameters");
977  std::stringstream name;
978  if (n == 1)
979  name << "FEM_PK_HIERARCHICAL(1," << k << ")";
980  else
981  name << "FEM_PRODUCT(FEM_PK_HIERARCHICAL(" << n-1 << "," << k
982  << "),FEM_PK_HIERARCHICAL(1," << k << "))";
983  return fem_descriptor(name.str());
984  }
985 
986  static pfem prism_PK_hierarch_fem(fem_param_list &params,
987  std::vector<dal::pstatic_stored_object> &) {
988  GMM_ASSERT1(params.size() == 2, "Bad number of parameters : "
989  << params.size() << " should be 2.");
990  GMM_ASSERT1(params[0].type() == 0 && params[1].type() == 0,
991  "Bad type of parameters");
992  int n = int(::floor(params[0].num() + 0.01));
993  int k = int(::floor(params[1].num() + 0.01));
994  GMM_ASSERT1(n > 1 && n < 100 && k >= 0 && k <= 150 &&
995  double(n) == params[0].num() && double(k) == params[1].num(),
996  "Bad parameters");
997  std::stringstream name;
998  if (n == 2)
999  name << "FEM_QK_HIERARCHICAL(1," << k << ")";
1000  else
1001  name << "FEM_PRODUCT(FEM_PK_HIERARCHICAL(" << n-1 << "," << k
1002  << "),FEM_PK_HIERARCHICAL(1," << k << "))";
1003  return fem_descriptor(name.str());
1004  }
1005 
1006 
1007  /* ******************************************************************** */
1008  /* parallelepiped fems. */
1009  /* ******************************************************************** */
1010 
1011  static pfem QK_fem_(fem_param_list &params, bool discontinuous) {
1012  const char *fempk = discontinuous ? "FEM_PK_DISCONTINUOUS" : "FEM_PK";
1013  const char *femqk = discontinuous ? "FEM_QK_DISCONTINUOUS" : "FEM_QK";
1014  GMM_ASSERT1(params.size() == 2 || (discontinuous && params.size() == 3),
1015  "Bad number of parameters : "
1016  << params.size() << " should be 2.");
1017  GMM_ASSERT1(params[0].type() == 0 && params[1].type() == 0 &&
1018  (params.size() != 3 || params[2].type() == 0),
1019  "Bad type of parameters");
1020  int n = int(::floor(params[0].num() + 0.01));
1021  int k = int(::floor(params[1].num() + 0.01));
1022  char alpha[128]; alpha[0] = 0;
1023  if (discontinuous && params.size() == 3) {
1024  scalar_type v = params[2].num();
1025  GMM_ASSERT1(v >= 0 && v <= 1, "Bad value for alpha: " << v);
1026  snprintf(alpha, 127, ",%g", v);
1027  }
1028  GMM_ASSERT1(n > 0 && n < 100 && k >= 0 && k <= 150 &&
1029  double(n) == params[0].num() && double(k) == params[1].num(),
1030  "Bad parameters");
1031  std::stringstream name;
1032  if (n == 1)
1033  name << fempk << "(1," << k << alpha << ")";
1034  else
1035  name << "FEM_PRODUCT(" << femqk << "(" << n-1 << ","
1036  << k << alpha << ")," << fempk << "(1," << k << alpha << "))";
1037  return fem_descriptor(name.str());
1038  }
1039 
1040  static pfem QK_fem(fem_param_list &params,
1041  std::vector<dal::pstatic_stored_object> &) {
1042  return QK_fem_(params, false);
1043  }
1044 
1045  static pfem QK_discontinuous_fem(fem_param_list &params,
1046  std::vector<dal::pstatic_stored_object> &) {
1047  return QK_fem_(params, true);
1048  }
1049 
1050 
1051  /* ******************************************************************** */
1052  /* prims fems. */
1053  /* ******************************************************************** */
1054 
1055  static pfem prism_PK_fem(fem_param_list &params,
1056  std::vector<dal::pstatic_stored_object> &) {
1057  GMM_ASSERT1(params.size() == 2, "Bad number of parameters : "
1058  << params.size() << " should be 2.");
1059  GMM_ASSERT1(params[0].type() == 0 && params[1].type() == 0,
1060  "Bad type of parameters");
1061  int n = int(::floor(params[0].num() + 0.01));
1062  int k = int(::floor(params[1].num() + 0.01));
1063  GMM_ASSERT1(n > 1 && n < 100 && k >= 0 && k <= 150 &&
1064  double(n) == params[0].num() && double(k) == params[1].num(),
1065  "Bad parameters");
1066  std::stringstream name;
1067  if (n == 2)
1068  name << "FEM_QK(1," << k << ")";
1069  else
1070  name << "FEM_PRODUCT(FEM_PK(" << n-1 << "," << k << "),FEM_PK(1,"
1071  << k << "))";
1072  return fem_descriptor(name.str());
1073  }
1074 
1075  static pfem
1076  prism_PK_discontinuous_fem(fem_param_list &params,
1077  std::vector<dal::pstatic_stored_object> &) {
1078  GMM_ASSERT1(params.size() == 2 || params.size() == 3,
1079  "Bad number of parameters : "
1080  << params.size() << " should be 2 or 3.");
1081  GMM_ASSERT1(params[0].type() == 0 && params[1].type() == 0 &&
1082  (params.size() != 3 || params[2].type() == 0),
1083  "Bad type of parameters");
1084  int n = int(::floor(params[0].num() + 0.01));
1085  int k = int(::floor(params[1].num() + 0.01));
1086  char alpha[128]; alpha[0] = 0;
1087  if (params.size() == 3) {
1088  scalar_type v = params[2].num();
1089  GMM_ASSERT1(v >= 0 && v <= 1, "Bad value for alpha: " << v);
1090  snprintf(alpha, 127, ",%g", v);
1091  }
1092  GMM_ASSERT1(n > 1 && n < 100 && k >= 0 && k <= 150 &&
1093  double(n) == params[0].num() && double(k) == params[1].num(),
1094  "Bad parameters");
1095  std::stringstream name;
1096  if (n == 2)
1097  name << "FEM_QK_DISCONTINUOUS(1," << k << alpha << ")";
1098  else
1099  name << "FEM_PRODUCT(FEM_PK_DISCONTINUOUS(" << n-1 << "," << k << alpha
1100  << "),FEM_PK_DISCONTINUOUS(1,"
1101  << k << alpha << "))";
1102  return fem_descriptor(name.str());
1103  }
1104 
1105  /* ******************************************************************** */
1106  /* P1 NON CONFORMING (dim 2) */
1107  /* ******************************************************************** */
1108 
1109  static pfem P1_nonconforming_fem(fem_param_list &params,
1110  std::vector<dal::pstatic_stored_object> &dependencies) {
1111  GMM_ASSERT1(params.size() == 0, "Bad number of parameters ");
1112  auto p = std::make_shared<fem<base_poly>>();
1113  p->mref_convex() = bgeot::simplex_of_reference(2);
1114  p->dim() = 2;
1115  p->is_standard() = p->is_equivalent() = true;
1116  p->is_polynomial() = p->is_lagrange() = true;
1117  p->estimated_degree() = 1;
1118  p->init_cvs_node();
1119  p->base().resize(3);
1120 
1121  p->add_node(lagrange_dof(2), base_small_vector(0.5, 0.5));
1122  read_poly(p->base()[0], 2, "2*x + 2*y - 1");
1123  p->add_node(lagrange_dof(2), base_small_vector(0.0, 0.5));
1124  read_poly(p->base()[1], 2, "1 - 2*x");
1125  p->add_node(lagrange_dof(2), base_small_vector(0.5, 0.0));
1126  read_poly(p->base()[2], 2, "1 - 2*y");
1127  dependencies.push_back(p->ref_convex(0));
1128  dependencies.push_back(p->node_tab(0));
1129 
1130  return pfem(p);
1131  }
1132 
1133 
1134  /* ******************************************************************** */
1135  /* Quad8/Hexa20 SERENDIPITY ELEMENT (dim 2 or 3) (incomplete Q2) */
1136  /* ******************************************************************** */
1137 
1138  // local dof numeration for 2D:
1139  // 5--6--7
1140  // | |
1141  // 3 4
1142  // | |
1143  // 0--1--2
1144  //
1145  // local dof numeration for 3D:
1146  //
1147  // 17---18---19
1148  // /| /|
1149  // / 10 / 11
1150  // 15 | 16 |
1151  // / 5----6/---7
1152  // / / / /
1153  // 12---13---14 /
1154  // | 3 | 4
1155  // 8 / 9 /
1156  // |/ |/
1157  // 0----1----2
1158 
1159  static pfem
1160  build_Q2_incomplete_fem(fem_param_list &params,
1161  std::vector<dal::pstatic_stored_object> &deps,
1162  bool discontinuous) {
1163  GMM_ASSERT1(params.size() <= 1, "Bad number of parameters");
1164  dim_type n = 2;
1165  if (params.size() > 0) {
1166  GMM_ASSERT1(params[0].type() == 0, "Bad type of parameters");
1167  n = dim_type(::floor(params[0].num() + 0.01));
1168  GMM_ASSERT1(n == 2 || n == 3, "Bad parameter, expected value 2 or 3");
1169  }
1170  auto p = std::make_shared<fem<base_poly>>();
1171  p->mref_convex() = bgeot::parallelepiped_of_reference(n);
1172  p->dim() = n;
1173  p->is_standard() = p->is_equivalent() = true;
1174  p->is_polynomial() = p->is_lagrange() = true;
1175  p->estimated_degree() = 2;
1176  p->init_cvs_node();
1177  p->base().resize(n == 2 ? 8 : 20);
1178  auto lag_dof = discontinuous ? lagrange_nonconforming_dof(n)
1179  : lagrange_dof(n);
1180 
1181  if (n == 2) {
1182  std::stringstream s
1183  ( "1 - 2*x^2*y - 2*x*y^2 + 2*x^2 + 5*x*y + 2*y^2 - 3*x - 3*y;"
1184  "4*(x^2*y - x^2 - x*y + x);"
1185  "2*x*y*y - 2*x*x*y + 2*x*x - x*y - x;"
1186  "4*(x*y*y - x*y - y*y + y);"
1187  "4*(x*y - x*y*y);"
1188  "2*x*x*y - 2*x*y*y - x*y + 2*y*y - y;"
1189  "4*(x*y - x*x*y);"
1190  "2*x*x*y + 2*x*y*y - 3*x*y;");
1191 
1192  for (int i = 0; i < 8; ++i) p->base()[i] = read_base_poly(2, s);
1193 
1194  p->add_node(lag_dof, base_small_vector(0.0, 0.0));
1195  p->add_node(lag_dof, base_small_vector(0.5, 0.0));
1196  p->add_node(lag_dof, base_small_vector(1.0, 0.0));
1197  p->add_node(lag_dof, base_small_vector(0.0, 0.5));
1198  p->add_node(lag_dof, base_small_vector(1.0, 0.5));
1199  p->add_node(lag_dof, base_small_vector(0.0, 1.0));
1200  p->add_node(lag_dof, base_small_vector(0.5, 1.0));
1201  p->add_node(lag_dof, base_small_vector(1.0, 1.0));
1202  } else {
1203  std::stringstream s
1204  ("1 + 2*x^2*y*z + 2*x*y^2*z + 2*x*y*z^2"
1205  " - 2*x^2*y - 2*x^2*z - 2*x*y^2 - 2*y^2*z - 2*y*z^2 - 2*x*z^2 - 7*x*y*z"
1206  " + 2*x^2 + 2*y^2 + 2*z^2 + 5*y*z + 5*x*z + 5*x*y - 3*x - 3*y - 3*z;"
1207  "4*( - x^2*y*z + x*y*z + x^2*z - x*z + x^2*y - x*y - x^2 + x);"
1208  "2*x^2*y*z - 2*x*y^2*z - 2*x*y*z^2"
1209  " - 2*x^2*y - 2*x^2*z + 2*x*y^2 + 2*x*z^2 + 3*x*y*z + 2*x^2 - x*y - x*z - x;"
1210  "4*( - x*y^2*z + x*y^2 + y^2*z + x*y*z - x*y - y^2 - y*z + y);"
1211  "4*(x*y^2*z - x*y^2 - x*y*z + x*y);"
1212  " - 2*x^2*y*z + 2*x*y^2*z - 2*x*y*z^2"
1213  " + 2*x^2*y - 2*x*y^2 - 2*y^2*z + 2*y*z^2 + 3*x*y*z - x*y + 2*y^2 - y*z - y;"
1214  "4*(x^2*y*z - x^2*y - x*y*z + x*y);"
1215  " - 2*x^2*y*z - 2*x*y^2*z + 2*x*y*z^2 + 2*x^2*y + 2*x*y^2 + x*y*z - 3*x*y;"
1216  "4*( - x*y*z^2 + x*z^2 + y*z^2 + x*y*z - x*z - y*z - z^2 + z);"
1217  "4*(x*y*z^2 - x*y*z - x*z^2 + x*z);"
1218  "4*(x*y*z^2 - x*y*z - y*z^2 + y*z);"
1219  "4*( - x*y*z^2 + x*y*z);"
1220  " - 2*x^2*y*z - 2*x*y^2*z + 2*x*y*z^2"
1221  " + 2*x^2*z + 2*y^2*z - 2*x*z^2 - 2*y*z^2 + 3*x*y*z - x*z - y*z + 2*z^2 - z;"
1222  "4*(x^2*y*z - x^2*z - x*y*z + x*z);"
1223  " - 2*x^2*y*z + 2*x*y^2*z - 2*x*y*z^2 + 2*x^2*z + 2*x*z^2 + x*y*z - 3*x*z;"
1224  "4*(x*y^2*z - y^2*z - x*y*z + y*z);"
1225  "4*( - x*y^2*z + x*y*z);"
1226  "2*x^2*y*z - 2*x*y^2*z - 2*x*y*z^2 + 2*y^2*z + 2*y*z^2 + x*y*z - 3*y*z;"
1227  "4*( - x^2*y*z + x*y*z);"
1228  "2*x^2*y*z + 2*x*y^2*z + 2*x*y*z^2 - 5*x*y*z;");
1229 
1230  for (int i = 0; i < 20; ++i) p->base()[i] = read_base_poly(3, s);
1231 
1232  p->add_node(lag_dof, base_small_vector(0.0, 0.0, 0.0));
1233  p->add_node(lag_dof, base_small_vector(0.5, 0.0, 0.0));
1234  p->add_node(lag_dof, base_small_vector(1.0, 0.0, 0.0));
1235  p->add_node(lag_dof, base_small_vector(0.0, 0.5, 0.0));
1236  p->add_node(lag_dof, base_small_vector(1.0, 0.5, 0.0));
1237  p->add_node(lag_dof, base_small_vector(0.0, 1.0, 0.0));
1238  p->add_node(lag_dof, base_small_vector(0.5, 1.0, 0.0));
1239  p->add_node(lag_dof, base_small_vector(1.0, 1.0, 0.0));
1240 
1241  p->add_node(lag_dof, base_small_vector(0.0, 0.0, 0.5));
1242  p->add_node(lag_dof, base_small_vector(1.0, 0.0, 0.5));
1243  p->add_node(lag_dof, base_small_vector(0.0, 1.0, 0.5));
1244  p->add_node(lag_dof, base_small_vector(1.0, 1.0, 0.5));
1245 
1246  p->add_node(lag_dof, base_small_vector(0.0, 0.0, 1.0));
1247  p->add_node(lag_dof, base_small_vector(0.5, 0.0, 1.0));
1248  p->add_node(lag_dof, base_small_vector(1.0, 0.0, 1.0));
1249  p->add_node(lag_dof, base_small_vector(0.0, 0.5, 1.0));
1250  p->add_node(lag_dof, base_small_vector(1.0, 0.5, 1.0));
1251  p->add_node(lag_dof, base_small_vector(0.0, 1.0, 1.0));
1252  p->add_node(lag_dof, base_small_vector(0.5, 1.0, 1.0));
1253  p->add_node(lag_dof, base_small_vector(1.0, 1.0, 1.0));
1254  }
1255  deps.push_back(p->ref_convex(0));
1256  deps.push_back(p->node_tab(0));
1257 
1258  return pfem(p);
1259  }
1260 
1261  static pfem Q2_incomplete_fem
1262  (fem_param_list &params, std::vector<dal::pstatic_stored_object> &deps)
1263  { return build_Q2_incomplete_fem(params, deps, false); }
1264 
1265  static pfem Q2_incomplete_discontinuous_fem
1266  (fem_param_list &params, std::vector<dal::pstatic_stored_object> &deps)
1267  { return build_Q2_incomplete_fem(params, deps, true); }
1268 
1269  /* ******************************************************************** */
1270  /* Lagrange Pyramidal element of degree 0, 1 and 2 */
1271  /* ******************************************************************** */
1272 
1273  // local dof numeration for K=1:
1274  // 4
1275  // /|||
1276  // / || |
1277  // 2-|--|-3
1278  // | | | |
1279  // || ||
1280  // || ||
1281  // 0------1
1282  //
1283  // local dof numeration for K=2:
1284  //
1285  // 13
1286  // / |
1287  // 11---12
1288  // | |
1289  // 9----10
1290  // / |
1291  // 6---7---8
1292  // | |
1293  // 3 4 5
1294  // | |
1295  // 0---1---2
1296 
1297  static pfem
1298  build_pyramid_QK_fem(short_type k, bool disc, scalar_type alpha=0) {
1299  auto p = std::make_shared<fem<base_rational_fraction>>();
1300  p->mref_convex() = bgeot::pyramid_QK_of_reference(1);
1301  p->dim() = 3;
1302  p->is_standard() = p->is_equivalent() = true;
1303  p->is_polynomial() = false;
1304  p->is_lagrange() = true;
1305  p->estimated_degree() = k;
1306  p->init_cvs_node();
1307  auto lag_dof = disc ? lagrange_nonconforming_dof(3) : lagrange_dof(3);
1308 
1309  if (k == 0) {
1310  p->base().resize(1);
1311  p->base()[0] = read_base_poly(3, "1");
1312  p->add_node(lagrange_0_dof(3), base_small_vector(0.0, 0.0, 0.5));
1313  } else if (k == 1) {
1314  p->base().resize(5);
1315  base_rational_fraction // Q = xy/(1-z)
1316  Q(read_base_poly(3, "x*y"), read_base_poly(3, "1-z"));
1317  p->base()[0] = (read_base_poly(3, "1-x-y-z") + Q)*0.25;
1318  p->base()[1] = (read_base_poly(3, "1+x-y-z") - Q)*0.25;
1319  p->base()[2] = (read_base_poly(3, "1-x+y-z") - Q)*0.25;
1320  p->base()[3] = (read_base_poly(3, "1+x+y-z") + Q)*0.25;
1321  p->base()[4] = read_base_poly(3, "z");
1322 
1323  p->add_node(lag_dof, base_small_vector(-1.0, -1.0, 0.0));
1324  p->add_node(lag_dof, base_small_vector( 1.0, -1.0, 0.0));
1325  p->add_node(lag_dof, base_small_vector(-1.0, 1.0, 0.0));
1326  p->add_node(lag_dof, base_small_vector( 1.0, 1.0, 0.0));
1327  p->add_node(lag_dof, base_small_vector( 0.0, 0.0, 1.0));
1328 
1329  } else if (k == 2) {
1330  p->base().resize(14);
1331 
1332  base_poly xi0 = read_base_poly(3, "(1-z-x)*0.5");
1333  base_poly xi1 = read_base_poly(3, "(1-z-y)*0.5");
1334  base_poly xi2 = read_base_poly(3, "(1-z+x)*0.5");
1335  base_poly xi3 = read_base_poly(3, "(1-z+y)*0.5");
1336  base_poly x = read_base_poly(3, "x");
1337  base_poly y = read_base_poly(3, "y");
1338  base_poly z = read_base_poly(3, "z");
1339  base_poly ones = read_base_poly(3, "1");
1340  base_poly un_z = read_base_poly(3, "1-z");
1341 
1342  std::vector<base_node> points = { base_node(-1.0, -1.0, 0.0),
1343  base_node( 0.0, -1.0, 0.0),
1344  base_node( 1.0, -1.0, 0.0),
1345  base_node(-1.0, 0.0, 0.0),
1346  base_node( 0.0, 0.0, 0.0),
1347  base_node( 1.0, 0.0, 0.0),
1348  base_node(-1.0, 1.0, 0.0),
1349  base_node( 0.0, 1.0, 0.0),
1350  base_node( 1.0, 1.0, 0.0),
1351  base_node(-0.5, -0.5, 0.5),
1352  base_node( 0.5, -0.5, 0.5),
1353  base_node(-0.5, 0.5, 0.5),
1354  base_node( 0.5, 0.5, 0.5),
1355  base_node( 0.0, 0.0, 1.0) };
1356 
1357  if (disc && alpha != scalar_type(0)) {
1358  base_node G =
1359  gmm::mean_value(points.begin(), points.end());
1360  for (auto && pt : points)
1361  pt = (1-alpha)*pt + alpha*G;
1362  for (size_type d = 0; d < 3; ++d) {
1363  base_poly S(1,2);
1364  S[0] = -alpha * G[d] / (1-alpha);
1365  S[1] = 1. / (1-alpha);
1366  xi0 = bgeot::poly_substitute_var(xi0, S, d);
1367  xi1 = bgeot::poly_substitute_var(xi1, S, d);
1368  xi2 = bgeot::poly_substitute_var(xi2, S, d);
1369  xi3 = bgeot::poly_substitute_var(xi3, S, d);
1370  x = bgeot::poly_substitute_var(x, S, d);
1371  y = bgeot::poly_substitute_var(y, S, d);
1372  z = bgeot::poly_substitute_var(z, S, d);
1373  un_z = bgeot::poly_substitute_var(un_z, S, d);
1374  }
1375  }
1376  base_rational_fraction Q(read_base_poly(3, "1"), un_z);
1377 
1378  p->base()[ 0] = Q*Q*xi0*xi1*(x*y-z*un_z);
1379  p->base()[ 1] = -Q*Q*xi0*xi1*xi2*y*4.;
1380  p->base()[ 2] = Q*Q*xi1*xi2*(-x*y-z*un_z);
1381  p->base()[ 3] = -Q*Q*xi3*xi0*xi1*x*4.;
1382  p->base()[ 4] = Q*Q*xi0*xi1*xi2*xi3*16.;
1383  p->base()[ 5] = Q*Q*xi1*xi2*xi3*x*4.;
1384  p->base()[ 6] = Q*Q*xi3*xi0*(-x*y-z*un_z);
1385  p->base()[ 7] = Q*Q*xi2*xi3*xi0*y*4.;
1386  p->base()[ 8] = Q*Q*xi2*xi3*(x*y-z*un_z);
1387  p->base()[ 9] = Q*z*xi0*xi1*4.;
1388  p->base()[10] = Q*z*xi1*xi2*4.;
1389  p->base()[11] = Q*z*xi3*xi0*4.;
1390  p->base()[12] = Q*z*xi2*xi3*4.;
1391  p->base()[13] = z*(z*2-ones);
1392 
1393  for (const auto &pt : points)
1394  p->add_node(lag_dof, pt);
1395 
1396  } else GMM_ASSERT1(false, "Sorry, pyramidal Lagrange fem "
1397  "implemented only for degree 0, 1 or 2");
1398 
1399  return pfem(p);
1400  }
1401 
1402 
1403  static pfem pyramid_QK_fem
1404  (fem_param_list &params, std::vector<dal::pstatic_stored_object> &deps) {
1405  GMM_ASSERT1(params.size() <= 1, "Bad number of parameters");
1406  short_type k = 2;
1407  if (params.size() > 0) {
1408  GMM_ASSERT1(params[0].type() == 0, "Bad type of parameters");
1409  k = dim_type(::floor(params[0].num() + 0.01));
1410  }
1411  pfem p = build_pyramid_QK_fem(k, false);
1412  deps.push_back(p->ref_convex(0));
1413  deps.push_back(p->node_tab(0));
1414  return p;
1415  }
1416 
1417  static pfem pyramid_QK_disc_fem
1418  (fem_param_list &params, std::vector<dal::pstatic_stored_object> &deps) {
1419  GMM_ASSERT1(params.size() <= 2, "Bad number of parameters");
1420  short_type k = 2;
1421  if (params.size() > 0) {
1422  GMM_ASSERT1(params[0].type() == 0, "Bad type of parameters");
1423  k = dim_type(::floor(params[0].num() + 0.01));
1424  }
1425  scalar_type alpha(0);
1426  if (params.size() > 1) {
1427  GMM_ASSERT1(params[1].type() == 0, "Bad type of parameters");
1428  alpha = params[1].num();
1429  }
1430  pfem p = build_pyramid_QK_fem(k, true, alpha);
1431  deps.push_back(p->ref_convex(0));
1432  deps.push_back(p->node_tab(0));
1433  return p;
1434  }
1435 
1436 
1437  /* ******************************************************************** */
1438  /* Incomplete quadratic Lagrange pyramidal element. */
1439  /* ******************************************************************** */
1440 
1441  // local dof numeration:
1442  //
1443  // 12
1444  // / |
1445  // 10---11
1446  // | |
1447  // 8----9
1448  // / |
1449  // 5---6---7
1450  // | |
1451  // 3 4
1452  // | |
1453  // 0---1---2
1454 
1455  static pfem build_pyramid_Q2_incomplete_fem(bool disc) {
1456  auto p = std::make_shared<fem<base_rational_fraction>>();
1457  p->mref_convex() = bgeot::pyramid_QK_of_reference(1);
1458  p->dim() = 3;
1459  p->is_standard() = p->is_equivalent() = true;
1460  p->is_polynomial() = false;
1461  p->is_lagrange() = true;
1462  p->estimated_degree() = 2;
1463  p->init_cvs_node();
1464  auto lag_dof = disc ? lagrange_nonconforming_dof(3) : lagrange_dof(3);
1465 
1466  p->base().resize(13);
1467 
1468  base_poly xy = read_base_poly(3, "x*y");
1469  base_poly z = read_base_poly(3, "z");
1470 
1471  base_poly p00m = read_base_poly(3, "1-z");
1472 
1473  base_poly pmmm = read_base_poly(3, "1-x-y-z");
1474  base_poly ppmm = read_base_poly(3, "1+x-y-z");
1475  base_poly pmpm = read_base_poly(3, "1-x+y-z");
1476  base_poly pppm = read_base_poly(3, "1+x+y-z");
1477 
1478  base_poly mmm0_ = read_base_poly(3, "-1-x-y")*0.25;
1479  base_poly mpm0_ = read_base_poly(3, "-1+x-y")*0.25;
1480  base_poly mmp0_ = read_base_poly(3, "-1-x+y")*0.25;
1481  base_poly mpp0_ = read_base_poly(3, "-1+x+y")*0.25;
1482 
1483  base_poly pp0m = read_base_poly(3, "1+x-z");
1484  base_poly pm0m = read_base_poly(3, "1-x-z");
1485  base_poly p0mm = read_base_poly(3, "1-y-z");
1486  base_poly p0pm = read_base_poly(3, "1+y-z");
1487 
1488  // (Bedrosian, 1992)
1489  p->base()[ 0] = mmm0_ * pmmm + base_rational_fraction(mmm0_ * xy, p00m); // N5
1490  p->base()[ 1] = base_rational_fraction(pp0m * pm0m * p0mm * 0.5, p00m); // N6
1491  p->base()[ 2] = mpm0_ * ppmm - base_rational_fraction(mpm0_ * xy, p00m); // N7
1492  p->base()[ 3] = base_rational_fraction(p0pm * p0mm * pm0m * 0.5, p00m); // N4
1493  p->base()[ 4] = base_rational_fraction(p0pm * p0mm * pp0m * 0.5, p00m); // N8
1494  p->base()[ 5] = mmp0_ * pmpm - base_rational_fraction(mmp0_ * xy, p00m); // N3
1495  p->base()[ 6] = base_rational_fraction(pp0m * pm0m * p0pm * 0.5, p00m); // N2
1496  p->base()[ 7] = mpp0_ * pppm + base_rational_fraction(mpp0_ * xy, p00m); // N1
1497  p->base()[ 8] = base_rational_fraction(pm0m * p0mm * z, p00m); // N11
1498  p->base()[ 9] = base_rational_fraction(pp0m * p0mm * z, p00m); // N12
1499  p->base()[10] = base_rational_fraction(pm0m * p0pm * z, p00m); // N10
1500  p->base()[11] = base_rational_fraction(pp0m * p0pm * z, p00m); // N9
1501  p->base()[12] = read_base_poly(3, "2*z^2-z"); // N13
1502 
1503  p->add_node(lag_dof, base_small_vector(-1.0, -1.0, 0.0));
1504  p->add_node(lag_dof, base_small_vector( 0.0, -1.0, 0.0));
1505  p->add_node(lag_dof, base_small_vector( 1.0, -1.0, 0.0));
1506  p->add_node(lag_dof, base_small_vector(-1.0, 0.0, 0.0));
1507  p->add_node(lag_dof, base_small_vector( 1.0, 0.0, 0.0));
1508  p->add_node(lag_dof, base_small_vector(-1.0, 1.0, 0.0));
1509  p->add_node(lag_dof, base_small_vector( 0.0, 1.0, 0.0));
1510  p->add_node(lag_dof, base_small_vector( 1.0, 1.0, 0.0));
1511  p->add_node(lag_dof, base_small_vector(-0.5, -0.5, 0.5));
1512  p->add_node(lag_dof, base_small_vector( 0.5, -0.5, 0.5));
1513  p->add_node(lag_dof, base_small_vector(-0.5, 0.5, 0.5));
1514  p->add_node(lag_dof, base_small_vector( 0.5, 0.5, 0.5));
1515  p->add_node(lag_dof, base_small_vector( 0.0, 0.0, 1.0));
1516 
1517  return pfem(p);
1518  }
1519 
1520 
1521  static pfem pyramid_Q2_incomplete_fem
1522  (fem_param_list &params, std::vector<dal::pstatic_stored_object> &deps) {
1523  GMM_ASSERT1(params.size() == 0, "Bad number of parameters");
1524  pfem p = build_pyramid_Q2_incomplete_fem(false);
1525  deps.push_back(p->ref_convex(0));
1526  deps.push_back(p->node_tab(0));
1527  return p;
1528  }
1529 
1530  static pfem pyramid_Q2_incomplete_disc_fem
1531  (fem_param_list &params, std::vector<dal::pstatic_stored_object> &deps) {
1532  GMM_ASSERT1(params.size() == 0, "Bad number of parameters");
1533  pfem p = build_pyramid_Q2_incomplete_fem(true);
1534  deps.push_back(p->ref_convex(0));
1535  deps.push_back(p->node_tab(0));
1536  return p;
1537  }
1538 
1539  /* ******************************************************************** */
1540  /* Incomplete quadratic Lagrange prism element. */
1541  /* ******************************************************************** */
1542 
1543  // local dof numeration:
1544  //
1545  // 14
1546  // /|`
1547  // 12 | 13
1548  // / 8 `
1549  // 9--10--11
1550  // | | |
1551  // | 5 |
1552  // 6 / ` 7
1553  // | 3 4 |
1554  // |/ `|
1555  // 0---1---2
1556 
1557  static pfem build_prism_incomplete_P2_fem(bool disc) {
1558  auto p = std::make_shared<fem<base_rational_fraction>>();
1559  p->mref_convex() = bgeot::prism_of_reference(3);
1560  p->dim() = 3;
1561  p->is_standard() = p->is_equivalent() = true;
1562  p->is_polynomial() = false;
1563  p->is_lagrange() = true;
1564  p->estimated_degree() = 2;
1565  p->init_cvs_node();
1566  auto lag_dof = disc ? lagrange_nonconforming_dof(3) : lagrange_dof(3);
1567 
1568  p->base().resize(15);
1569 
1570  std::stringstream s
1571  ( "-2*y*z^2-2*x*z^2+2*z^2-2*y^2*z-4*x*y*z+5*y*z-2*x^2*z+5*x*z"
1572  "-3*z+2*y^2+4*x*y-3*y+2*x^2-3*x+1;"
1573  "4*(x*y*z+x^2*z-x*z-x*y-x^2+x);"
1574  "2*x*z^2-2*x^2*z-x*z+2*x^2-x;"
1575  "4*(y^2*z+x*y*z-y*z-y^2-x*y+y);"
1576  "4*(x*y-x*y*z);"
1577  "2*y*z^2-2*y^2*z-y*z+2*y^2-y;"
1578  "4*(y*z^2+x*z^2-z^2-y*z-x*z+z);"
1579  "4*(x*z-x*z^2);"
1580  "4*(y*z-y*z^2);"
1581  "-2*y*z^2-2*x*z^2+2*z^2+2*y^2*z+4*x*y*z-y*z+2*x^2*z-x*z-z;"
1582  "4*(-x*y*z-x^2*z+x*z);"
1583  "2*x*z^2+2*x^2*z-3*x*z;"
1584  "4*(-y^2*z-x*y*z+y*z);"
1585  "4*x*y*z;"
1586  "2*y*z^2+2*y^2*z-3*y*z;");
1587 
1588  for (int i = 0; i < 15; ++i)
1589  p->base()[i] = read_base_poly(3, s);
1590 
1591  p->add_node(lag_dof, base_small_vector(0.0, 0.0, 0.0));
1592  p->add_node(lag_dof, base_small_vector(0.5, 0.0, 0.0));
1593  p->add_node(lag_dof, base_small_vector(1.0, 0.0, 0.0));
1594  p->add_node(lag_dof, base_small_vector(0.0, 0.5, 0.0));
1595  p->add_node(lag_dof, base_small_vector(0.5, 0.5, 0.0));
1596  p->add_node(lag_dof, base_small_vector(0.0, 1.0, 0.0));
1597  p->add_node(lag_dof, base_small_vector(0.0, 0.0, 0.5));
1598  p->add_node(lag_dof, base_small_vector(1.0, 0.0, 0.5));
1599  p->add_node(lag_dof, base_small_vector(0.0, 1.0, 0.5));
1600  p->add_node(lag_dof, base_small_vector(0.0, 0.0, 1.0));
1601  p->add_node(lag_dof, base_small_vector(0.5, 0.0, 1.0));
1602  p->add_node(lag_dof, base_small_vector(1.0, 0.0, 1.0));
1603  p->add_node(lag_dof, base_small_vector(0.0, 0.5, 1.0));
1604  p->add_node(lag_dof, base_small_vector(0.5, 0.5, 1.0));
1605  p->add_node(lag_dof, base_small_vector(0.0, 1.0, 1.0));
1606 
1607  return pfem(p);
1608  }
1609 
1610 
1611  static pfem prism_incomplete_P2_fem
1612  (fem_param_list &params, std::vector<dal::pstatic_stored_object> &deps) {
1613  GMM_ASSERT1(params.size() == 0, "Bad number of parameters");
1614  pfem p = build_prism_incomplete_P2_fem(false);
1615  deps.push_back(p->ref_convex(0));
1616  deps.push_back(p->node_tab(0));
1617  return p;
1618  }
1619 
1620  static pfem prism_incomplete_P2_disc_fem
1621  (fem_param_list &params, std::vector<dal::pstatic_stored_object> &deps) {
1622  GMM_ASSERT1(params.size() == 0, "Bad number of parameters");
1623  pfem p = build_prism_incomplete_P2_fem(true);
1624  deps.push_back(p->ref_convex(0));
1625  deps.push_back(p->node_tab(0));
1626  return p;
1627  }
1628 
1629  /* ******************************************************************** */
1630  /* P1 element with a bubble base function on a face */
1631  /* ******************************************************************** */
1632 
1633  struct P1_wabbfoaf_ : public PK_fem_ {
1634  P1_wabbfoaf_(dim_type nc);
1635  };
1636 
1637  P1_wabbfoaf_::P1_wabbfoaf_(dim_type nc) : PK_fem_(nc, 1) {
1638  is_lag = false; es_degree = 2;
1639  base_node pt(nc); pt.fill(0.5);
1640  unfreeze_cvs_node();
1641  add_node(bubble1_dof(nc), pt);
1642  base_.resize(nb_dof(0));
1643  base_[nc+1] = base_[1]; base_[nc+1] *= scalar_type(1 << nc);
1644  for (int i = 2; i <= nc; ++i) base_[nc+1] *= base_[i];
1645  // Le raccord assure la continuite
1646  // des possibilités de raccord avec du P2 existent mais il faudrait
1647  // modifier qlq chose (transformer les fct de base P1)
1648  }
1649 
1650  static pfem P1_with_bubble_on_a_face(fem_param_list &params,
1651  std::vector<dal::pstatic_stored_object> &dependencies) {
1652  GMM_ASSERT1(params.size() == 1, "Bad number of parameters : "
1653  << params.size() << " should be 1.");
1654  GMM_ASSERT1(params[0].type() == 0, "Bad type of parameters");
1655  int n = int(::floor(params[0].num() + 0.01));
1656  GMM_ASSERT1(n > 1 && n < 100 && double(n) == params[0].num(),
1657  "Bad parameter");
1658  pfem p = std::make_shared<P1_wabbfoaf_>(dim_type(n));
1659  dependencies.push_back(p->ref_convex(0));
1660  dependencies.push_back(p->node_tab(0));
1661  return p;
1662  }
1663 
1664  /* ******************************************************************** */
1665  /* Element Pk on a square with internal nodes (with possible node */
1666  /* correspondance for surface in 3D (build for HHO elements). */
1667  /* ******************************************************************** */
1668  // Not tested. To be tested
1669 
1670  struct CIPK_SQUARE_ : public fem<base_poly> {
1671  dim_type k; //
1672  mutable base_matrix K;
1673  base_small_vector norient;
1674  mutable bgeot::pgeotrans_precomp pgp;
1675  mutable bgeot::pgeometric_trans pgt_stored;
1676  // mutable pfem_precomp pfp;
1677 
1678  bgeot::pstored_point_tab pC;
1679 
1680  virtual void mat_trans(base_matrix &M, const base_matrix &G,
1681  bgeot::pgeometric_trans pgt) const;
1682  CIPK_SQUARE_(dim_type nc_);
1683  };
1684 
1685  void CIPK_SQUARE_::mat_trans(base_matrix &M,
1686  const base_matrix &G,
1687  bgeot::pgeometric_trans pgt) const {
1688  // All the dof of this element are concentrated at the center of the element
1689  // This is a PK element on a square. The base functions are the monomials
1690  // The trans_mat is here to eliminate a potential rotation of angle k PI/2
1691  // The idea is to compute the gradient at the center and to sort and
1692  // orientate the derivative in the two directions, and exchange the base
1693  // functions accordingly.
1694  dim_type N = dim_type(G.nrows());
1695  gmm::copy(gmm::identity_matrix(), M);
1696  if (pgt != pgt_stored) {
1697  pgt_stored = pgt;
1698  pgp = bgeot::geotrans_precomp(pgt, pC, 0);
1699  }
1700  gmm::resize(K, N, 2);
1701  gmm::mult(G, pgp->grad(0), K);
1702  scalar_type s0(0), m0(M_PI);
1703  for (size_type i = 0; i < N; ++i, m0*=M_PI) s0 += m0 * K(i, 0);
1704  scalar_type s1(0), m1(M_PI);
1705  for (size_type i = 0; i < N; ++i, m1*=M_PI) s1 += m1 * K(i, 1);
1706  scalar_type a0 = gmm::sgn(s0), a1 = gmm::sgn(s1);
1707 
1708  bool inv = false;
1709  for (size_type i = 0; i < N; ++i) {
1710  if (K(i, 0) * a0 < K(i, 1) * a1 - 1e-6) break;
1711  if (K(i, 0) * a0 > K(i, 1) * a1 + 1e-6) { inv = true; break; }
1712  }
1713 
1714  if (a0 < 0.) {
1715  for (size_type i = 1, l = 1; i < k; ++i)
1716  for (size_type j = 0; j <= i; ++j, ++l)
1717  { if (((i-j) % 2) == 1) M(l, l) = -1.0; } // X^(i-j) Y^j
1718  }
1719 
1720  if (a1 < 0.) {
1721  for (size_type i = 1, l = 1; i < k; ++i)
1722  for (size_type j = 0; j <= i; ++j, ++l)
1723  { if ((j % 2) == 1) M(l, l) = -1.0; } // X^(i-j) Y^j
1724  }
1725 
1726  if (inv) {
1727  // std::swap(a0, a1);
1728  for (size_type i = 1, l = 1; i < k; ++i)
1729  for (size_type j = 0; j <= i; ++j, ++l)
1730  { M(l, l) = 0.0; M(l, l+i-2*j) = 1.0; }
1731  }
1732  }
1733 
1734  CIPK_SQUARE_::CIPK_SQUARE_(dim_type k_) {
1735  k = k_;
1736  pgt_stored = 0;
1737 
1739  dim_ = cvr->structure()->dim();
1740  init_cvs_node();
1741  es_degree = k;
1742  is_pol = true;
1743  is_standard_fem = is_lag = is_equiv = false;
1744  base_.resize((k+1)*(k+2)/2);
1745 
1746  std::vector<base_node> C(1);
1747  C[0] = base_node(0.5, 0.5);
1748  pC = bgeot::store_point_tab(C);
1749 
1750  base_poly X, Y;
1751  read_poly(X, 2, "x-0.5"); read_poly(Y, 2, "y-0.5");
1752 
1753  base_[0] = bgeot::one_poly(2);
1754  add_node(ipk_center_dof(2,0), C[0]);
1755 
1756  for (size_type i = 1, l = 1; i < k; ++i)
1757  for (size_type j = 0; j <= i; ++j, ++l) { // X^(i-j) Y^j
1758  base_[l] = base_[0];
1759  for (size_type n = 0; n < i-j; ++n) base_[l] *= X;
1760  for (size_type n = 0; n < j; ++n) base_[l] *= Y;
1761 
1762  add_node(ipk_center_dof(2,l), C[0]);
1763  }
1764  }
1765 
1766  static pfem CIPK_SQUARE(fem_param_list &params,
1767  std::vector<dal::pstatic_stored_object> &dependencies) {
1768  GMM_ASSERT1(params.size() == 1, "Bad number of parameters : "
1769  << params.size() << " should be 1.");
1770  GMM_ASSERT1(params[0].type() == 0, "Bad type of parameters");
1771  int k = int(::floor(params[0].num() + 0.01));
1772  GMM_ASSERT1(k >= 0 && k < 50 && double(k) == params[0].num(),
1773  "Bad parameter");
1774  pfem p = std::make_shared<CIPK_SQUARE_>(dim_type(k));
1775  dependencies.push_back(p->ref_convex(0));
1776  dependencies.push_back(p->node_tab(0));
1777  return p;
1778  }
1779 
1780 
1781 
1782 
1783 
1784  /* ******************************************************************** */
1785  /* Element RTk on simplices. */
1786  /* ******************************************************************** */
1787 
1788  struct RTk_ : public fem<base_poly> {
1789  dim_type nc, k;
1790  mutable base_matrix K;
1791  base_small_vector norient;
1792  mutable bgeot::pgeotrans_precomp pgp;
1793  mutable bgeot::pgeometric_trans pgt_stored;
1794  // mutable pfem_precomp pfp;
1795 
1796  virtual void mat_trans(base_matrix &M, const base_matrix &G,
1797  bgeot::pgeometric_trans pgt) const;
1798  RTk_(dim_type nc_, dim_type k_);
1799  };
1800 
1801  void RTk_::mat_trans(base_matrix &M,
1802  const base_matrix &G,
1803  bgeot::pgeometric_trans pgt) const {
1804  dim_type N = dim_type(G.nrows());
1805  gmm::copy(gmm::identity_matrix(), M);
1806  if (pgt != pgt_stored) {
1807  pgt_stored = pgt;
1808  pgp = bgeot::geotrans_precomp(pgt, node_tab(0), 0);
1809  // pfp = fem_precomp(this, node_tab(0), 0);
1810  }
1811  GMM_ASSERT1(N == nc, "Sorry, this element works only in dimension " << nc);
1812 
1813  gmm::mult(G, pgp->grad(0), K); gmm::lu_inverse(K);
1814  for (unsigned j = 0; j <= nb_dof(0); ++j) {
1815 
1816  if (faces_of_dof(0, j).size()) {
1817  unsigned nf = faces_of_dof(0, j)[0];
1818  if (!(pgt->is_linear()))
1819  { gmm::mult(G, pgp->grad(j), K); gmm::lu_inverse(K); }
1821  gmm::mult(gmm::transposed(K), cvr->normals()[nf], n);
1822 
1823  M(j,j) = gmm::vect_norm2(n);
1824  n /= M(j,j);
1825  scalar_type ps = gmm::vect_sp(n, norient);
1826 
1827  if (ps < 0) M(j, j) *= scalar_type(-1);
1828  if (gmm::abs(ps) < 1E-8)
1829  GMM_WARNING2("RTk : The normal orientation may be incorrect");
1830  }
1831  }
1832  }
1833 
1834  // Raviart-Thomas Element on simplices, dimension d and degree k
1835  // The dof nodes are on the Lagrange lattice of a Lagrange P_(k+2)
1836  // The internal nodes (i.e. a P_(k-1) lattice) correspond to vectorial
1837  // Lagrange dof and the nodes on the boundary which are one oly one face
1838  // (i.e. internal to one face) correspond to a normal component dof.
1839  // The orientation of the normal component dof is selected in comparaison to
1840  // a the fixed direction (pi, pi^2, pi^3) arbitrarily chosen.
1841  // The number of ddl is (k+d+1)*(k+d-1)!/(k! (d-1)!)
1842  // The definition of RTk is
1843  // RTk = (Pk)^d + x(Pk)
1844  // But this is not a direct sum, in fact a direct sum is given by
1845  // RTk = (Pk)^d + x(Pk \ P(k-1))
1846  RTk_::RTk_(dim_type nc_, dim_type k_) {
1847  nc = nc_; k = k_;
1848  pgt_stored = 0;
1849  gmm::resize(K, nc, nc);
1850  gmm::resize(norient, nc);
1851  norient[0] = M_PI;
1852  for (unsigned i = 1; i < nc; ++i) norient[i] = norient[i-1]*M_PI;
1853 
1854  cvr = bgeot::simplex_of_reference(nc);
1855  dim_ = cvr->structure()->dim();
1856  init_cvs_node();
1857  es_degree = k;
1858  is_pol = true;
1859  is_standard_fem = is_lag = is_equiv = false;
1860  ntarget_dim = nc;
1861  vtype = VECTORIAL_PRIMAL_TYPE;
1862 
1863  bgeot::pconvex_ref cvn
1865 
1866  size_type nddl = (k+nc+1);
1867  for (unsigned i = 1; i < nc; ++i) nddl *= (k+i);
1868  for (unsigned i = 1; i < nc; ++i) nddl /= i;
1869  std::vector<bgeot::base_poly> base_RT(nddl*nc, base_poly(nc,0));
1870 
1871  // Building a simple base of RTk
1872  PK_fem_ PK(nc, k); // First (PK)^d
1873  size_type nddl_pk = (PK.base()).size();
1874  for (unsigned i = 0; i < nddl_pk; ++i)
1875  for (unsigned j = 0; j < nc; ++j) {
1876  base_RT[i*nc + j * (nddl_pk*nc+1)] = PK.base()[i];
1877  }
1878  unsigned l = 0;
1879  bgeot::power_index pi(nc);
1880  do { // Second, searching for degree k monomials
1881  base_poly p0(nc,0); p0.add_monomial(1., pi);
1882 
1883  if (pi.degree() == k) {
1884  for (dim_type j = 0; j < nc; ++j) {
1885  base_poly p(nc,0); p.add_monomial(1., pi);
1886  base_RT[nddl_pk*nc*nc + l * nc + j] = p * base_poly(nc, 1, j);
1887  }
1888  ++l;
1889  }
1890  for (dim_type j = 0; j < nc; ++j)
1891  { pi[j]++; if (pi[j] == k+1) pi[j] = 0; else break; }
1892  } while(pi.degree() != 0);
1893  GMM_ASSERT2(nddl_pk*nc+l == nddl, "Internal error");
1894 
1895  // Estimating the base functions on the dofs
1896  base_matrix A(nddl, nddl);
1897  unsigned ipoint = 0;
1898  for (unsigned i = 0; i < cvn->nb_points(); ++i) {
1899  l = 0; unsigned cpt_found = 0;
1900  for(dim_type j = 0; j < nc+1; ++j)
1901  if (gmm::abs(cvn->is_in_face(j, cvn->points()[i])) < 1E-10)
1902  { l = j; cpt_found++; }
1903 
1904  switch (cpt_found) {
1905  case 0 :
1906  for (unsigned j = 0; j < nddl; ++j) {
1907  for (unsigned m = 0; m < nc; ++m)
1908  A(ipoint+m, j) = base_RT[j*nc+m].eval(cvn->points()[i].begin());
1909  }
1910  for (dim_type m = 0; m < nc; ++m)
1911  add_node(to_coord_dof(lagrange_dof(nc), m), cvn->points()[i]);
1912 
1913  ipoint += nc; break;
1914  case 1 :
1915  for (unsigned j = 0; j < nddl; ++j) {
1916  base_small_vector v(nc);
1917  for (unsigned m = 0; m < nc; ++m)
1918  v[m] = base_RT[j*nc+m].eval(cvn->points()[i].begin());
1919  A(ipoint, j) = gmm::vect_sp(v, cvn->normals()[l]);
1920  }
1921  add_node(normal_component_dof(nc), cvn->points()[i]);
1922  ++ipoint; break;
1923  default : break;
1924  }
1925  }
1926  GMM_ASSERT2(ipoint == nddl, "Internal error");
1927 
1928  // Deducing the base of shape functions
1929  gmm::lu_inverse(A);
1930  base_.resize(nddl*nc, base_poly(nc,0));
1931  for (size_type i = 0; i < nddl; ++i)
1932  for (size_type j = 0; j < nddl; ++j)
1933  for (unsigned m = 0; m < nc; ++m)
1934  if (gmm::abs(A(j, i)) > 1e-14)
1935  base_[i+m*nddl] += base_RT[j*nc+m] * A(j, i);
1936  }
1937 
1938  static pfem RTk(fem_param_list &params,
1939  std::vector<dal::pstatic_stored_object> &dependencies) {
1940  GMM_ASSERT1(params.size() == 2, "Bad number of parameters : "
1941  << params.size() << " should be 2.");
1942  GMM_ASSERT1(params[0].type() == 0, "Bad type of parameters");
1943  GMM_ASSERT1(params[1].type() == 0, "Bad type of parameters");
1944  int n = int(::floor(params[0].num() + 0.01));
1945  int k = int(::floor(params[1].num() + 0.01));
1946  GMM_ASSERT1(n > 1 && n < 100 && double(n) == params[0].num(),
1947  "Bad parameter n");
1948  GMM_ASSERT1(k >= 0 && k < 100 && double(k) == params[1].num(),
1949  "Bad parameter k");
1950  pfem p = std::make_shared<RTk_>(dim_type(n), dim_type(k));
1951  dependencies.push_back(p->ref_convex(0));
1952  dependencies.push_back(p->node_tab(0));
1953  return p;
1954  }
1955 
1956 
1957 
1958  // struct P1_RT0_ : public fem<base_poly> {
1959  // dim_type nc;
1960  // mutable base_matrix K;
1961  // base_small_vector norient;
1962  // mutable bgeot::pgeotrans_precomp pgp;
1963  // mutable bgeot::pgeometric_trans pgt_stored;
1964  // // mutable pfem_precomp pfp;
1965 
1966  // virtual void mat_trans(base_matrix &M, const base_matrix &G,
1967  // bgeot::pgeometric_trans pgt) const;
1968  // P1_RT0_(dim_type nc_);
1969  // };
1970 
1971  // void P1_RT0_::mat_trans(base_matrix &M,
1972  // const base_matrix &G,
1973  // bgeot::pgeometric_trans pgt) const {
1974  // dim_type N = dim_type(G.nrows());
1975  // gmm::copy(gmm::identity_matrix(), M);
1976  // if (pgt != pgt_stored) {
1977  // pgt_stored = pgt;
1978  // pgp = bgeot::geotrans_precomp(pgt, node_tab(0), 0);
1979  // // pfp = fem_precomp(this, node_tab(0), 0);
1980  // }
1981  // GMM_ASSERT1(N == nc, "Sorry, this element works only in dimension " << nc);
1982 
1983  // gmm::mult(G, pgp->grad(0), K); gmm::lu_inverse(K);
1984  // for (unsigned i = 0; i <= nc; ++i) {
1985  // if (!(pgt->is_linear()))
1986  // { gmm::mult(G, pgp->grad(i), K); gmm::lu_inverse(K); }
1987  // bgeot::base_small_vector n(nc);
1988  // gmm::mult(gmm::transposed(K), cvr->normals()[i], n);
1989 
1990  // M(i,i) = gmm::vect_norm2(n);
1991  // n /= M(i,i);
1992  // scalar_type ps = gmm::vect_sp(n, norient);
1993  // if (ps < 0) M(i, i) *= scalar_type(-1);
1994  // if (gmm::abs(ps) < 1E-8)
1995  // GMM_WARNING2("RT0 : The normal orientation may be incorrect");
1996  // }
1997  // }
1998 
1999  // // The dof of this RT0 are not the integral on the edges or faces of the
2000  // // normal component but the normal component on the midpoint of each edge/face
2001  // // The reason : easier to deal in case of nonlinear transformation (otherwise
2002  // // an integral with several Gauss points would be necessary to compute on
2003  // // edges / faces)
2004  // // Shape fonctions on the reference element for nc = 2
2005  // // sqrt(2)(x, y) ; (x-1, y) ; (x, y-1)
2006  // // The shape functions on the real element are K \phi ||K^{-T}n_i||, where
2007  // // K is the gradient of the transformation.
2008  // P1_RT0_::P1_RT0_(dim_type nc_) {
2009  // nc = nc_;
2010  // pgt_stored = 0;
2011  // gmm::resize(K, nc, nc);
2012  // gmm::resize(norient, nc);
2013  // norient[0] = M_PI;
2014  // for (unsigned i = 1; i < nc; ++i) norient[i] = norient[i-1]*M_PI;
2015 
2016  // cvr = bgeot::simplex_of_reference(nc);
2017  // dim_ = cvr->structure()->dim();
2018  // init_cvs_node();
2019  // es_degree = 1;
2020  // is_pol = true;
2021  // is_standard_fem = is_lag = is_equiv = false;
2022  // ntarget_dim = nc;
2023  // vtype = VECTORIAL_PRIMAL_TYPE;
2024  // base_.resize(nc*(nc+1));
2025 
2026 
2027  // for (size_type j = 0; j < nc; ++j)
2028  // for (size_type i = 0; i <= nc; ++i) {
2029  // base_[i+j*(nc+1)] = base_poly(nc, 1, short_type(j));
2030  // if (i-1 == j) base_[i+j*(nc+1)] -= bgeot::one_poly(nc);
2031  // if (i == 0) base_[i+j*(nc+1)] *= sqrt(opt_long_scalar_type(nc));
2032  // }
2033 
2034  // base_node pt(nc);
2035  // pt.fill(scalar_type(1)/scalar_type(nc));
2036  // add_node(normal_component_dof(nc), pt);
2037 
2038  // for (size_type i = 0; i < nc; ++i) {
2039  // pt[i] = scalar_type(0);
2040  // add_node(normal_component_dof(nc), pt);
2041  // pt[i] = scalar_type(1)/scalar_type(nc);
2042 
2043  // }
2044  // }
2045 
2046  static pfem P1_RT0(fem_param_list &params,
2047  std::vector<dal::pstatic_stored_object> &) {
2048  GMM_ASSERT1(params.size() == 1, "Bad number of parameters : "
2049  << params.size() << " should be 1.");
2050  GMM_ASSERT1(params[0].type() == 0, "Bad type of parameters");
2051  int n = int(::floor(params[0].num() + 0.01));
2052  GMM_ASSERT1(n > 1 && n < 100 && double(n) == params[0].num(),
2053  "Bad parameter");
2054  std::stringstream name;
2055  name << "FEM_RTK(" << n << ",0)";
2056  return fem_descriptor(name.str());
2057 
2058  // pfem p = std::make_shared<P1_RT0_>(dim_type(n));
2059  // dependencies.push_back(p->ref_convex(0));
2060  // dependencies.push_back(p->node_tab(0));
2061  // return p;
2062  }
2063 
2064 
2065  /* ******************************************************************** */
2066  /* Element RT0 on parallelepideds. */
2067  /* ******************************************************************** */
2068 
2069  struct P1_RT0Q_ : public fem<base_poly> {
2070  dim_type nc;
2071  mutable base_matrix K;
2072  base_small_vector norient;
2073  mutable bgeot::pgeotrans_precomp pgp;
2074  mutable bgeot::pgeometric_trans pgt_stored;
2075  // mutable pfem_precomp pfp;
2076 
2077  virtual void mat_trans(base_matrix &M, const base_matrix &G,
2078  bgeot::pgeometric_trans pgt) const;
2079  P1_RT0Q_(dim_type nc_);
2080  };
2081 
2082  void P1_RT0Q_::mat_trans(base_matrix &M,
2083  const base_matrix &G,
2084  bgeot::pgeometric_trans pgt) const {
2085  dim_type N = dim_type(G.nrows());
2086  gmm::copy(gmm::identity_matrix(), M);
2087  if (pgt != pgt_stored) {
2088  pgt_stored = pgt;
2089  pgp = bgeot::geotrans_precomp(pgt, node_tab(0),0);
2090  // pfp = fem_precomp(this, node_tab(0), 0);
2091  }
2092  GMM_ASSERT1(N == nc, "Sorry, this element works only in dimension " << nc);
2093 
2094  gmm::mult(G, pgp->grad(0), K); gmm::lu_inverse(K);
2095  for (unsigned i = 0; i < unsigned(2*nc); ++i) {
2096  if (!(pgt->is_linear()))
2097  { gmm::mult(G, pgp->grad(i), K); gmm::lu_inverse(K); }
2099  gmm::mult(gmm::transposed(K), cvr->normals()[i], n);
2100 
2101  M(i,i) = gmm::vect_norm2(n);
2102  n /= M(i,i);
2103  scalar_type ps = gmm::vect_sp(n, norient);
2104  if (ps < 0) M(i, i) *= scalar_type(-1);
2105  if (gmm::abs(ps) < 1E-8)
2106  GMM_WARNING2("RT0Q : The normal orientation may be incorrect");
2107  }
2108  }
2109 
2110  P1_RT0Q_::P1_RT0Q_(dim_type nc_) {
2111  nc = nc_;
2112  pgt_stored = 0;
2113  gmm::resize(K, nc, nc);
2114  gmm::resize(norient, nc);
2115  norient[0] = M_PI;
2116  for (unsigned i = 1; i < nc; ++i) norient[i] = norient[i-1]*M_PI;
2117 
2119  dim_ = cvr->structure()->dim();
2120  init_cvs_node();
2121  es_degree = 1;
2122  is_pol = true;
2123  is_standard_fem = is_lag = is_equiv = false;
2124  ntarget_dim = nc;
2125  vtype = VECTORIAL_PRIMAL_TYPE;
2126  base_.resize(nc*2*nc);
2127 
2128  for (size_type j = 0; j < size_type(nc*2*nc); ++j)
2129  base_[j] = bgeot::null_poly(nc);
2130 
2131  for (short_type i = 0; i < nc; ++i) {
2132  base_[2*i+i*2*nc] = base_poly(nc, 1, i);
2133  base_[2*i+1+i*2*nc] = base_poly(nc, 1, i) - bgeot::one_poly(nc);
2134  }
2135 
2136  base_node pt(nc); pt.fill(0.5);
2137 
2138  for (size_type i = 0; i < nc; ++i) {
2139  pt[i] = 1.0;
2140  add_node(normal_component_dof(nc), pt);
2141  pt[i] = 0.0;
2142  add_node(normal_component_dof(nc), pt);
2143  pt[i] = 0.5;
2144  }
2145  }
2146 
2147  static pfem P1_RT0Q(fem_param_list &params,
2148  std::vector<dal::pstatic_stored_object> &dependencies) {
2149  GMM_ASSERT1(params.size() == 1, "Bad number of parameters : "
2150  << params.size() << " should be 1.");
2151  GMM_ASSERT1(params[0].type() == 0, "Bad type of parameters");
2152  int n = int(::floor(params[0].num() + 0.01));
2153  GMM_ASSERT1(n > 1 && n < 100 && double(n) == params[0].num(),
2154  "Bad parameter");
2155  pfem p = std::make_shared<P1_RT0Q_>(dim_type(n));
2156  dependencies.push_back(p->ref_convex(0));
2157  dependencies.push_back(p->node_tab(0));
2158  return p;
2159  }
2160 
2161 
2162  /* ******************************************************************** */
2163  /* Element BDMk on simplices. */
2164  /* ******************************************************************** */
2165 
2166  struct BDMk_ : public fem<base_poly> {
2167  dim_type nc, k;
2168  mutable base_matrix K;
2169  base_small_vector norient;
2170  mutable bgeot::pgeotrans_precomp pgp;
2171  mutable bgeot::pgeometric_trans pgt_stored;
2172  // mutable pfem_precomp pfp;
2173 
2174  virtual void mat_trans(base_matrix &M, const base_matrix &G,
2175  bgeot::pgeometric_trans pgt) const;
2176  BDMk_(dim_type nc_, dim_type k_);
2177  };
2178 
2179  void BDMk_::mat_trans(base_matrix &M,
2180  const base_matrix &G,
2181  bgeot::pgeometric_trans pgt) const {
2182  dim_type N = dim_type(G.nrows());
2183  gmm::copy(gmm::identity_matrix(), M);
2184  if (pgt != pgt_stored) {
2185  pgt_stored = pgt;
2186  pgp = bgeot::geotrans_precomp(pgt, node_tab(0), 0);
2187  // pfp = fem_precomp(this, node_tab(0), 0);
2188  }
2189  GMM_ASSERT1(N == nc, "Sorry, this element works only in dimension " << nc);
2190 
2191  gmm::mult(G, pgp->grad(0), K); gmm::lu_inverse(K);
2192  for (unsigned j = 0; j <= nb_dof(0); ++j) {
2193 
2194  if (faces_of_dof(0, j).size()) {
2195  unsigned nf = faces_of_dof(0, j)[0];
2196  if (!(pgt->is_linear()))
2197  { gmm::mult(G, pgp->grad(j), K); gmm::lu_inverse(K); }
2199  gmm::mult(gmm::transposed(K), cvr->normals()[nf], n);
2200 
2201  M(j,j) = gmm::vect_norm2(n);
2202  n /= M(j,j);
2203  scalar_type ps = gmm::vect_sp(n, norient);
2204 
2205  if (ps < 0) M(j, j) *= scalar_type(-1);
2206  if (gmm::abs(ps) < 1E-8)
2207  GMM_WARNING2("RTk : The normal orientation may be incorrect");
2208  }
2209  }
2210  }
2211 
2212  // Brezzi-Douglas-Marini Element on simplices, dimension d and degree k=1 or 2
2213  // The orientation of the normal component dof is selected in comparison to
2214  // the fixed direction (pi, pi^2, pi^3) arbitrarily chosen.
2215  // The definition of RTk is
2216  // BDMk = (Pk)^d
2217 
2218  BDMk_::BDMk_(dim_type nc_, dim_type k_) {
2219  nc = nc_; k = k_;
2220  pgt_stored = 0;
2221  gmm::resize(K, nc, nc);
2222  gmm::resize(norient, nc);
2223  norient[0] = M_PI;
2224  for (unsigned i = 1; i < nc; ++i) norient[i] = norient[i-1]*M_PI;
2225 
2226  cvr = bgeot::simplex_of_reference(nc);
2227  dim_ = cvr->structure()->dim();
2228  init_cvs_node();
2229  es_degree = k;
2230  is_pol = true;
2231  is_standard_fem = is_lag = is_equiv = false;
2232  ntarget_dim = nc;
2233  vtype = VECTORIAL_PRIMAL_TYPE;
2234 
2235  bgeot::pconvex_ref cvn
2237 
2238  // Building a simple base of BDMk
2239  PK_fem_ PK(nc, k);
2240  size_type nddl_pk = (PK.base()).size(), nddl = nddl_pk * nc;
2241  std::vector<bgeot::base_poly> base_BDM(nddl*nc, base_poly(nc,0));
2242  for (unsigned i = 0; i < nddl_pk; ++i)
2243  for (unsigned j = 0; j < nc; ++j) {
2244  base_BDM[i*nc + j * (nddl_pk*nc+1)] = PK.base()[i];
2245  }
2246  GMM_ASSERT2(nddl_pk*nc == nddl, "Internal error");
2247 
2248  // Estimating the base functions on the dofs
2249  base_matrix A(nddl, nddl);
2250  unsigned ipoint = 0;
2251  for (unsigned i = 0; i < cvn->nb_points(); ++i) {
2252  unsigned l = 0; unsigned cpt_found = 0;
2253  for(dim_type j = 0; j < nc+1; ++j)
2254  if (gmm::abs(cvn->is_in_face(j, cvn->points()[i])) < 1E-10)
2255  { l = j; cpt_found++; }
2256 
2257  if (cpt_found == 1) {
2258  for (unsigned j = 0; j < nddl; ++j) {
2259  base_small_vector v(nc);
2260  for (unsigned m = 0; m < nc; ++m)
2261  v[m] = base_BDM[j*nc+m].eval(cvn->points()[i].begin());
2262  A(ipoint, j) = gmm::vect_sp(v, cvn->normals()[l]);
2263  }
2264  add_node(normal_component_dof(nc), cvn->points()[i]);
2265  ++ipoint;
2266  }
2267  }
2268 
2269  base_node barycenter(nc); barycenter.fill(1./(nc+1));
2270 
2271  if (k > 1) {
2272  bgeot::pbasic_mesh pm;
2273  bgeot::pmesh_precomposite pmp;
2274 
2275  structured_mesh_for_convex(PK.ref_convex(0), 1, pm, pmp);
2276  mesh m(*pm);
2277  mesh_fem mf(m);
2278  mf.set_classical_finite_element(pm->convex_index(), bgeot::dim_type(k-1));
2279  mesh_fem mfd(m);
2280  mfd.set_qdim(nc);
2281  mfd.set_classical_finite_element(pm->convex_index(), k);
2282  mesh_im mim(m);
2283  mim.set_integration_method(bgeot::dim_type(k*(k-1)));
2284 
2285  gmm::sub_interval Iu(0, mfd.nb_dof()), Ip(Iu.last(), mf.nb_dof());
2286  base_vector u(mfd.nb_dof()), p(mf.nb_dof());
2287  ga_workspace workspace;
2288  workspace.add_fem_variable("u", mfd, Iu, u);
2289  workspace.add_fem_variable("p", mf, Ip, p);
2290  workspace.add_expression("Div(u).Test_p", mim);
2291  workspace.assembly(2);
2292  gmm::sub_interval IA1(ipoint, mf.nb_dof()), IA2(0, nddl);
2293  if (gmm::mat_nrows(workspace.assembled_matrix()))
2294  gmm::add(gmm::sub_matrix(workspace.assembled_matrix(), Ip, Iu),
2295  gmm::sub_matrix(A, IA1, IA2));
2296 
2297  for (size_type i = 0; i < mf.nb_dof(); ++i) {
2298  add_node(ipk_center_dof(nc, ipoint), barycenter);
2299  ++ipoint;
2300  }
2301  }
2302 
2303  if (k > 2) { // Completing the base with an orthogonal base of the kernel
2304 # if defined(GMM_USES_LAPACK)
2305  base_vector EIG(nddl);
2306  base_matrix U(nddl, nddl), V(nddl, nddl), AA(A);
2307  gmm::svd(AA, U, V, EIG);
2308  gmm::clean(V, 1E-14);
2309 
2310  for (size_type i = 0; i < nddl; ++i)
2311  if (gmm::abs(EIG[i]) < 1E-16) {
2312  gmm::copy(gmm::mat_row(V, i), gmm::mat_row(A, ipoint));
2313  add_node(ipk_center_dof(nc, ipoint), barycenter); ++ipoint;
2314  }
2315 # else
2316  GMM_ASSERT2(false, "You need Lapack to useget BDMk with k > 2");
2317 # endif
2318  }
2319 
2320  GMM_ASSERT2(ipoint == nddl, "Internal error");
2321 
2322  // Deducing the base of shape functions
2323  gmm::lu_inverse(A);
2324  base_.resize(nddl*nc, base_poly(nc,0));
2325  for (size_type i = 0; i < nddl; ++i)
2326  for (size_type j = 0; j < nddl; ++j)
2327  for (unsigned m = 0; m < nc; ++m)
2328  if (gmm::abs(A(j, i)) > 1e-14)
2329  base_[i+m*nddl] += base_BDM[j*nc+m] * A(j, i);
2330 
2331  // for (size_type i = 0; i < nddl; ++i)
2332  // for (unsigned m = 0; m < nc; ++m)
2333  // cout << base_[i+m*nddl] << endl;
2334  }
2335 
2336  static pfem BDMk(fem_param_list &params,
2337  std::vector<dal::pstatic_stored_object> &dependencies) {
2338  GMM_ASSERT1(params.size() == 2, "Bad number of parameters for BDM element: "
2339  << params.size() << " should be 2.");
2340  GMM_ASSERT1(params[0].type() == 0, "Bad type of parameters");
2341  GMM_ASSERT1(params[1].type() == 0, "Bad type of parameters");
2342  int n = int(::floor(params[0].num() + 0.01));
2343  int k = int(::floor(params[1].num() + 0.01));
2344  GMM_ASSERT1(n > 1 && n < 100 && double(n) == params[0].num(),
2345  "Bad parameter n for BDM element");
2346  GMM_ASSERT1(k >= 1 && k < 100 && double(k) == params[1].num(),
2347  "Bad parameter k for BDM element");
2348  pfem p = std::make_shared<BDMk_>(dim_type(n), dim_type(k));
2349  dependencies.push_back(p->ref_convex(0));
2350  dependencies.push_back(p->node_tab(0));
2351  return p;
2352  }
2353 
2354 
2355  /* ******************************************************************** */
2356  /* Nedelec Element. */
2357  /* ******************************************************************** */
2358 
2359  struct P1_nedelec_ : public fem<base_poly> {
2360  dim_type nc;
2361  base_small_vector norient;
2362  std::vector<base_small_vector> tangents;
2363  mutable bgeot::pgeotrans_precomp pgp;
2364  mutable bgeot::pgeometric_trans pgt_stored;
2365  mutable pfem_precomp pfp;
2366 
2367  virtual void mat_trans(base_matrix &M, const base_matrix &G,
2368  bgeot::pgeometric_trans pgt) const;
2369  P1_nedelec_(dim_type nc_);
2370  };
2371 
2372  void P1_nedelec_::mat_trans(base_matrix &M, const base_matrix &G,
2373  bgeot::pgeometric_trans pgt) const {
2374  bgeot::base_small_vector t(nc), v(nc);
2375  GMM_ASSERT1(G.nrows() == nc,
2376  "Sorry, this element works only in dimension " << nc);
2377 
2378  if (pgt != pgt_stored) {
2379  pgt_stored = pgt;
2380  pgp = bgeot::geotrans_precomp(pgt, node_tab(0), 0);
2381  pfp = fem_precomp(std::make_shared<P1_nedelec_>(nc), node_tab(0), 0);
2382  }
2383  fem_interpolation_context ctx(pgp,pfp,0,G,0);
2384 
2385  for (unsigned i = 0; i < nb_dof(0); ++i) {
2386  ctx.set_ii(i);
2387  gmm::mult(ctx.K(), tangents[i], t);
2388  t /= gmm::vect_norm2(t);
2389  gmm::mult(gmm::transposed(ctx.B()), t, v);
2390  scalar_type ps = gmm::vect_sp(t, norient);
2391  if (ps < 0) v *= scalar_type(-1);
2392  if (gmm::abs(ps) < 1E-8)
2393  GMM_WARNING2("Nedelec element: "
2394  "The normal orientation may be incorrect");
2395 
2396  const bgeot::base_tensor &tt = pfp->val(i);
2397  for (size_type j = 0; j < nb_dof(0); ++j) {
2398  scalar_type a = scalar_type(0);
2399  for (size_type k = 0; k < nc; ++k) a += tt(j, k) * v[k];
2400  M(j, i) = a;
2401  }
2402  }
2403  // In fact matrix M is diagonal (at least for linear transformations).
2404  // The computation can be simplified.
2405  gmm::lu_inverse(M);
2406  }
2407 
2408  P1_nedelec_::P1_nedelec_(dim_type nc_) {
2409  nc = nc_;
2410  pgt_stored = 0;
2411  gmm::resize(norient, nc);
2412  norient[0] = M_PI;
2413  for (unsigned i = 1; i < nc; ++i) norient[i] = norient[i-1]*M_PI;
2414 
2415  cvr = bgeot::simplex_of_reference(nc);
2416  dim_ = cvr->structure()->dim();
2417  init_cvs_node();
2418  es_degree = 1;
2419  is_pol = true;
2420  is_standard_fem = is_lag = is_equiv = false;
2421  ntarget_dim = nc;
2422  vtype = VECTORIAL_DUAL_TYPE;
2423  base_.resize(nc*(nc+1)*nc/2);
2424  tangents.resize(nc*(nc+1)*nc/2);
2425 
2426  std::vector<base_poly> lambda(nc+1);
2427  std::vector<base_vector> grad_lambda(nc+1);
2428  lambda[0] = bgeot::one_poly(nc);
2429  gmm::resize(grad_lambda[0], nc);
2430  gmm::fill(grad_lambda[0], scalar_type(-1));
2431  for (size_type i = 1; i <= nc; ++i) {
2432  lambda[i] = base_poly(nc, 1, short_type(i-1));
2433  lambda[0] -= lambda[i];
2434  gmm::resize(grad_lambda[i], nc);
2435  grad_lambda[i][i-1] = 1;
2436  }
2437 
2438  size_type j = 0;
2439  for (size_type k = 0; k <= nc; ++k)
2440  for (size_type l = k+1; l <= nc; ++l, ++j) {
2441  for (size_type i = 0; i < nc; ++i) {
2442  base_[j+i*(nc*(nc+1)/2)] = lambda[k] * grad_lambda[l][i]
2443  - lambda[l] * grad_lambda[k][i];
2444  }
2445 
2446  base_node pt = (cvr->points()[k] + cvr->points()[l]) / scalar_type(2);
2447  add_node(edge_component_dof(nc), pt);
2448  tangents[j] = cvr->points()[l] - cvr->points()[k];
2449  tangents[j] /= gmm::vect_norm2(tangents[j]);
2450  }
2451  }
2452 
2453  static pfem P1_nedelec(fem_param_list &params,
2454  std::vector<dal::pstatic_stored_object> &dependencies) {
2455  GMM_ASSERT1(params.size() == 1, "Bad number of parameters : "
2456  << params.size() << " should be 1.");
2457  GMM_ASSERT1(params[0].type() == 0, "Bad type of parameters");
2458  int n = int(::floor(params[0].num() + 0.01));
2459  GMM_ASSERT1(n > 1 && n < 100 && double(n) == params[0].num(),
2460  "Bad parameter");
2461  pfem p = std::make_shared<P1_nedelec_>(dim_type(n));
2462  dependencies.push_back(p->ref_convex(0));
2463  dependencies.push_back(p->node_tab(0));
2464  return p;
2465  }
2466 
2467 
2468  /* ******************************************************************** */
2469  /* P1 element with a bubble base function on a face : type lagrange */
2470  /* ******************************************************************** */
2471 
2472  struct P1_wabbfoafla_ : public PK_fem_
2473  { // idem elt prec mais avec raccord lagrange. A faire en dim. quelconque ..
2474  P1_wabbfoafla_();
2475  };
2476 
2477  P1_wabbfoafla_::P1_wabbfoafla_() : PK_fem_(2, 1) {
2478  unfreeze_cvs_node();
2479  es_degree = 2;
2480  base_node pt(2); pt.fill(0.5);
2481  add_node(lagrange_dof(2), pt);
2482  base_.resize(nb_dof(0));
2483 
2484  read_poly(base_[0], 2, "1 - y - x");
2485  read_poly(base_[1], 2, "x*(1 - 2*y)");
2486  read_poly(base_[2], 2, "y*(1 - 2*x)");
2487  read_poly(base_[3], 2, "4*x*y");
2488  }
2489 
2490  static pfem P1_with_bubble_on_a_face_lagrange(fem_param_list &params,
2491  std::vector<dal::pstatic_stored_object> &dependencies) {
2492  GMM_ASSERT1(params.size() == 0, "Bad number of parameters");
2493  pfem p = std::make_shared<P1_wabbfoafla_>();
2494  dependencies.push_back(p->ref_convex(0));
2495  dependencies.push_back(p->node_tab(0));
2496  return p;
2497  }
2498 
2499 
2500  /* ******************************************************************** */
2501  /* PK Gauss-Lobatto element on the segment */
2502  /* ******************************************************************** */
2503 
2504  static const double fem_coef_gausslob_1[4] =
2505  { 1.000000000000000e+00, -1.000000000000000e+00, 0.000000000000000e-01,
2506  1.000000000000000e+00 };
2507 
2508  static const double fem_coef_gausslob_2[9] =
2509  { 1.000000000000000e+00, -3.000000000000000e+00, 2.000000000000000e+00,
2510  0.000000000000000e-01, 4.000000000000000e+00, -4.000000000000000e+00,
2511  0.000000000000000e-01, -1.000000000000000e+00, 2.000000000000000e+00 };
2512 
2513  static const double fem_coef_gausslob_3[16] =
2514  { 1.000000000000000e+00, -6.000000000000000e+00, 1.000000000000000e+01,
2515  -5.000000000000000e+00, 0.000000000000000e-01, 8.090169943749474e+00,
2516  -1.927050983124842e+01, 1.118033988749895e+01, 0.000000000000000e-01,
2517  -3.090169943749474e+00, 1.427050983124842e+01, -1.118033988749895e+01,
2518  0.000000000000000e-01, 1.000000000000000e+00, -5.000000000000000e+00,
2519  5.000000000000000e+00 };
2520 
2521  static const double fem_coef_gausslob_4[25] =
2522  { 1.000000000000000e+00, -1.000000000000000e+01, 3.000000000000000e+01,
2523  -3.500000000000000e+01, 1.400000000000000e+01, 0.000000000000000e-01,
2524  1.351300497744848e+01, -5.687234826567877e+01, 7.602600995489696e+01,
2525  -3.266666666666667e+01, 0.000000000000000e-01, -5.333333333333333e+0,
2526  4.266666666666667e+01, -7.466666666666667e+01, 3.733333333333333e+01,
2527  0.000000000000000e-01, 2.820328355884853e+00, -2.479431840098789e+01,
2528  5.464065671176971e+01, -3.266666666666667e+01, 0.000000000000000e-01,
2529  -1.000000000000000e+00, 9.000000000000000e+00, -2.100000000000000e+01,
2530  1.400000000000000e+01 };
2531 
2532  static const double fem_coef_gausslob_5[36] =
2533  { 1.000000000000000e+00, -1.500000000000000e+01, 7.000000000000000e+01,
2534  -1.400000000000000e+02, 1.260000000000000e+02, -4.200000000000000e+01,
2535  0.000000000000000e-01, 2.028283187263934e+01, -1.315819844629968e+02,
2536  2.996878573260126e+02, -2.884609153819731e+02, 1.000722106463179e+02,
2537  0.000000000000000e-01, -8.072374540610696e+00, 9.849823568607377e+01,
2538  -2.894574355386068e+02, 3.201990314777874e+02, -1.211674570846437e+02,
2539  0.000000000000000e-01, 4.489369296352334e+00, -6.035445290945900e+01,
2540  2.203358804738940e+02, -2.856382539454310e+02, 1.211674570846437e+02,
2541  0.000000000000000e-01, -2.699826628380976e+00, 3.743820168638206e+01,
2542  -1.465663022612998e+02, 2.119001378496167e+02, -1.000722106463179e+02,
2543  0.000000000000000e-01, 1.000000000000000e+00, -1.400000000000000e+01,
2544  5.600000000000000e+01, -8.400000000000000e+01, 4.200000000000000e+01 };
2545 
2546  static const double fem_coef_gausslob_6[49] =
2547  { 1.000000000000000e+00, -2.100000000000000e+01, 1.400000000000000e+02,
2548  -4.200000000000000e+02, 6.300000000000000e+02, -4.620000000000000e+02,
2549  1.320000000000000e+02, 0.000000000000000e-01, 2.840315320583963e+01,
2550  -2.618707992013254e+02, 8.915455952644434e+02, -1.426720320066430e+03,
2551  1.086906031987037e+03, -3.182636611895653e+02, 0.000000000000000e-01,
2552  -1.133797045109102e+01, 1.954053162272040e+02, -8.515354909154440e+02,
2553  1.555570646517052e+03, -1.285566162567286e+03, 3.974636611895653e+02,
2554  0.000000000000000e-01, 6.400000000000000e+00, -1.216000000000000e+02,
2555  6.528000000000000e+02, -1.382400000000000e+03, 1.267200000000000e+03,
2556  -4.224000000000000e+02, 0.000000000000000e-01, -4.099929626153486e+00,
2557  8.051601475380118e+01, -4.643586932712080e+02, 1.089694751524101e+03,
2558  -1.099215804570106e+03, 3.974636611895653e+02, 0.000000000000000e-01,
2559  2.634746871404869e+00, -5.245053177967978e+01, 3.115485889222086e+02,
2560  -7.661450779747230e+02, 8.226759351503546e+02, -3.182636611895653e+02,
2561  0.000000000000000e-01, -1.000000000000000e+00, 2.000000000000000e+01,
2562  -1.200000000000000e+02, 3.000000000000000e+02, -3.300000000000000e+02,
2563  1.320000000000000e+02 };
2564 
2565  static const double fem_coef_gausslob_7[64] =
2566  { 1.000000000000000e+00, -2.800000000000000e+01, 2.520000000000000e+02,
2567  -1.050000000000000e+03, 2.310000000000000e+03, -2.772000000000000e+03,
2568  1.716000000000000e+03, -4.290000000000000e+02, 0.000000000000000e-01,
2569  3.787519721423474e+01, -4.699045385400572e+02, 2.217166528901653e+03,
2570  -5.195916436930171e+03, 6.469992588404291e+03, -4.101225846986446e+03,
2571  1.042012507936495e+03, 0.000000000000000e-01, -1.513857963869697e+01,
2572  3.497259983590744e+02, -2.101837798737552e+03, 5.599947843186200e+03,
2573  -7.539551580657127e+03, 5.032695631593761e+03, -1.325841514105659e+03,
2574  0.000000000000000e-01, 8.595816328530350e+00, -2.189405837038675e+02,
2575  1.612357003153179e+03, -4.947308401212060e+03, 7.342604827965170e+03,
2576  -5.255204822337236e+03, 1.457896159806284e+03, 0.000000000000000e-01,
2577  -5.620377978515898e+00, 1.480753190084385e+02, -1.171440824431867e+03,
2578  3.964008996775197e+03, -6.427195249873722e+03, 4.950068296306753e+03,
2579  -1.457896159806284e+03, 0.000000000000000e-01, 3.883318851088245e+00,
2580  -1.038534676200790e+02, 8.481025943868683e+02, -3.011828579891082e+03,
2581  5.186049587313396e+03, -4.248194967145850e+03, 1.325841514105659e+03,
2582  0.000000000000000e-01, -2.595374776640464e+00, 6.989727249649080e+01,
2583  -5.793475032722815e+02, 2.106096578071916e+03, -3.744900173152008e+03,
2584  3.192861708569018e+03, -1.042012507936495e+03, 0.000000000000000e-01,
2585  1.000000000000000e+00, -2.700000000000000e+01, 2.250000000000000e+02,
2586  -8.250000000000000e+02, 1.485000000000000e+03, -1.287000000000000e+03,
2587  4.290000000000000e+02 };
2588 
2589  static const double fem_coef_gausslob_8[81] =
2590  { 1.000000000000000e+00, -3.600000000000000e+01, 4.200000000000000e+02,
2591  -2.310000000000000e+03, 6.930000000000000e+03, -1.201200000000000e+04,
2592  1.201200000000000e+04, -6.435000000000000e+03, 1.430000000000000e+03,
2593  0.000000000000000e-01, 4.869949034318613e+01, -7.815432549965997e+02,
2594  4.860656931912704e+03, -1.551737634456316e+04, 2.788918324236022e+04,
2595  -2.854121637661796e+04, 1.553203650368708e+04, -3.490440192125469e+03,
2596  0.000000000000000e-01, -1.947740331442309e+01, 5.805138088476765e+02,
2597  -4.583922431826645e+03, 1.659300238583299e+04, -3.217606831061953e+04,
2598  3.461498040096808e+04, -1.950464316590829e+04, 4.495614716020147e+03,
2599  0.000000000000000e-01, 1.108992781389876e+01, -3.644117397881921e+02,
2600  3.513408770397022e+03, -1.458458798126453e+04, 3.105326914181443e+04,
2601  -3.569574046476449e+04, 2.111700401254369e+04, -5.050031666751820e+03,
2602  0.000000000000000e-01, -7.314285714285714e+00, 2.486857142857143e+02,
2603  -2.574628571428571e+03, 1.174674285714286e+04, -2.719451428571429e+04,
2604  3.347017142857143e+04, -2.091885714285714e+04, 5.229714285714286e+03,
2605  0.000000000000000e-01, 5.181491353118710e+00, -1.789312751409961e+02,
2606  1.913693930879634e+03, -9.161425477258226e+03, 2.246586272145708e+04,
2607  -2.927759904600966e+04, 1.928324932147088e+04, -5.050031666751820e+03,
2608  0.000000000000000e-01, -3.748881746893966e+00, 1.304893011815078e+02,
2609  -1.418925315009559e+03, 6.967886161876575e+03, -1.767073170824305e+04,
2610  2.395969028817416e+04, -1.646027456225289e+04, 4.495614716020147e+03,
2611  0.000000000000000e-01, 2.569661265399177e+00, -8.980255438911062e+01,
2612  9.847166850754155e+02, -4.899241601766511e+03, 1.264999919894514e+04,
2613  -1.754928623032154e+04, 1.239148503331668e+04, -3.490440192125469e+03,
2614  0.000000000000000e-01, -1.000000000000000e+00, 3.500000000000000e+01,
2615  -3.850000000000000e+02, 1.925000000000000e+03, -5.005000000000000e+03,
2616  7.007000000000000e+03, -5.005000000000000e+03, 1.430000000000000e+03 };
2617 
2618  static const double fem_coef_gausslob_9[100] =
2619  { 1.000000000000000e+00, -4.500000000000000e+01, 6.600000000000000e+02,
2620  -4.620000000000000e+03, 1.801800000000000e+04, -4.204200000000000e+04,
2621  6.006000000000000e+04, -5.148000000000000e+04, 2.431000000000000e+04,
2622  -4.862000000000000e+03, 0.000000000000000e-01, 6.087629005856384e+01,
2623  -1.226341297551814e+03, 9.697405499616728e+03, -4.021760400071670e+04,
2624  9.725280603247945e+04, -1.421240159771644e+05, 1.237105621496494e+05,
2625  -5.906188663911807e+04, 1.190819794274692e+04, 0.000000000000000e-01,
2626  -2.435589341485964e+01, 9.095415690555422e+02, -9.111255870205338e+03,
2627  4.276661412893713e+04, -1.114146601604227e+05, 1.709573510663859e+05,
2628  -1.539309822784481e+05, 7.531473186776967e+04, -1.546698442965720e+04,
2629  0.000000000000000e-01, 1.388757697026791e+01, -5.717395054991898e+02,
2630  6.975542885191629e+03, -3.743822964286359e+04, 1.068054892026842e+05,
2631  -1.747039036097183e+05, 1.648204809285228e+05, -8.352714678107793e+04,
2632  1.762561894579012e+04, 0.000000000000000e-01, -9.198709522206266e+00,
2633  3.919017281073292e+02, -5.132147808492991e+03, 3.020136030457121e+04,
2634  -9.337958558844686e+04, 1.629937209113228e+05, -1.619399017586618e+05,
2635  8.553993533073839e+04, -1.866608440961585e+04, 0.000000000000000e-01,
2636  6.589286067498368e+00, -2.852085019651226e+02, 3.859417687766574e+03,
2637  -2.381847798089535e+04, 7.784545414265617e+04, -1.434184925463668e+05,
2638  1.495994578589254e+05, -8.245482435580428e+04, 1.866608440961585e+04,
2639  0.000000000000000e-01, -4.905768350885374e+00, 2.141208512030290e+02,
2640  -2.948048350518040e+03, 1.867520721718195e+04, -6.311993447254502e+04,
2641  1.208313444661297e+05, -1.311255887283438e+05, 7.510342373103317e+04,
2642  -1.762561894579012e+04, 0.000000000000000e-01, 3.659127863806492e+00,
2643  -1.604518938956052e+02, 2.230466872754075e+03, -1.433960781600324e+04,
2644  4.943623515122416e+04, -9.697372467640532e+04, 1.082245668039501e+05,
2645  -6.388812799914516e+04, 1.546698442965720e+04, 0.000000000000000e-01,
2646  -2.551909672185327e+00, 1.121770505458310e+02, -1.567380916112636e+03,
2647  1.015673778978859e+04, -3.539780430762936e+04, 7.040572036581639e+04,
2648  -7.991059497559391e+04, 4.811189484560421e+04, -1.190819794274692e+04,
2649  0.000000000000000e-01, 1.000000000000000e+00, -4.400000000000000e+01,
2650  6.160000000000000e+02, -4.004000000000000e+03, 1.401400000000000e+04,
2651  -2.802800000000000e+04, 3.203200000000000e+04, -1.944800000000000e+04,
2652  4.862000000000000e+03 };
2653 
2654  static const double fem_coef_gausslob_10[121] =
2655  { 1.000000000000000e+00, -5.500000000000000e+01, 9.900000000000000e+02,
2656  -8.580000000000000e+03, 4.204200000000000e+04, -1.261260000000000e+05,
2657  2.402400000000000e+05, -2.917200000000000e+05, 2.187900000000000e+05,
2658  -9.237800000000000e+04, 1.679600000000000e+04, 0.000000000000000e-01,
2659  7.440573476392379e+01, -1.837547309495916e+03, 1.797721877249297e+04,
2660  -9.362519219895049e+04, 2.909773746534557e+05, -5.668103968059107e+05,
2661  6.987888266998443e+05, -5.297630128145374e+05, 2.254581472606030e+05,
2662  -4.123982399226536e+04, 0.000000000000000e-01, -2.977479259019735e+01,
2663  1.361302600480045e+03, -1.684411461834327e+04, 9.915381814787320e+04,
2664  -3.316413447923031e+05, 6.777335995676564e+05, -8.637075009663581e+05,
2665  6.706702925312933e+05, -2.905859066780586e+05, 5.388962900035043e+04,
2666  0.000000000000000e-01, 1.699123898926703e+01, -8.563552206749944e+02,
2667  1.288193007592445e+04, -8.652550760766087e+04, 3.163119148667456e+05,
2668  -6.879421746683590e+05, 9.173107022760963e+05, -7.368809317678005e+05,
2669  3.277210563158369e+05, -6.203762550909711e+04, 0.000000000000000e-01,
2670  -1.128077599537177e+01, 5.884060270969327e+02, -9.496934299975062e+03,
2671  6.981839702203256e+04, -2.759867860090975e+05, 6.390150586777585e+05,
2672  -8.953334100127128e+05, 7.481407085083284e+05, -3.434511859876541e+05,
2673  6.671702685021839e+04, 0.000000000000000e-01, 8.126984126984127e+00,
2674  -4.307301587301587e+02, 7.184253968253968e+03, -5.536101587301587e+04,
2675  2.309526349206349e+05, -5.631187301587302e+05, 8.261892063492063e+05,
2676  -7.184253968253968e+05, 3.412520634920635e+05, -6.825041269841270e+04,
2677  0.000000000000000e-01, -6.131078401763724e+00, 3.277460052754944e+02,
2678  -5.563892337052540e+03, 4.401679638240306e+04, -1.898229640674875e+05,
2679  4.802970424048780e+05, -7.315927845245721e+05, 6.593462428792687e+05,
2680  -3.237190825145298e+05, 6.671702685021839e+04, 0.000000000000000e-01,
2681  4.719539826177156e+00, -2.535442364309725e+02, 4.348374949258725e+03,
2682  -3.493745849693315e+04, 1.537770968392435e+05, -3.987659746141970e+05,
2683  6.242937855878344e+05, -5.790845728346388e+05, 2.926551987751342e+05,
2684  -6.203762550909711e+04, 0.000000000000000e-01, -3.595976071589556e+00,
2685  1.937484128537626e+02, -3.342868418261306e+03, 2.710687970739982e+04,
2686  -1.208013807254569e+05, 3.181552127960248e+05, -5.073176789159280e+05,
2687  4.804304374445346e+05, -2.483103833254456e+05, 5.388962900035043e+04,
2688  0.000000000000000e-01, 2.539125352570295e+00, -1.370261203741934e+02,
2689  2.372031907702074e+03, -1.933271708314826e+04, 8.675745431426523e+04,
2690  -2.305316371991209e+05, 3.716008535065897e+05, -3.564317671210514e+05,
2691  1.869400926620506e+05, -4.123982399226536e+04, 0.000000000000000e-01,
2692  -1.000000000000000e+00, 5.400000000000000e+01, -9.360000000000000e+02,
2693  7.644000000000000e+03, -3.439800000000000e+04, 9.172800000000000e+04,
2694  -1.485120000000000e+05, 1.432080000000000e+05, -7.558200000000000e+04,
2695  1.679600000000000e+04 };
2696 
2697  static const double fem_coef_gausslob_11[144] =
2698  { 1.000000000000000e+00, -6.600000000000000e+01, 1.430000000000000e+03,
2699  -1.501500000000000e+04, 9.009000000000000e+04, -3.363360000000000e+05,
2700  8.168160000000000e+05, -1.312740000000000e+06, 1.385670000000000e+06,
2701  -9.237800000000000e+05, 3.527160000000000e+05, -5.878600000000000e+04,
2702  0.000000000000000e-01, 8.928790437897459e+01, -2.652104227906408e+03,
2703  3.141784850363868e+04, -2.002791716233576e+05, 7.743819221375186e+05,
2704  -1.922871126014229e+06, 3.137025618338122e+06, -3.346678943928588e+06,
2705  2.248625248986712e+06, -8.636670995581690e+05, 1.446085194818801e+05,
2706  0.000000000000000e-01, -3.573451504477809e+01, 1.963011183403142e+03,
2707  -2.937610003978132e+04, 2.114542549822465e+05, -8.792000471014727e+05,
2708  2.288870840565664e+06, -3.858042797257275e+06, 4.213930780912515e+06,
2709  -2.881507044264936e+06, 1.121761824282757e+06, -1.898189887480762e+05,
2710  0.000000000000000e-01, 2.040222049137883e+01, -1.235400296692680e+03,
2711  2.244501976036562e+04, -1.840644193090062e+05, 8.352985709834925e+05,
2712  -2.311501023251837e+06, 4.072373742578464e+06, -4.597525083798586e+06,
2713  3.224564284996090e+06, -1.280533828091591e+06, 2.201577342088092e+05,
2714  0.000000000000000e-01, -1.356395972416294e+01, 8.500434612026409e+02,
2715  -1.656519758544980e+04, 1.484886632288921e+05, -7.274015626850215e+05,
2716  2.139270125221522e+06, -3.953929242730888e+06, 4.636483776329532e+06,
2717  -3.352298848558998e+06, 1.364514095203156e+06, -2.393982879242230e+05,
2718  0.000000000000000e-01, 9.803369220897211e+00, -6.243148521745071e+02,
2719  1.257271925920887e+04, -1.180754347844014e+05, 6.096877374094766e+05,
2720  -1.885008008173690e+06, 3.641310114569300e+06, -4.434918589444567e+06,
2721  3.311645240511804e+06, -1.385401912847929e+06, 2.488026449837513e+05,
2722  0.000000000000000e-01, -7.447686911212630e+00, 4.784415903433910e+02,
2723  -9.808275331323619e+03, 9.456732952354300e+04, -5.045513347291155e+05,
2724  1.617062776783016e+06, -3.237833360324115e+06, 4.079238919323811e+06,
2725  -3.141771586138831e+06, 1.351427181973335e+06, -2.488026449837513e+05,
2726  0.000000000000000e-01, 5.819619912607334e+00, -3.757783851118444e+02,
2727  7.785050290867036e+03, -7.625636515182549e+04, 4.153153824802320e+05,
2728  -1.363841143951918e+06, 2.804561170833446e+06, -3.631789084056234e+06,
2729  2.874063732359706e+06, -1.268867071963298e+06, 2.393982879242230e+05,
2730  0.000000000000000e-01, -4.587084978600364e+00, 2.971291972095372e+02,
2731  -6.195597982053585e+03, 6.128651035627590e+04, -3.381847677955126e+05,
2732  1.128582073344179e+06, -2.364480249965060e+06, 3.125557361498120e+06,
2733  -2.527901385564680e+06, 1.141201248205309e+06, -2.201577342088092e+05,
2734  0.000000000000000e-01, 3.549738472143437e+00, -2.303803824096343e+02,
2735  4.822860472410032e+03, -4.799737703690675e+04, 2.670306747478879e+05,
2736  -9.003482951717774e+05, 1.909697516429202e+06, -2.560483668180433e+06,
2737  2.103933182581560e+06, -9.662470519460815e+05, 1.898189887480762e+05,
2738  0.000000000000000e-01, -2.529605817247381e+00, 1.643527121363626e+02,
2739  -3.448327347881922e+03, 3.443600981453996e+04, -1.924805754474854e+05,
2740  6.528637806490704e+05, -1.394862512471197e+06, 1.886334531344429e+06,
2741  -1.565422824908427e+06, 7.270266147425120e+05, -1.446085194818801e+05,
2742  0.000000000000000e-01, 1.000000000000000e+00, -6.500000000000000e+01,
2743  1.365000000000000e+03, -1.365000000000000e+04, 7.644000000000000e+04,
2744  -2.598960000000000e+05, 5.569200000000000e+05, -7.558200000000000e+05,
2745  6.298500000000000e+05, -2.939300000000000e+05, 5.878600000000000e+04 };
2746 
2747  static const double fem_coef_gausslob_12[169] =
2748  { 1.000000000000000e+00, -7.800000000000000e+01, 2.002000000000000e+03,
2749  -2.502500000000000e+04, 1.801800000000000e+05, -8.168160000000000e+05,
2750  2.450448000000000e+06, -4.988412000000000e+06, 6.928350000000000e+06,
2751  -6.466460000000000e+06, 3.879876000000000e+06, -1.352078000000000e+06,
2752  2.080120000000000e+05, 0.000000000000000e-01, 1.055228477237708e+02,
2753  -3.710649283521791e+03, 5.230891096204477e+04, -4.000264992878070e+05,
2754  1.877737871587605e+06, -5.758751500257082e+06, 1.189876582421287e+07,
2755  -1.670085336595664e+07, 1.570840983751716e+07, -9.480360124877962e+06,
2756  3.318799039873028e+06, -5.124248673374161e+05, 0.000000000000000e-01,
2757  -4.223530748650643e+01, 2.744602756239140e+03, -4.883026612748412e+04,
2758  4.213447894212839e+05, -2.125569662252139e+06, 6.831231541213443e+06,
2759  -1.457745185889376e+07, 2.094131826427298e+07, -2.004063010887189e+07,
2760  1.225627209853367e+07, -4.335340118801754e+06, 6.749529540569050e+05,
2761  0.000000000000000e-01, 2.412126940135046e+01, -1.727728082317750e+03,
2762  3.727953470399318e+04, -3.660428937429080e+05, 2.013286677665669e+06,
2763  -6.871455230919223e+06, 1.531439984708661e+07, -2.272429867457359e+07,
2764  2.229291249432404e+07, -1.390087225188044e+07, 4.993770899110666e+06,
2765  -7.872767949619026e+05, 0.000000000000000e-01, -1.605014152757175e+01,
2766  1.189832345018574e+03, -2.753035300171167e+04, 2.951729666043859e+05,
2767  -1.750245295939125e+06, 6.340418364700963e+06, -1.480658414760223e+07,
2768  2.279585234765233e+07, -2.303126179585568e+07, 1.470734589654657e+07,
2769  -5.387526099148482e+06, 8.631843338394749e+05, 0.000000000000000e-01,
2770  1.162284069412542e+01, -8.756167723813171e+02, 2.093616690467957e+04,
2771  -2.350848402511507e+05, 1.467905987404880e+06, -5.583024412516426e+06,
2772  1.360724316266146e+07, -2.172800271110029e+07, 2.264080373496021e+07,
2773  -1.484050586374976e+07, 5.558088637639386e+06, -9.074958680213037e+05,
2774  0.000000000000000e-01, -8.865800865800866e+00, 6.738008658008658e+02,
2775  -1.640173160173160e+04, 1.890632034632035e+05, -1.219313593073593e+06,
2776  4.803100813852814e+06, -1.211898237229437e+07, 1.998830268398268e+07,
2777  -2.144876606060606e+07, 1.443281454545455e+07, -5.532578909090909e+06,
2778  9.220964848484848e+05, 0.000000000000000e-01, 6.984318980773296e+00,
2779  -5.335955916987455e+02, 1.312836634638491e+04, -1.537652068533838e+05,
2780  1.012269836848560e+06, -4.084347297774684e+06, 1.057602476941974e+07,
2781  -1.790936242524428e+07, 1.971847079705798e+07, -1.359625813912256e+07,
2782  5.331861778616258e+06, -9.074958680213037e+05, 0.000000000000000e-01,
2783  -5.596679201904262e+00, 4.289927383042951e+02, -1.062596939367885e+04,
2784  1.257256555151274e+05, -8.388435073376655e+05, 3.440109149730765e+06,
2785  -9.074697250266149e+06, 1.567950042058767e+07, -1.762881516112804e+07,
2786  1.241472483931862e+07, -4.970685906925217e+06, 8.631843338394749e+05,
2787  0.000000000000000e-01, 4.489137849846207e+00, -3.448281543178960e+02,
2788  8.578250876817155e+03, -1.021659510074640e+05, 6.876731048919487e+05,
2789  -2.851145716716003e+06, 7.618634882796075e+06, -1.335715271315875e+07,
2790  1.525930546501226e+07, -1.092966082914868e+07, 4.453550640432165e+06,
2791  -7.872767949619026e+05, 0.000000000000000e-01, -3.514808358523940e+00,
2792  2.703477424140389e+02, -6.743800341396192e+03, 8.065306199056715e+04,
2793  -5.459331868312813e+05, 2.279586137602263e+06, -6.143562568432354e+06,
2794  1.087848437431968e+07, -1.256803423488744e+07, 9.114425759470104e+06,
2795  -3.764095329881106e+06, 6.749529540569050e+05, 0.000000000000000e-01,
2796  2.522322790441051e+00, -1.941585635394145e+02, 4.850890672082830e+03,
2797  -5.815428585185421e+04, 3.949277670351431e+05, -1.655905848916830e+06,
2798  4.485333711312109e+06, -7.989838200781784e+06, 9.294715032477446e+06,
2799  -6.793611930544113e+06, 2.830299368175965e+06, -5.124248673374161e+05,
2800  0.000000000000000e-01, -1.000000000000000e+00, 7.700000000000000e+01,
2801  -1.925000000000000e+03, 2.310000000000000e+04, -1.570800000000000e+05,
2802  6.597360000000000e+05, -1.790712000000000e+06, 3.197700000000000e+06,
2803  -3.730650000000000e+06, 2.735810000000000e+06, -1.144066000000000e+06,
2804  2.080120000000000e+05 };
2805 
2806  static const double fem_coef_gausslob_13[196] =
2807  { 1.000000000000000e+00, -9.100000000000000e+01, 2.730000000000000e+03,
2808  -4.004000000000000e+04, 3.403400000000000e+05, -1.837836000000000e+06,
2809  6.651216000000000e+06, -1.662804000000000e+07, 2.909907000000000e+07,
2810  -3.556553000000000e+07, 2.974571600000000e+07, -1.622493600000000e+07,
2811  5.200300000000000e+06, -7.429000000000000e+05, 0.000000000000000e-01,
2812  1.231105960095249e+02, -5.057514000718615e+03, 8.362619816879477e+04,
2813  -7.548172444491492e+05, 4.219784854542762e+06, -1.560990588170226e+07,
2814  3.960523865471669e+07, -7.003645336672149e+07, 8.625846242015506e+07,
2815  -7.256273938600024e+07, 3.975792117062384e+07, -1.278833059440045e+07,
2816  1.832147578471145e+06, 0.000000000000000e-01, -4.927732466948325e+01,
2817  3.738734011094227e+03, -7.796486012083982e+04, 7.935560370804071e+05,
2818  -4.765562636392240e+06, 1.846680880578437e+07, -4.837506802694851e+07,
2819  8.753277424234758e+07, -1.096660444159086e+08, 9.346798694406962e+07,
2820  -5.173889595224656e+07, 1.677849814552107e+07, -2.419777739872722e+06,
2821  0.000000000000000e-01, 2.814884111282567e+01, -2.353904695653627e+03,
2822  5.948276501192433e+04, -6.883051529064705e+05, 4.502895601024915e+06,
2823  -1.851735708867110e+07, 5.063079101609929e+07, -9.458217148027056e+07,
2824  1.214199817163488e+08, -1.054743067017811e+08, 5.927651305189011e+07,
2825  -1.946011726944643e+07, 2.834919298555227e+06, 0.000000000000000e-01,
2826  -1.874042032746388e+01, 1.621968976936385e+03, -4.394233902947216e+04,
2827  5.547892506224127e+05, -3.908876121817967e+06, 1.704431633766850e+07,
2828  -4.878627691196220e+07, 9.448003328782282e+07, -1.248200449226441e+08,
2829  1.109678546438889e+08, -6.355498649510845e+07, 2.119358718443647e+07,
2830  -3.128057142433586e+06, 0.000000000000000e-01, 1.358783086373605e+01,
2831  -1.195146716951513e+03, 3.345811195278515e+04, -4.422483366082136e+05,
2832  3.278781781106079e+06, -1.499532485039955e+07, 4.474689669452104e+07,
2833  -8.978037194074775e+07, 1.222039761714010e+08, -1.114085938050346e+08,
2834  6.517880226738924e+07, -2.213159774622623e+07, 3.317403211532315e+06,
2835  0.000000000000000e-01, -1.039065134180050e+01, 9.220321824274881e+02,
2836  -2.627964906979335e+04, 3.565631308351814e+05, -2.729347397416285e+06,
2837  1.291899991743804e+07, -3.987098284679090e+07, 8.253644504125924e+07,
2838  -1.155541226713629e+08, 1.080161713852185e+08, -6.460510650895925e+07,
2839  2.236736005147009e+07, -3.410612094153076e+06, 0.000000000000000e-01,
2840  8.225051804237637e+00, -7.337438600306013e+02, 2.113982918743374e+04,
2841  -2.914573383452468e+05, 2.277144431399071e+06, -1.103660550091489e+07,
2842  3.493361321847434e+07, -7.418006034176242e+07, 1.064417028079657e+08,
2843  -1.018292957440870e+08, 6.222452923525811e+07, -2.197059717251990e+07,
2844  3.410612094153076e+06, 0.000000000000000e-01, -6.651370533890156e+00,
2845  5.953674398464600e+02, -1.727143617692029e+04, 2.405949101477657e+05,
2846  -1.905359074321061e+06, 9.386078020968711e+06, -3.025905095154839e+07,
2847  6.552811535463406e+07, -9.594395490329804e+07, 9.365009838355809e+07,
2848  -5.835707981219508e+07, 2.099464400369387e+07, -3.317403211532315e+06,
2849  0.000000000000000e-01, 5.430796129527214e+00, -4.871978584294892e+02,
2850  1.419769025501944e+04, -1.991370307462581e+05, 1.591472100521582e+06,
2851  -7.928247009292726e+06, 2.589562028603176e+07, -5.690356974983853e+07,
2852  8.463743197871011e+07, -8.398458536550263e+07, 5.322039739169053e+07,
2853  -1.947115566720015e+07, 3.128057142433586e+06, 0.000000000000000e-01,
2854  -4.414467779036191e+00, 3.966097971621681e+02, -1.159268854505275e+04,
2855  1.633445673328560e+05, -1.313458735263122e+06, 6.593624701202045e+06,
2856  -2.173390279168494e+07, 4.826160481317836e+07, -7.262663174126566e+07,
2857  7.298651647234048e+07, -4.687881110584063e+07, 1.739383361177152e+07,
2858  -2.834919298555227e+06, 0.000000000000000e-01, 3.487743182287134e+00,
2859  -3.136500314357888e+02, 9.185689380767778e+03, -1.298134042763866e+05,
2860  1.048017196494400e+06, -5.287706376855868e+06, 1.753577438278919e+07,
2861  -3.921741432164137e+07, 5.949694434313328e+07, -6.033542452985016e+07,
2862  3.913958191606598e+07, -1.467861247282431e+07, 2.419777739872722e+06,
2863  0.000000000000000e-01, -2.516624450464659e+00, 2.264447557529062e+02,
2864  -6.639311014646825e+03, 9.399061131310191e+04, -7.605959998781342e+05,
2865  3.848998924774717e+06, -1.281093272369737e+07, 2.877371846174006e+07,
2866  -4.386952078323465e+07, 4.473878170318014e+07, -2.920546515856783e+07,
2867  1.102958792572444e+07, -1.832147578471145e+06, 0.000000000000000e-01,
2868  1.000000000000000e+00, -9.000000000000000e+01, 2.640000000000000e+03,
2869  -3.740000000000000e+04, 3.029400000000000e+05, -1.534896000000000e+06,
2870  5.116320000000000e+06, -1.151172000000000e+07, 1.758735000000000e+07,
2871  -1.797818000000000e+07, 1.176753600000000e+07, -4.457400000000000e+06,
2872  7.429000000000000e+05 };
2873 
2874  static const double fem_coef_gausslob_14[225] =
2875  { 1.000000000000000e+00, -1.050000000000000e+02, 3.640000000000000e+03,
2876  -6.188000000000000e+04, 6.126120000000000e+05, -3.879876000000000e+06,
2877  1.662804000000000e+07, -4.988412000000000e+07, 1.066965900000000e+08,
2878  -1.636014380000000e+08, 1.784742960000000e+08, -1.352078000000000e+08,
2879  6.760390000000000e+07, -2.005830000000000e+07, 2.674440000000000e+06,
2880  0.000000000000000e-01, 1.420511699552723e+02, -6.740724197514907e+03,
2881  1.291563810650317e+05, -1.357536885890637e+06, 8.899789739175488e+06,
2882  -3.898284725729828e+07, 1.186784002318284e+08, -2.564866709310747e+08,
2883  3.962828733570607e+08, -4.348015522628213e+08, 3.308658899677545e+08,
2884  -1.660170000478420e+08, 4.939776003229131e+07, -6.601663651220939e+06,
2885  0.000000000000000e-01, -5.686066782897496e+01, 4.980782943180571e+03,
2886  -1.202886759366057e+05, 1.425067611910860e+06, -1.003204881513823e+07,
2887  4.601736532886305e+07, -1.446080878593359e+08, 3.197256124417587e+08,
2888  -5.024241189222256e+08, 5.584380089699472e+08, -4.292685524711295e+08,
2889  2.171358326952990e+08, -6.503152653250142e+07, 8.737812306213077e+06,
2890  0.000000000000000e-01, 3.248522677540712e+01, -3.136209432322820e+03,
2891  9.172216152088957e+04, -1.234458149638161e+06, 9.460578149039340e+06,
2892  -4.602710110035357e+07, 1.508977142152744e+08, -3.443000936718750e+08,
2893  5.541917935770469e+08, -6.276282328622294e+08, 4.896977188070307e+08,
2894  -2.507043130148833e+08, 7.583045543918066e+07, -1.027267982590785e+07,
2895  0.000000000000000e-01, -2.163547691954172e+01, 2.161829695966707e+03,
2896  -6.777232432848026e+04, 9.945601317987818e+05, -8.202377657972944e+06,
2897  4.227975782999525e+07, -1.449995018490026e+08, 3.427553248466447e+08,
2898  -5.674380093336526e+08, 6.573468625138306e+08, -5.224446315267705e+08,
2899  2.715766154508912e+08, -8.319461131269656e+07, 1.139164303704407e+07,
2900  0.000000000000000e-01, 1.569978564006007e+01, -1.594280678736617e+03,
2901  5.164364569735884e+04, -7.932250762767995e+05, 6.879605840139093e+06,
2902  -3.716431671531196e+07, 1.327627119052969e+08, -3.248633554644047e+08,
2903  5.536614212284358e+08, -6.572276042331931e+08, 5.332102141003966e+08,
2904  -2.820526436178851e+08, 8.770029066945359e+07, -1.216316370145453e+07,
2905  0.000000000000000e-01, -1.202518395631915e+01, 1.231993083463710e+03,
2906  -4.063141778456666e+04, 6.405521495953326e+05, -5.734055805513453e+06,
2907  3.204057307537486e+07, -1.182863821502541e+08, 2.983631937198568e+08,
2908  -5.225422090403253e+08, 6.354190974001179e+08, -5.265537919663995e+08,
2909  2.837551732890861e+08, -8.968009595208465e+07, 1.261735673043107e+07,
2910  0.000000000000000e-01, 9.547785547785548e+00, -9.834219114219114e+02,
2911  3.278709557109557e+04, -5.252427785547786e+05, 4.798602442890443e+06,
2912  -2.744701911421911e+07, 1.038669217715618e+08, -2.685490364568765e+08,
2913  4.816180870862471e+08, -5.987952711608392e+08, 5.064437616783217e+08,
2914  -2.780475554312354e+08, 8.937242853146853e+07, -1.276748979020979e+07,
2915  0.000000000000000e-01, -7.763592643695499e+00, 8.024013730981778e+02,
2916  -2.693903659000494e+04, 4.360799342555947e+05, -4.038452021764897e+06,
2917  2.347605516322762e+07, -9.046087127754393e+07, 2.384165701554799e+08,
2918  -4.360078989902932e+08, 5.526354677146948e+08, -4.761786531169400e+08,
2919  2.660933883812130e+08, -8.696289827395033e+07, 1.261735673043107e+07,
2920  0.000000000000000e-01, 6.402657115106499e+00, -6.632652203626004e+02,
2921  2.237191510124190e+04, -3.647008347515229e+05, 3.408912135873189e+06,
2922  -2.004238739169268e+07, 7.824760241311718e+07, -2.092325230710293e+08,
2923  3.885803431690498e+08, -5.004334616015021e+08, 4.381904244262927e+08,
2924  -2.487967617473505e+08, 8.258400115090981e+07, -1.216316370145453e+07,
2925  0.000000000000000e-01, -5.303584550798654e+00, 5.502727059685037e+02,
2926  -1.861988467344103e+04, 3.050015660700474e+05, -2.869271809771707e+06,
2927  1.700462338220501e+07, -6.701518639186630e+07, 1.811217810430339e+08,
2928  -3.403535526125257e+08, 4.438883801280693e+08, -3.938531369776322e+08,
2929  2.266861847568459e+08, -7.628839120592035e+07, 1.139164303704407e+07,
2930  0.000000000000000e-01, 4.356127432886088e+00, -4.524531153029460e+02,
2931  1.534317874813675e+04, -2.521565333504139e+05, 2.382646312619400e+06,
2932  -1.419908547341188e+07, 5.633074020272954e+07, -1.534171364617007e+08,
2933  2.907942363862238e+08, -3.828802350952767e+08, 3.432339697459343e+08,
2934  -1.997222564631490e+08, 6.798706212352923e+07, -1.027267982590785e+07,
2935  0.000000000000000e-01, -3.466327490120249e+00, 3.602867454806401e+02,
2936  -1.223518159744950e+04, 2.015152850494290e+05, -1.909713800970267e+06,
2937  1.142278748458884e+07, -4.551909122318173e+07, 1.246206804545239e+08,
2938  -2.376275441309645e+08, 3.149824199011395e+08, -2.844660497989077e+08,
2939  1.668669076381706e+08, -5.729784575448167e+07, 8.737812306213077e+06,
2940  0.000000000000000e-01, 2.512080922932578e+00, -2.612119914965073e+02,
2941  8.878143206793750e+03, -1.464124202177336e+05, 1.389929291394544e+06,
2942  -8.332053211967151e+06, 3.329158201137647e+07, -9.143262460433713e+07,
2943  1.749809182259230e+08, -2.329047114119376e+08, 2.113183971320489e+08,
2944  -1.245975118891604e+08, 4.302553108480184e+07, -6.601663651220939e+06,
2945  0.000000000000000e-01, -1.000000000000000e+00, 1.040000000000000e+02,
2946  -3.536000000000000e+03, 5.834400000000000e+04, -5.542680000000000e+05,
2947  3.325608000000000e+06, -1.330243200000000e+07, 3.658168800000000e+07,
2948  -7.011490200000000e+07, 9.348653600000000e+07, -8.498776000000000e+07,
2949  5.022004000000000e+07, -1.738386000000000e+07, 2.674440000000000e+06 };
2950 
2951  static const double fem_coef_gausslob_16[289] =
2952  { 1.000000000000000e+00, -1.360000000000000e+02, 6.120000000000000e+03,
2953  -1.356600000000000e+05, 1.763580000000000e+06, -1.481407200000000e+07,
2954  8.535727200000000e+07, -3.505745100000000e+08, 1.051723530000000e+09,
2955  -2.337163400000000e+09, 3.866943080000000e+09, -4.745793780000000e+09,
2956  4.259045700000000e+09, -2.714556600000000e+09, 1.163381400000000e+09,
2957  -3.005401950000000e+08, 3.535767000000000e+07, 0.000000000000000e-01,
2958  1.839908474110340e+02, -1.132675577023645e+04, 2.828774748172428e+05,
2959  -3.903228397113182e+06, 3.393217989215092e+07, -1.997936813387011e+08,
2960  8.326183533203730e+08, -2.523654441487500e+09, 5.650496513849965e+09,
2961  -9.402288564814163e+09, 1.159004125992500e+10, -1.043753556167033e+10,
2962  6.671119113102151e+09, -2.865585732582308e+09, 7.416762022559170e+08,
2963  -8.739414676532781e+07, 0.000000000000000e-01, -7.365158560983221e+01,
2964  8.363752486870456e+03, -2.630512922725150e+05, 4.088268892503375e+06,
2965  -3.814296099037553e+07, 2.350888858038512e+08, -1.010915772862718e+09,
2966  3.133749897384450e+09, -7.134585101325640e+09, 1.202392366962845e+10,
2967  -1.496979454364896e+10, 1.358833701849443e+10, -8.740756338653663e+09,
2968  3.774397412355719e+09, -9.811765345365573e+08, 1.160408606498937e+08,
2969  0.000000000000000e-01, 4.208515410469884e+01, -5.266887544418802e+03,
2970  2.004067164817591e+05, -3.534528216742270e+06, 3.586506864599599e+07,
2971  -2.342572871648561e+08, 1.050195570375994e+09, -3.357626237614668e+09,
2972  7.826157982970905e+09, -1.343314504492630e+10, 1.696909064108448e+10,
2973  -1.558480944857237e+10, 1.012167818105129e+10, -4.405611470443590e+09,
2974  1.152926420144654e+09, -1.371250292488943e+08, 0.000000000000000e-01,
2975  -2.804154671449467e+01, 3.632134644860107e+03, -1.481030987143817e+05,
2976  2.845430205439061e+06, -3.103475950537538e+07, 2.145184209516461e+08,
2977  -1.004950951655481e+09, 3.325504487572721e+09, -7.965634686855131e+09,
2978  1.397533464514550e+10, -1.797134014690632e+10, 1.674913384367476e+10,
2979  -1.101142723314074e+10, 4.842306972881947e+09, -1.278281396603255e+09,
2980  1.531698732399162e+08, 0.000000000000000e-01, 2.036791285538472e+01,
2981  -2.681212491930484e+03, 1.129589658306899e+05, -2.270501508829428e+06,
2982  2.601887714173907e+07, -1.882644410377163e+08, 9.175357517098464e+08,
2983  -3.139134215049928e+09, 7.731773974122787e+09, -1.388518223176127e+10,
2984  1.820883321323428e+10, -1.725391802961138e+10, 1.150422262078233e+10,
2985  -5.120395806896533e+09, 1.365808881323657e+09, -1.651383905702324e+08,
2986  0.000000000000000e-01, -1.562975981216744e+01, 2.075857199589987e+03,
2987  -8.904128307330524e+04, 1.836683464233000e+06, -2.171339625537650e+07,
2988  1.623702309776589e+08, -8.168673425840398e+08, 2.877184244039678e+09,
2989  -7.272633187920932e+09, 1.336161532561319e+10, -1.787465369706492e+10,
2990  1.723415209556249e+10, -1.166677727073840e+10, 5.262202876034756e+09,
2991  -1.420107794637259e+09, 1.734782145645626e+08, 0.000000000000000e-01,
2992  1.245158740600359e+01, -1.662689739514946e+03, 7.210078018619273e+04,
2993  -1.511262926531350e+06, 1.823010400853032e+07, -1.394732137018548e+08,
2994  7.186625912313578e+08, -2.591802100670653e+09, 6.699969496687534e+09,
2995  -1.256822106464210e+10, 1.713562111741701e+10, -1.680796707246793e+10,
2996  1.155571599892056e+10, -5.285087289024682e+09, 1.444204616664480e+09,
2997  -1.784123720377501e+08, 0.000000000000000e-01, -1.018430458430458e+01,
2998  1.364696814296814e+03, -5.959855042735043e+04, 1.262405659052059e+06,
2999  -1.543602456068376e+07, 1.199989722604507e+08, -6.293065120124320e+08,
3000  2.311744565308469e+09, -6.087583637383061e+09, 1.162721665412277e+10,
3001  -1.612769282864336e+10, 1.607722369253147e+10, -1.122097126220979e+10,
3002  5.203928701314685e+09, -1.440373122685315e+09, 1.800466403356643e+08,
3003  0.000000000000000e-01, 8.484036081962663e+00, -1.139564172918365e+03,
3004  5.000628114583172e+04, -1.066865683702600e+06, 1.316848914076596e+07,
3005  -1.035421266853741e+08, 5.500823983897466e+08, -2.049399257475671e+09,
3006  5.477078740096760e+09, -1.061962761323504e+10, 1.495184835525608e+10,
3007  -1.512401891411349e+10, 1.070494963879464e+10, -5.031502683587495e+09,
3008  1.410393335939522e+09, -1.784123720377501e+08, 0.000000000000000e-01,
3009  -7.151250283691663e+00, 9.621468006776697e+02, -4.236328367402523e+04,
3010  9.083924059514159e+05, -1.128778312795541e+07, 8.948673396532559e+07,
3011  -4.799806642461592e+08, 1.807454740270899e+09, -4.886699456126079e+09,
3012  9.591077381959552e+09, -1.367409274689175e+10, 1.400781324267719e+10,
3013  -1.004054471299105e+10, 4.777971704223384e+09, -1.355543638395742e+09,
3014  1.734782145645626e+08, 0.000000000000000e-01, 6.060147075943005e+00,
3015  -8.163167553056976e+02, 3.602890134025652e+04, -7.753708269797396e+05,
3016  9.681484150831325e+06, -7.721340002337801e+07, 4.170906086685726e+08,
3017  -1.583343835764609e+09, 4.319156776154927e+09, -8.559301071696637e+09,
3018  1.232825943540154e+10, -1.276387222258454e+10, 9.248884856115279e+09,
3019  -4.449869455469566e+09, 1.276405367800062e+09, -1.651383905702324e+08,
3020  0.000000000000000e-01, -5.123522643555085e+00, 6.907394286218810e+02,
3021  -3.053901287681582e+04, 6.589382296622791e+05, -8.256408016568484e+06,
3022  6.613528180437879e+07, -3.591109349416936e+08, 1.371451685008549e+09,
3023  -3.766497172573159e+09, 7.519828793959344e+09, -1.091857986975193e+10,
3024  1.140164818726860e+10, -8.336452758217789e+09, 4.048470812623064e+09,
3025  -1.172436575235404e+09, 1.531698732399162e+08, 0.000000000000000e-01,
3026  4.271888353674923e+00, -5.762713061877649e+02, 2.550919052304026e+04,
3027  -5.514258520673562e+05, 6.926418073801134e+06, -5.565457178175802e+07,
3028  3.033329010654617e+08, -1.163492208450654e+09, 3.211252052317023e+09,
3029  -6.446888262886903e+09, 9.417864122967573e+09, -9.899668972442366e+09,
3030  7.289624669351123e+09, -3.566718678141100e+09, 1.041074047837655e+09,
3031  -1.371250292488943e+08, 0.000000000000000e-01, -3.434977405385288e+00,
3032  4.635617485626016e+02, -2.053688028669370e+04, 4.444943513906060e+05,
3033  -5.592632684586483e+06, 4.503253959356561e+07, -2.460675245081598e+08,
3034  9.466718497394927e+08, -2.621823641133609e+09, 5.284002694315866e+09,
3035  -7.752423037115038e+09, 8.187712309040204e+09, -6.060153271928369e+09,
3036  2.981652672294607e+09, -8.754772358617425e+08, 1.160408606498937e+08,
3037  0.000000000000000e-01, 2.505373764729175e+00, -3.381913429670035e+02,
3038  1.499009100007397e+04, -3.246847962658711e+05, 4.089321087106837e+06,
3039  -3.296978262323839e+07, 1.804331430493320e+08, -6.954301078105766e+08,
3040  1.930060872117711e+09, -3.899125665782255e+09, 5.735918309736332e+09,
3041  -6.075963842786729e+09, 4.511802094762441e+09, -2.227740310582889e+09,
3042  6.566301459893279e+08, -8.739414676532781e+07, 0.000000000000000e-01,
3043  -1.000000000000000e+00, 1.350000000000000e+02, -5.985000000000000e+03,
3044  1.296750000000000e+05, -1.633905000000000e+06, 1.318016700000000e+07,
3045  -7.217710500000000e+07, 2.783974050000000e+08, -7.733261250000000e+08,
3046  1.563837275000000e+09, -2.303105805000000e+09, 2.442687975000000e+09,
3047  -1.816357725000000e+09, 8.981988750000000e+08, -2.651825250000000e+08,
3048  3.535767000000000e+07 };
3049 
3050  static const double fem_coef_gausslob_24[625] =
3051  { 1.000000000000000e+00, -3.000000000000000e+02, 2.990000000000000e+04,
3052  -1.480050000000000e+06, 4.351347000000000e+07, -8.412604200000000e+08,
3053  1.141710570000000e+10, -1.137633032250000e+11, 8.595449577000000e+11,
3054  -5.042663751840000e+12, 2.337962284944000e+13, -8.678799391080000e+13,
3055  2.603639817324000e+14, -6.351736697208000e+14, 1.264298066396640e+15,
3056  -2.054484357894540e+15, 2.719170473683950e+15, -2.914666390092600e+15,
3057  2.505590405518200e+15, -1.701164012167620e+15, 8.910859111354200e+14,
3058  -3.471763290138000e+14, 9.468445336740000e+13, -1.612380184155000e+13,
3059  1.289904147324000e+12, 0.000000000000000e-01, 4.058641271792565e+02,
3060  -5.527892747506228e+04, 3.080680865091051e+06, -9.608544697986574e+07,
3061  1.921815551511292e+09, -2.664514371195282e+10, 2.693344195607988e+11,
3062  -2.055620699316044e+12, 1.214897536784061e+13, -5.664114215003022e+13,
3063  2.111637034506248e+14, -6.356401824720572e+14, 1.554903769748071e+15,
3064  -3.101863582054997e+15, 5.049759901096915e+15, -6.693732300831693e+15,
3065  7.184248666000200e+15, -6.182729556103940e+15, 4.201716500300169e+15,
3066  -2.202700032171432e+15, 8.588067464630930e+14, -2.343664562972425e+14,
3067  3.993223187351215e+13, -3.196139551478179e+12, 0.000000000000000e-01,
3068  -1.624756704002590e+02, 4.076566744849383e+04, -2.856559180759908e+06,
3069  1.002242332396244e+08, -2.149192199655287e+09, 3.116591524589708e+10,
3070  -3.248555446646729e+11, 2.534404897909630e+12, -1.522400128496926e+13,
3071  7.186059820369571e+13, -2.704952845330370e+14, 8.204876425573068e+14,
3072  -2.019503996546278e+15, 4.049106649016715e+15, -6.619542027745681e+15,
3073  8.805466617020362e+15, -9.478911036302426e+15, 8.178282706527972e+15,
3074  -5.570062256804815e+15, 2.925593222099543e+15, -1.142548313369483e+15,
3075  3.122535907953383e+14, -5.327144417235540e+13, 4.268671053543734e+12,
3076  0.000000000000000e-01, 9.285790471348058e+01, -2.567292232023452e+04,
3077  2.172505008713478e+06, -8.632693629032278e+07, 2.009759260312978e+09,
3078  -3.083881003217180e+10, 3.346965047874316e+11, -2.690206053619648e+12,
3079  1.652940573703274e+13, -7.940281485029880e+13, 3.030598877175188e+14,
3080  -9.295754861643471e+14, 2.308921995608790e+15, -4.664329550291535e+15,
3081  7.673380080847903e+15, -1.026158278560169e+16, 1.109639715400819e+16,
3082  -9.611028022799504e+15, 6.567868332535721e+15, -3.459765425094874e+15,
3083  1.354622808613475e+15, -3.710479852977045e+14, 6.342841599973944e+13,
3084  -5.091588188794019e+12, 0.000000000000000e-01, -6.190263201810896e+01,
3085  1.771295817306943e+04, -1.605426884400296e+06, 6.937138005497782e+07,
3086  -1.732266817595608e+09, 2.807090718452186e+10, -3.177491729312126e+11,
3087  2.638958096874092e+12, -1.663806369766778e+13, 8.158796865135113e+13,
3088  -3.166342096198069e+14, 9.845663378570931e+14, -2.473337869447428e+15,
3089  5.044014753850598e+15, -8.364663482728635e+15, 1.126254226203764e+16,
3090  -1.225027170970453e+16, 1.066427200479037e+16, -7.319785257851210e+15,
3091  3.870748078365627e+15, -1.520689469004945e+15, 4.177883147633562e+14,
3092  -7.160927970988626e+13, 5.762006100161049e+12, 0.000000000000000e-01,
3093  4.501042175430940e+01, -1.308958048352837e+04, 1.225547369430789e+06,
3094  -5.535760993480313e+07, 1.449945861634959e+09, -2.454369660090688e+10,
3095  2.883865544213490e+11, -2.470900824125910e+12, 1.598637745987517e+13,
3096  -8.009303566237079e+13, 3.164491556576764e+14, -9.988976501079246e+14,
3097  2.541436559580714e+15, -5.239264041161704e+15, 8.769361705836964e+15,
3098  -1.190220432935039e+16, 1.303612471279278e+16, -1.141726255498977e+16,
3099  7.878336148801056e+15, -4.185657107040718e+15, 1.651238357905402e+15,
3100  -4.553312625304459e+14, 7.830179054235796e+13, -6.319165567954503e+12,
3101  0.000000000000000e-01, -3.460823180120079e+01, 1.015469610544880e+04,
3102  -9.679531870145017e+05, 4.485134755229398e+07, -1.210735945225935e+09,
3103  2.114609948086286e+10, -2.559531795223062e+11, 2.252595670603948e+12,
3104  -1.492191456512238e+13, 7.630937241452699e+13, -3.068986895462340e+14,
3105  9.837309848042438e+14, -2.536329824251836e+15, 5.289429958022946e+15,
3106  -8.942835505684019e+15, 1.224496508118832e+16, -1.351567177210176e+16,
3107  1.191830727462528e+16, -8.273935552638878e+15, 4.419525275428065e+15,
3108  -1.751884239411906e+15, 4.851652818736986e+14, -8.375521716296401e+13,
3109  6.782865257514837e+12, 0.000000000000000e-01, 2.766582877253528e+01,
3110  -8.161941725332768e+03, 7.865526415735044e+05, -3.702889412503837e+07,
3111  1.019390720188427e+09, -1.819645578676150e+10, 2.252249000861092e+11,
3112  -2.025483052842698e+12, 1.369084263890056e+13, -7.131369560391163e+13,
3113  2.915943262851778e+14, -9.485944639479267e+14, 2.478119277999363e+15,
3114  -5.228788122037598e+15, 8.932615077176731e+15, -1.234455468758280e+16,
3115  1.373835480205531e+16, -1.220422101884528e+16, 8.528504524807064e+15,
3116  -4.582579019928659e+15, 1.826238758482371e+15, -5.082003015125067e+14,
3117  8.811547249928783e+13, -7.164301017225998e+12, 0.000000000000000e-01,
3118  -2.275670591599455e+01, 6.737590226239552e+03, -6.539504206517175e+05,
3119  3.111139106156313e+07, -8.679722967903971e+08, 1.573365420642779e+10,
3120  -1.979909637705803e+11, 1.810880611538906e+12, -1.244463025448231e+13,
3121  6.585374856883214e+13, -2.732735801573156e+14, 9.011914571652850e+14,
3122  -2.383831456114384e+15, 5.087291841992724e+15, -8.780953301699755e+15,
3123  1.224889816733013e+16, -1.374781660040675e+16, 1.230672077620068e+16,
3124  -8.660226214361099e+15, 4.682883135541219e+15, -1.876981572450838e+15,
3125  5.250670186065034e+14, -9.147680701891190e+13, 7.470231264323625e+12,
3126  0.000000000000000e-01, 1.912965144613660e+01, -5.677631395079384e+03,
3127  5.537935689545739e+05, -2.653927821530689e+07, 7.474036306614312e+08,
3128  -1.369940651896189e+10, 1.745319507247928e+11, -1.617301631376405e+12,
3129  1.126327452432594e+13, -6.039298017983792e+13, 2.538313181524926e+14,
3130  -8.473116290006231e+14, 2.267097817730376e+15, -4.890112526330036e+15,
3131  8.524655979372967e+15, -1.200076621013731e+16, 1.358349523272153e+16,
3132  -1.225446423734989e+16, 8.685297402148473e+15, -4.727405822382261e+15,
3133  1.906317065479628e+15, -5.362492238636365e+14, 9.390516767804315e+13,
3134  -7.704880889559378e+12, 0.000000000000000e-01, -1.635497697368700e+01,
3135  4.862656953497025e+03, -4.759804636482565e+05, 2.293041632316653e+07,
3136  -6.502015538842764e+08, 1.201606379408697e+10, -1.545199230484324e+11,
3137  1.446437458063616e+12, -1.018096106218994e+13, 5.518468570532575e+13,
3138  -2.344620385089091e+14, 7.909885622725649e+14, -2.138165417503776e+15,
3139  4.657339854616682e+15, -8.194527986057532e+15, 1.163730420250179e+16,
3140  -1.328057957790062e+16, 1.207345046837354e+16, -8.618482475976474e+15,
3141  4.722435616707614e+15, -1.916176031917556e+15, 5.421466879431477e+14,
3142  -9.544980641239802e+13, 7.870911362255844e+12, 0.000000000000000e-01,
3143  1.417066207624127e+01, -4.218698704765500e+03, 4.140273580736256e+05,
3144  -2.002373113338682e+07, 5.706909517514257e+08, -1.061235738178459e+10,
3145  1.374488760853391e+11, -1.296867134188179e+12, 9.206001697332345e+12,
3146  -5.034424091354864e+13, 2.158419782218546e+14, -7.348173021384713e+14,
3147  2.004252206567683e+15, -4.404149060382797e+15, 7.815178748758451e+15,
3148  -1.118956431220418e+16, 1.286957131473114e+16, -1.178684055128811e+16,
3149  8.473168167228462e+15, -4.673705358375533e+15, 1.908297467260950e+15,
3150  -5.431049066701974e+14, 9.614927445703371e+13, -7.969947411626695e+12,
3151  0.000000000000000e-01, -1.240846755882427e+01, 3.697723332529632e+03,
3152  -3.636177333437864e+05, 1.763791694375029e+07, -5.046596469793725e+08,
3153  9.429433336134134e+09, -1.228099190218494e+11, 1.166008419408402e+12,
3154  -8.333618884154624e+12, 4.590449180645647e+13, -1.982963080519099e+14,
3155  6.803133908337801e+14, -1.870091239145240e+15, 4.141349396659428e+15,
3156  -7.405302748248103e+15, 1.068239700855010e+16, -1.237594459251991e+16,
3157  1.141465416121965e+16, -8.261228940134621e+15, 4.586380576952005e+15,
3158  -1.884249466545215e+15, 5.394272826690079e+14, -9.603440259637641e+13,
3159  8.002866883031367e+12, 0.000000000000000e-01, 1.095558179466470e+01,
3160  -3.267249008495488e+03, 3.217786804294041e+05, -1.564425754031200e+07,
3161  4.489762785029423e+08, -8.420409805207488e+09, 1.101506623685581e+11,
3162  -1.051033145830932e+12, 7.553210200363392e+12, -4.185258869687206e+13,
3163  1.819278279112502e+14, -6.282336154227903e+14, 1.738507104235632e+15,
3164  -3.876120340749998e+15, 6.978305450391071e+15, -1.013471839778258e+16,
3165  1.182005159615111e+16, -1.097352991130819e+16, 7.992846614334175e+15,
3166  -4.464988119249731e+15, 1.845417602986293e+15, -5.313770797673897e+14,
3167  9.512946342200696e+13, -7.969947411626695e+12, 0.000000000000000e-01,
3168  -9.733404845062563e+00, 2.904495367336991e+03, -2.863957452026712e+05,
3169  1.394908621565543e+07, -4.012835563442479e+08, 7.548227155070059e+09,
3170  -9.908687724892865e+10, 9.492474279583278e+11, -6.852122094227041e+12,
3171  3.815223404048325e+13, -1.667054040084672e+14, 5.788252023371522e+14,
3172  -1.610924210936436e+15, 3.612762299121459e+15, -6.543084510709907e+15,
3173  9.560030643675167e+15, -1.121725598566102e+16, 1.047660019645038e+16,
3174  -7.676343347474552e+15, 4.313320840279778e+15, -1.792974677700824e+15,
3175  5.191726764406062e+14, -9.345206628174223e+13, 7.870911362255844e+12,
3176  0.000000000000000e-01, 8.685152146887849e+00, -2.592917301003156e+03,
3177  2.559159080755008e+05, -1.248235381982623e+07, 3.597715754514247e+08,
3178  -6.783361410773893e+09, 8.929618961811727e+10, -8.582135820103382e+11,
3179  6.217423158689400e+12, -3.475607425638306e+13, 1.525197220141970e+14,
3180  -5.320009405626489e+14, 1.487763351500956e+15, -3.353349463718517e+15,
3181  6.104800041187937e+15, -8.967037300250809e+15, 1.057820092203265e+16,
3182  -9.933456336414407e+15, 7.318037585534789e+15, -4.134330534453634e+15,
3183  1.727837357443638e+15, -5.029774927870322e+14, 9.101197367138191e+13,
3184  -7.704880889559378e+12, 0.000000000000000e-01, -7.768227503689160e+00,
3185  2.320048262018063e+03, -2.291579825895192e+05, 1.118998178170061e+07,
3186  -3.230127412726743e+08, 6.101825984880789e+09, -8.050592964465223e+10,
3187  7.757517929934399e+11, -5.636578411502579e+12, 3.161187883403309e+13,
3188  -1.392153217132889e+14, 4.874510273126649e+14, -1.368719368735070e+15,
3189  3.098228256202772e+15, -5.665515780120550e+15, 8.360206053329256e+15,
3190  -9.909089467205730e+15, 9.350136076665120e+15, -6.922098442148973e+15,
3191  3.930003596385763e+15, -1.650608740098542e+15, 4.828842861248500e+14,
3192  -8.780874332485509e+13, 7.470231264323625e+12, 0.000000000000000e-01,
3193  6.949251795654158e+00, -2.076080736426886e+03, 2.051850668187582e+05,
3194  -1.002851556374879e+07, 2.898385274463058e+08, -5.483488755332865e+09,
3195  7.247948130849744e+10, -6.998845716368053e+11, 5.097508994937879e+12,
3196  -2.866481138828522e+13, 1.266058930533223e+14, -4.447041797385597e+14,
3197  1.252927498139101e+15, -2.846337193255717e+15, 5.224630116918579e+15,
3198  -7.740148279482860e+15, 9.211839907560781e+15, -8.729031202403334e+15,
3199  6.490342376708594e+15, -3.701195553992629e+15, 1.561498591338377e+15,
3200  -4.588915147832623e+14, 8.382775191413614e+13, -7.164301017225998e+12,
3201  0.000000000000000e-01, -6.200545901231066e+00, 1.852852310460863e+03,
3202  -1.832115058838774e+05, 8.961081566680860e+06, -2.592406841374813e+08,
3203  4.910586592056635e+09, -6.500190149790611e+10, 6.287466876199138e+11,
3204  -4.588252565931313e+12, 2.585696625207004e+13, -1.144768233740891e+14,
3205  4.031460020145847e+14, -1.139023606360627e+15, 2.595327972551887e+15,
3206  -4.779021130665880e+15, 7.103675353349177e+15, -8.483943776806492e+15,
3207  8.068562477979859e+15, -6.021870692282251e+15, 3.447372991345801e+15,
3208  -1.460201300789598e+15, 4.308660981996213e+14, -7.903354901739207e+13,
3209  6.782865257514837e+12, 0.000000000000000e-01, 5.497265260133587e+00,
3210  -1.643010914375697e+03, 1.625245542407611e+05, -7.953853255844527e+06,
3211  2.302798044521235e+08, -4.366227075820252e+09, 5.786337032883471e+10,
3212  -5.604566478207931e+11, 4.096239643506256e+12, -2.312433390636899e+13,
3213  1.025754064938261e+14, -3.619933583977279e+14, 1.025085118853682e+15,
3214  -2.341436140046740e+15, 4.322778692729082e+15, -6.443312152718818e+15,
3215  7.717747123310279e+15, -7.362354286134902e+15, 5.512353176524103e+15,
3216  -3.166155510128892e+15, 1.345687520087759e+15, -3.984797768116558e+14,
3217  7.335818308855012e+13, -6.319165567954503e+12, 0.000000000000000e-01,
3218  -4.814420396783881e+00, 1.439137261510244e+03, -1.424001050225189e+05,
3219  6.972107765750786e+06, -2.019777804539574e+08, 3.832494908082456e+09,
3220  -5.083618287186299e+10, 4.929144471099037e+11, -3.606960360420349e+12,
3221  2.039001482865880e+13, -9.058350359554217e+13, 3.202053356214614e+14,
3222  -9.083926524953095e+14, 2.078951013598256e+15, -3.846222877659622e+15,
3223  5.745792065253601e+15, -6.898564020656367e+15, 6.597335811773795e+15,
3224  -4.952528004193797e+15, 2.852412393699805e+15, -1.215806035913631e+15,
3225  3.610885650804218e+14, -6.667886669397892e+13, 5.762006100161049e+12,
3226  0.000000000000000e-01, 4.122502768575858e+00, -1.232445305915745e+03,
3227  1.219756720552666e+05, -5.974119340666288e+06, 1.731450552812862e+08,
3228  -3.287266438655767e+09, 4.363384253154989e+10, -4.234185297825935e+11,
3229  3.101259925467429e+12, -1.754945237689139e+13, 7.805398522969187e+13,
3230  -2.762644893141324e+14, 7.848217578377621e+14, -1.798840649081661e+15,
3231  3.333370625337169e+15, -4.988259107765304e+15, 6.000070847701146e+15,
3232  -5.749271353120764e+15, 4.324788417805135e+15, -2.496262406568326e+15,
3233  1.066418114121039e+15, -3.174727574108465e+14, 5.876970053131701e+13,
3234  -5.091588188794019e+12, 0.000000000000000e-01, -3.378098091794216e+00,
3235  1.009981094027902e+03, -9.997415292076045e+04, 4.897701324351262e+06,
3236  -1.419932385393241e+08, 2.696914741487987e+09, -3.581511558046563e+10,
3237  3.477438352489987e+11, -2.548653261914288e+12, 1.443296944374584e+13,
3238  -6.424560812216257e+13, 2.275969917931459e+14, -6.472060159591627e+14,
3239  1.485016620793322e+15, -2.755030677045359e+15, 4.127938042773006e+15,
3240  -4.971860898078912e+15, 4.770796079822418e+15, -3.594142516031414e+15,
3241  2.077829100777859e+15, -8.891455208945626e+14, 2.651635856092349e+14,
3242  -4.917666111269423e+13, 4.268671053543734e+12, 0.000000000000000e-01,
3243  2.493031698759675e+00, -7.454011644125376e+02, 7.379166798110049e+04,
3244  -3.615566630393531e+06, 1.048426846839652e+08, -1.991802210178859e+09,
3245  2.645916950749144e+10, -2.569938254028299e+11, 1.884300408926143e+12,
3246  -1.067564580288449e+13, 4.754491961430585e+13, -1.685282542848975e+14,
3247  4.795322158961934e+14, -1.101030336950954e+15, 2.044141709763629e+15,
3248  -3.065196721720791e+15, 3.694953407319221e+15, -3.548705940334544e+15,
3249  2.676012339710790e+15, -1.548605987126603e+15, 6.633870802695019e+14,
3250  -1.980596394144405e+14, 3.677511736196415e+13, -3.196139551478179e+12,
3251  0.000000000000000e-01, -1.000000000000000e+00, 2.990000000000000e+02,
3252  -2.960100000000000e+04, 1.450449000000000e+06, -4.206302100000000e+07,
3253  7.991973990000000e+08, -1.061790830100000e+10, 1.031453949240000e+11,
3254  -7.563995627760000e+11, 4.286264189064000e+12, -1.909335866037600e+13,
3255  6.769463525042400e+13, -1.926693464819760e+14, 4.425043232388240e+14,
3256  -8.217937431578160e+14, 1.232690614736724e+15, -1.486479858947226e+15,
3257  1.428186531145374e+15, -1.077403874372826e+15, 6.237601377947940e+14,
3258  -2.673257733406260e+14, 7.985055567317400e+13, -1.483389769422600e+13,
3259  1.289904147324000e+12 };
3260 
3261  static const double fem_coef_gausslob_32[1089] =
3262  { 1.000000000000000e+00, -5.280000000000000e+02, 9.275200000000000e+04,
3263  -8.115800000000000e+06, 4.236447600000000e+08, -1.462986571200000e+10,
3264  3.573867195360000e+11, -6.471252385884000e+12, 8.987850535950000e+13,
3265  -9.826716585972000e+14, 8.629643838226320e+15, -6.184578084062196e+16,
3266  3.663173172867608e+17, -1.811459261308158e+18, 7.539120925634905e+18,
3267  -2.657540126286304e+19, 7.972620378858912e+19, -2.042658293145551e+20,
3268  4.479513800757788e+20, -8.416770667739633e+20, 1.354699278902855e+21,
3269  -1.864910695632502e+21, 2.189242990525111e+21, -2.181310950704368e+21,
3270  1.832301198591669e+21, -1.285429763935079e+21, 7.434251911077520e+20,
3271  -3.481117958361696e+20, 1.286127324517868e+20, -3.607069737728273e+19,
3272  7.214139475456547e+18, -9.163120704712953e+17, 5.553406487704820e+16,
3273  0.000000000000000e-01, 7.143214682034540e+02, -1.714133648848133e+05,
3274  1.688198752795928e+07, -9.347155797218437e+08, 3.338933321339879e+10,
3275  -8.331872976904955e+11, 1.530331866800279e+13, -2.146891160964000e+14,
3276  2.364531150945150e+15, -2.087974965454055e+16, 1.502766434956253e+17,
3277  -8.930913114593062e+17, 4.428285547618542e+18, -1.847053591535166e+19,
3278  6.522650112096549e+19, -1.959752299775458e+20, 5.027465769775919e+20,
3279  -1.103711061615762e+21, 2.075747280986809e+21, -3.343657099618051e+21,
3280  4.606186697816854e+21, -5.410587449851726e+21, 5.393904740095235e+21,
3281  -4.533054367123241e+21, 3.181470251931304e+21, -1.840698151594781e+21,
3282  8.622096114618880e+20, -3.186487205259235e+20, 8.939310241964093e+19,
3283  -1.788315002192243e+19, 2.271972224754086e+18, -1.377242653770284e+17,
3284  0.000000000000000e-01, -2.859599139140576e+02, 1.263498115660723e+05,
3285  -1.563762114667972e+07, 9.735262028286150e+08, -3.727077001705718e+10,
3286  9.724728419064618e+11, -1.841437932011095e+13, 2.640184847320257e+14,
3287  -2.955001754223333e+15, 2.641501188215526e+16, -1.919333187312935e+17,
3288  1.149300695265413e+18, -5.733477927220639e+18, 2.403400433666191e+19,
3289  -8.522440623029794e+19, 2.569470483161848e+20, -6.610937005531425e+20,
3290  1.454972285683492e+21, -2.742254919882459e+21, 4.425523119288710e+21,
3291  -6.106476088763322e+21, 7.183124069502222e+21, -7.170000472640595e+21,
3292  6.032425263760434e+21, -4.238001893187230e+21, 2.454158919196046e+21,
3293  -1.150483843370953e+21, 4.254938488755735e+20, -1.194452209653931e+20,
3294  2.390927098916194e+19, -3.039204212011252e+18, 1.843238572103207e+17,
3295  0.000000000000000e-01, 1.634368826450262e+02, -7.956978254181237e+04,
3296  1.188506225092293e+07, -8.373897346830345e+08, 3.478333876388285e+10,
3297  -9.598393772867426e+11, 1.891593013667364e+13, -2.793128536050818e+14,
3298  3.196655214719607e+15, -2.907291848273606e+16, 2.141468780998689e+17,
3299  -1.296440193900301e+18, 6.525499955570070e+18, -2.755634128784674e+19,
3300  9.831738858873329e+19, -2.979627701541287e+20, 7.700118175018154e+20,
3301  -1.701110443974214e+21, 3.216663602425906e+21, -5.205922417479511e+21,
3302  7.201199888459469e+21, -8.489441777094031e+21, 8.490373918346112e+21,
3303  -7.155631502801035e+21, 5.034836798969603e+21, -2.919618180375494e+21,
3304  1.370386674687711e+21, -5.073912120857659e+20, 1.425804015450344e+20,
3305  -2.856660788223791e+19, 3.634277715764878e+18, -2.205841595819251e+17,
3306  0.000000000000000e-01, -1.089624682152292e+02, 5.490286557349962e+04,
3307  -8.781653856365252e+06, 6.724119974793967e+08, -2.993574836604601e+10,
3308  8.717420300323828e+11, -1.790617757376325e+13, 2.730388108651176e+14,
3309  -3.204823752640508e+15, 2.974036495407882e+16, -2.226577421064578e+17,
3310  1.366028725355318e+18, -6.951897867287077e+18, 2.962837694696566e+19,
3311  -1.065339992825695e+20, 3.250038142137898e+20, -8.446629720680499e+20,
3312  1.875178351120271e+21, -3.560917379168056e+21, 5.784532874816462e+21,
3313  -8.027770029015426e+21, 9.491255762425382e+21, -9.516676697643140e+21,
3314  8.038962462344214e+21, -5.667965587919967e+21, 3.292818343972966e+21,
3315  -1.548126823651629e+21, 5.740631512413311e+20, -1.615361972833789e+20,
3316  3.240477969405117e+19, -4.127262310667621e+18, 2.507669351857205e+17,
3317  0.000000000000000e-01, 7.924220268285228e+01, -4.057928795465258e+04,
3318  6.704332297502558e+06, -5.364604956918865e+08, 2.503646198522573e+10,
3319  -7.610195551213778e+11, 1.621371476972958e+13, -2.548664517300070e+14,
3320  3.067722734616486e+15, -2.906734241270257e+16, 2.214249975700081e+17,
3321  -1.378338812356282e+18, 7.101001568235638e+18, -3.058038376939241e+19,
3322  1.109399051188740e+20, -3.410471802537065e+20, 8.922579803599067e+20,
3323  -1.992320553154499e+21, 3.802564715982721e+21, -6.204660474711801e+21,
3324  8.644825045503473e+21, -1.025665248235139e+22, 1.031630159337718e+22,
3325  -8.738843624083011e+21, 6.176944575139345e+21, -3.596664164242111e+21,
3326  1.694457654020145e+21, -6.294971162057861e+20, 1.774358410868178e+20,
3327  -3.564953335849152e+19, 4.546981308698057e+18, -2.766285114923478e+17,
3328  0.000000000000000e-01, -6.094810716099949e+01, 3.149084615481936e+04,
3329  -5.296674502372112e+06, 4.346997745238327e+08, -2.090081537881765e+10,
3330  6.551264846374850e+11, -1.436792716105805e+13, 2.318076448212311e+14,
3331  -2.854539793592080e+15, 2.758693070051896e+16, -2.137570364709653e+17,
3332  1.350278421513405e+18, -7.045142142783022e+18, 3.067459655658656e+19,
3333  -1.123483766643411e+20, 3.482651662900422e+20, -9.178174833360337e+20,
3334  2.062604456625362e+21, -3.959135109240898e+21, 6.492786887393485e+21,
3335  -9.086987198956428e+21, 1.082464243206250e+22, -1.092690369776145e+22,
3336  9.286162259274268e+21, -6.583075803335110e+21, 3.843334757170004e+21,
3337  -1.815042549975247e+21, 6.757786079688690e+20, -1.908640091400089e+20,
3338  3.841802724253007e+19, -4.908370532055551e+18, 2.990786503802649e+17,
3339  0.000000000000000e-01, 4.874762271398016e+01, -2.532459924379460e+04,
3340  4.306289111489640e+06, -3.590409832532830e+08, 1.760136771205027e+10,
3341  -5.636351004936871e+11, 1.263327395525212e+13, -2.081295681322519e+14,
3342  2.613155513828582e+15, -2.570230208401814e+16, 2.023153786109967e+17,
3343  -1.296022489490302e+18, 6.846470251956364e+18, -3.013872322115386e+19,
3344  1.114644422978128e+20, -3.485183237291328e+20, 9.255531281005032e+20,
3345  -2.094244828319674e+21, 4.044473148145946e+21, -6.669094801072411e+21,
3346  9.379689895649970e+21, -1.122286017421572e+22, 1.137425276024759e+22,
3347  -9.701397530693913e+21, 6.900090712824613e+21, -4.040491989417283e+21,
3348  1.913372195656766e+21, -7.141717651945982e+20, 2.021704584417841e+20,
3349  -4.077964478229480e+19, 5.220210907153068e+18, -3.186495777814819e+17,
3350  0.000000000000000e-01, -4.013085745911482e+01, 2.092265556924549e+04,
3351  -3.583307397906160e+06, 3.019036845311046e+08, -1.499682567334736e+10,
3352  4.875419883971985e+11, -1.110534210962378e+13, 1.859662144990967e+14,
3353  -2.372232833495577e+15, 2.368570555021916e+16, -1.890606460337203e+17,
3354  1.226710982466906e+18, -6.556236864370271e+18, 2.916718348444145e+19,
3355  -1.089043462231537e+20, 3.434548724554294e+20, -9.192120758302752e+20,
3356  2.094521354663323e+21, -4.070706954543361e+21, 6.750946202167051e+21,
3357  -9.544297656724117e+21, 1.147387384551836e+22, -1.167874642179135e+22,
3358  1.000023491239336e+22, -7.138163819152158e+21, 4.193633752898508e+21,
3359  -1.991877420085289e+21, 7.455334138647318e+20, -2.115867266165027e+20,
3360  4.277941431548355e+19, -5.488110031116298e+18, 3.356769581362759e+17,
3361  0.000000000000000e-01, 3.377658303742900e+01, -1.765321539233928e+04,
3362  3.038340440514934e+06, -2.578584606807322e+08, 1.292884612296167e+10,
3363  -4.249332478575872e+11, 9.796453340445514e+12, -1.661322016030880e+14,
3364  2.146412285165976e+15, -2.170063067679739e+16, 1.753071524663780e+17,
3365  -1.150445213494342e+18, 6.214123504683469e+18, -2.791805131931260e+19,
3366  1.051885109311114e+20, -3.345072958360405e+20, 9.021185531229185e+20,
3367  -2.069976464960887e+21, 4.048800325514122e+21, -6.754020775002269e+21,
3368  9.599959543792231e+21, -1.159763408249418e+22, 1.185806715330365e+22,
3369  -1.019594067425241e+22, 7.305655578610319e+21, -4.307135697275206e+21,
3370  2.052428738060058e+21, -7.705007825196310e+20, 2.192794049399991e+20,
3371  -4.444874922276286e+19, 5.715873383290923e+18, -3.503832522669480e+17,
3372  0.000000000000000e-01, -2.892964123166297e+01, 1.514678464159201e+04,
3373  -2.616230196259168e+06, 2.232056370284014e+08, -1.126780271399590e+10,
3374  3.733563821201946e+11, -8.686293054983950e+12, 1.487584698214981e+14,
3375  -1.941627928264148e+15, 1.983312707085937e+16, -1.618550810194144e+17,
3376  1.072675099399285e+18, -5.848903282733471e+18, 2.651290247911275e+19,
3377  -1.007365700808825e+20, 3.228755039109242e+20, -8.771430385090572e+20,
3378  2.026394505724555e+21, -3.988616003559215e+21, 6.692583651440911e+21,
3379  -9.564190176741721e+21, 1.161237649908247e+22, -1.192826855978758e+22,
3380  1.030040441263462e+22, -7.409917359938946e+21, 4.384750316004612e+21,
3381  -2.096582122064279e+21, 7.895856427194460e+20, -2.253772189916786e+20,
3382  4.581095810605600e+19, -5.906211978906061e+18, 3.629208802827826e+17,
3383  0.000000000000000e-01, 2.513021588285159e+01, -1.317482888832123e+04,
3384  2.281636380391524e+06, -1.954241069277852e+08, 9.915879553852877e+09,
3385  -3.305907224268159e+11, 7.745610540950591e+12, -1.336744677758923e+14,
3386  1.759053047347007e+15, -1.812022604295268e+16, 1.491398073535739e+17,
3387  -9.967823580408796e+17, 5.480122870501913e+18, -2.504020332812559e+19,
3388  9.587106380784488e+19, -3.095239755572209e+20, 8.466795723536765e+20,
3389  -1.968748626171725e+21, 3.898845137794306e+21, -6.579450581556874e+21,
3390  9.452948974562387e+21, -1.153486704390072e+22, 1.190416296509360e+22,
3391  -1.032457212621363e+22, 7.457660044656362e+21, -4.429851231444799e+21,
3392  2.125705105699995e+21, -8.032242691112874e+20, 2.299857495593084e+20,
3393  -4.688429048988357e+19, 6.061137852550284e+18, -3.733965028540281e+17,
3394  0.000000000000000e-01, -2.208386882313948e+01, 1.158936145601140e+04,
3395  -2.011104324155879e+06, 1.727696977814699e+08, -8.800873732349352e+09,
3396  2.948204525687799e+11, -6.945679729271358e+12, 1.206045724118162e+14,
3397  -1.597549338531331e+15, 1.657073913780072e+16, -1.373597907391489e+17,
3398  9.246697496818755e+17, -5.120171153308929e+18, 2.356084529994870e+19,
3399  -9.082843603687474e+19, 2.951965214544448e+20, -8.126535950009281e+20,
3400  1.901181843699431e+21, -3.786945462658442e+21, 6.425892713139728e+21,
3401  -9.280555773871743e+21, 1.138038464790677e+22, -1.179939706531010e+22,
3402  1.027858871223671e+22, -7.455106011504378e+21, 4.445547883990988e+21,
3403  -2.141041178542259e+21, 8.118044630932303e+20, -2.331957228005324e+20,
3404  4.768370096691469e+19, -6.182197530650295e+18, 3.818855272205113e+17,
3405  0.000000000000000e-01, 1.959414243804128e+01, -1.029081802559516e+04,
3406  1.788568172854703e+06, -1.540118150914350e+08, 7.869521604579143e+09,
3407  -2.646147373681910e+11, 6.261419532268355e+12, -1.092584911616051e+14,
3408  1.455025808801897e+15, -1.517863644621452e+16, 1.265704706962783e+17,
3409  -8.572524657708660e+17, 4.776247526570586e+18, -2.211426166036566e+19,
3410  8.577380339701724e+19, -2.804435586124510e+20, 7.765584710933440e+20,
3411  -1.827036131219099e+21, 3.659136530638906e+21, -6.241580538370836e+21,
3412  9.059595877078572e+21, -1.116262879266932e+22, 1.162640401193756e+22,
3413  -1.017180635719499e+22, 7.408032173818105e+21, -4.434731590925861e+21,
3414  2.143740476291448e+21, -8.156798285468939e+20, 2.350876961959084e+20,
3415  -4.822189338581046e+19, 6.270614615621034e+18, -3.884411477495515e+17,
3416  0.000000000000000e-01, -1.752536768073206e+01, 9.210004044516183e+03,
3417  -1.602710362254713e+06, 1.382643168640165e+08, -7.082209191374808e+09,
3418  2.388593247336584e+11, -5.671955040601066e+12, 9.936819687224059e+13,
3419  -1.329133616843959e+15, 1.393095353694366e+16, -1.167468019716584e+17,
3420  7.948230830253194e+17, -4.451987054929648e+18, 2.072406047410437e+19,
3421  -8.081630829587058e+19, 2.656550395781670e+20, -7.395103797274482e+20,
3422  1.748920815324121e+21, -3.520456085792643e+21, 6.034597075619834e+21,
3423  -8.800877008017673e+21, 1.089363982096666e+22, -1.139632655550776e+22,
3424  1.001274028996965e+22, -7.321760958016250e+21, 4.400085249649023e+21,
3425  -2.134871514399776e+21, 8.151766211905410e+20, -2.357346041272461e+20,
3426  4.850993390791870e+19, -6.327377892472496e+18, 3.931001229299567e+17,
3427  0.000000000000000e-01, 1.578106132320405e+01, -8.297465341460668e+03,
3428  1.445356637015484e+06, -1.248763055461196e+08, 6.409121288934440e+09,
3429  -2.166867323836831e+11, 5.160255428324136e+12, -9.069980923376013e+13,
3430  1.217593153323901e+15, -1.281217702947176e+16, 1.078222149705347e+17,
3431  -7.373025946691738e+17, 4.148685852384210e+18, -1.940267191328230e+19,
3432  7.602301795140850e+19, -2.510934651183994e+20, 7.023105241061891e+20,
3433  -1.668804442314510e+21, 3.374862747204858e+21, -5.811516441898685e+21,
3434  8.513453677248631e+21, -1.058376696971405e+22, 1.111895644585412e+22,
3435  -9.809014479986894e+21, 7.201130357372178e+21, -4.344074707924148e+21,
3436  2.115422234515678e+21, -8.105961395642809e+20, 2.352029716821803e+20,
3437  -4.855759087275033e+19, 6.353294711027987e+18, -3.958864781209368e+17,
3438  0.000000000000000e-01, -1.429082487951404e+01, 7.516973886624383e+03,
3439  -1.310468641451437e+06, 1.133605392742571e+08, -5.827511997735239e+09,
3440  1.974178249055285e+11, -4.712515373341917e+12, 8.305450385112180e+13,
3441  -1.118328972822835e+15, 1.180653064142852e+16, -9.971166758181266e+16,
3442  6.844038883665075e+17, -3.866168854945464e+18, 1.815490936983781e+19,
3443  -7.143043815405257e+19, 2.369235292422868e+20, -6.655061581666021e+20,
3444  1.588114879269808e+21, -3.225364968659972e+21, 5.577529629049808e+21,
3445  -8.204710901105034e+21, 1.024169036500672e+22, -1.080270746628453e+22,
3446  9.567317871713345e+21, -7.050459812170524e+21, 4.268932026970228e+21,
3447  -2.086295163199683e+21, 8.022143863884770e+20, -2.335532639673231e+20,
3448  4.837349156604751e+19, -6.349020768043736e+18, 3.968137980027335e+17,
3449  0.000000000000000e-01, 1.300209931372656e+01, -6.841393840416191e+03,
3450  1.193492661387020e+06, -1.033456200764548e+08, 5.319778623982719e+09,
3451  -1.805161947596514e+11, 4.317533185036128e+12, -7.626509475155619e+13,
3452  1.029508945956098e+15, -1.089906772387182e+16, 9.232461935811958e+16,
3453  -6.357336264452389e+17, 3.603376239255576e+18, -1.698055636889742e+19,
3454  6.705347306221760e+19, -2.232368248073979e+20, 6.294452022548759e+20,
3455  -1.507836188614350e+21, 3.074157987189278e+21, -5.336595912526426e+21,
3456  7.880489249366001e+21, -9.874488341898865e+21, 1.045462363245188e+22,
3457  -9.293378659359744e+21, 6.873520006757566e+21, -4.176636208226636e+21,
3458  2.048299449271481e+21, -7.902800175855315e+20, 2.308396453521622e+20,
3459  -4.796514797886738e+19, 6.315072588841990e+18, -3.958864781209368e+17,
3460  0.000000000000000e-01, -1.187480374787823e+01, 6.249975469245804e+03,
3461  -1.090926975816432e+06, 9.454341715249161e+07, -4.872094426264295e+09,
3462  1.655534657183789e+11, -3.966168303111664e+12, 7.019129535830873e+13,
3463  -9.495382387492220e+14, 1.007610862599221e+16, -8.557186874129430e+16,
3464  5.908530248892806e+17, -3.358744210862016e+18, 1.587616779782261e+19,
3465  -6.289207145157216e+19, 2.100713184820985e+20, -5.943219992524428e+20,
3466  1.428595119033459e+21, -2.922754970902040e+21, 5.091600520853282e+21,
3467  -7.545231007708337e+21, 9.487734903251288e+21, -1.008041543577854e+22,
3468  8.991956191593799e+21, -6.673509171379833e+21, 4.068893946683280e+21,
3469  -2.002141237919232e+21, 7.750111453424084e+20, -2.271093028431890e+20,
3470  4.733888021452981e+19, -6.251826041286116e+18, 3.931001229299567e+17,
3471  0.000000000000000e-01, 1.087774446529347e+01, -5.726532522119743e+03,
3472  1.000026921141720e+06, -8.672640379209894e+07, 4.473426627332310e+09,
3473  -1.521830785057648e+11, 3.650893458666403e+12, -6.471493237339299e+13,
3474  8.770338012270925e+14, -9.325329559951301e+15, 7.936874744339234e+16,
3475  -5.493120646406107e+17, 3.130441935246294e+18, -1.483627518494573e+19,
3476  5.893595494590624e+19, -1.974260043524307e+20, 5.602136541583943e+20,
3477  -1.350733620606971e+21, 2.772103374812838e+21, -4.844503527518292e+21,
3478  7.202129004924270e+21, -9.085610385118606e+21, 9.684512731454793e+21,
3479  -8.666845324741530e+21, 6.453034816508831e+21, -3.947120866745059e+21,
3480  1.948412902571092e+21, -7.565912375504262e+20, 2.224014019524002e+20,
3481  -4.649964958533596e+19, 6.159502112364614e+18, -3.884411477495515e+17,
3482  0.000000000000000e-01, -9.986140223631332e+00, 5.258180249016786e+03,
3483  -9.185985927746997e+05, 7.971153565650261e+07, -4.114819554974130e+09,
3484  1.401203840137855e+11, -3.365432249133715e+12, 5.973558126785002e+13,
3485  -8.107918476058353e+14, 8.635671857055418e+15, -7.363618322103649e+16,
3486  5.106667921634938e+17, -2.916510065095704e+18, 1.385415474244305e+19,
3487  -5.516783142970931e+19, 1.852714215024819e+20, -5.271074464383260e+20,
3488  1.274366202537370e+21, -2.622681385943975e+21, 4.596469304424025e+21,
3489  -6.853262795168416e+21, 8.671008970964122e+21, -9.270120999117532e+21,
3490  8.320885075782802e+21, -6.214097196642535e+21, 3.812422050430118e+21,
3491  -1.887580884371838e+21, 7.351640810621922e+20, -2.167456694682573e+20,
3492  4.545079901812915e+19, -6.038139340406067e+18, 3.818855272205113e+17,
3493  0.000000000000000e-01, 9.179865311132163e+00, -4.834435688158695e+03,
3494  8.448504512588955e+05, -7.334848338052211e+07, 3.788859743400152e+09,
3495  -1.291272970868570e+11, 3.104465491388026e+12, -5.516672358352230e+13,
3496  7.497538905042167e+14, -7.997160527339879e+15, 6.830050930752028e+16,
3497  -4.744858033268795e+17, 2.714931990926294e+18, -1.292227727069609e+19,
3498  5.156543365822560e+19, -1.735567332289304e+20, 4.949202035461436e+20,
3499  -1.199422235955881e+21, 2.474571823687724e+21, -4.347969142753134e+21,
3500  6.499709691677232e+21, -8.245627749154246e+21, 8.839266680637617e+21,
3501  -7.955961175047700e+21, 5.958068545674167e+21, -3.665569136784129e+21,
3502  1.819971125502232e+21, -7.108274904080239e+20, 2.101605178572964e+20,
3503  -4.419368247642274e+19, 5.887550238778617e+18, -3.733965028540281e+17,
3504  0.000000000000000e-01, -8.442157387023658e+00, 4.446553379007233e+03,
3505  -7.772828492878541e+05, 6.751075382325961e+07, -3.489264209336539e+09,
3506  1.190001385182876e+11, -2.863388547750731e+12, 5.093235749821151e+13,
3507  -6.929732092529343e+14, 7.400674318693824e+15, -6.329249553366740e+16,
3508  4.403495020338399e+17, -2.523657530207839e+18, 1.203252080967825e+19,
3509  -4.810263202989546e+19, 1.622139284826088e+20, -4.635104707077193e+20,
3510  1.125673633860567e+21, -2.327511860731306e+21, 4.098851177315484e+21,
3511  -6.141619421494262e+21, 7.810022020551529e+21, -8.392815674436741e+21,
3512  7.572989471395764e+21, -5.685659534933809e+21, 3.506969466398297e+21,
3513  -1.745750145592470e+21, 6.836250778812437e+20, -2.026505202012846e+20,
3514  4.272714338022826e+19, -5.707256190142981e+18, 3.629208802827826e+17,
3515  0.000000000000000e-01, 7.758620432176431e+00, -4.087010780643976e+03,
3516  7.146017483117621e+05, -6.208866298624787e+07, 3.210548205967185e+09,
3517  -1.095595506626254e+11, 2.638102073062174e+12, -4.696390598303079e+13,
3518  6.395814992099562e+14, -6.837680401038084e+15, 5.854580721511378e+16,
3519  -4.078439182746133e+17, 2.340589674143266e+18, -1.117619206099512e+19,
3520  4.474976818167516e+19, -1.511594767319364e+20, 4.326839217130804e+20,
3521  -1.052747833818875e+21, 2.180916376866737e+21, -3.848371023940319e+21,
3522  5.778239784350781e+21, -7.363608932672221e+21, 7.930445122237345e+21,
3523  -7.171862635842173e+21, 5.396860454297140e+21, -3.336620071079666e+21,
3524  1.664898414527208e+21, -6.535348447882521e+20, 1.942028797566696e+20,
3525  -4.104676746515045e+19, 5.496390689251412e+18, -3.503832522669480e+17,
3526  0.000000000000000e-01, -7.116397718865410e+00, 3.749079648317452e+03,
3527  -6.556462179536947e+05, 5.698334876317732e+07, -2.947736407946278e+09,
3528  1.006414850064029e+11, -2.424817814258759e+12, 4.319719539696606e+13,
3529  -5.887538442457942e+14, 6.299924892323114e+15, -5.399488828717867e+16,
3530  3.765493816021260e+17, -2.163536905559044e+18, 1.034386803998833e+19,
3531  -4.147323866260055e+19, 1.402934443266815e+20, -4.021917192563760e+20,
3532  9.801245774469403e+20, -2.033870287254597e+21, 3.595172619362371e+21,
3533  -5.407874926278053e+21, 6.904593808205439e+21, -7.450539640286401e+21,
3534  6.751333782133479e+21, -5.090837485270753e+21, 3.154034661016916e+21,
3535  -1.577170275266693e+21, 6.204523939342194e+20, -1.847822507348537e+20,
3536  3.914377458647115e+19, -5.253552629244530e+18, 3.356769581362759e+17,
3537  0.000000000000000e-01, 6.503405049947615e+00, -3.426426844095358e+03,
3538  5.993202798185401e+05, -5.210105929407407e+07, 2.696081626301935e+09,
3539  -9.208817752140222e+10, 2.219856964226088e+12, -3.956916806058024e+13,
3540  5.396682472814272e+14, -5.779046608150560e+15, 4.957204191401071e+16,
3541  -3.460227309661112e+17, 1.990124376198793e+18, -9.525027063011665e+18,
3542  3.823419916527245e+19, -1.294955870987350e+20, 3.717202435921960e+20,
3543  -9.071121012468153e+20, 1.885079625280803e+21, -3.337199379905083e+21,
3544  5.027744029565647e+21, -6.429775852763725e+21, 6.949963688436526e+21,
3545  -6.308792489007701e+21, 4.765750352591050e+21, -2.958122806424166e+21,
3546  1.482030100296912e+21, -5.841647400501416e+20, 1.743227189970331e+20,
3547  -3.700329724016468e+19, 4.976575581854351e+18, -3.186495777814819e+17,
3548  0.000000000000000e-01, -5.907497514106532e+00, 3.112678595829013e+03,
3549  -5.445178292388210e+05, 4.734677219183480e+07, -2.450744429063559e+09,
3550  8.373760838189771e+10, -2.019407140707212e+12, 3.601376581781814e+13,
3551  -4.914525865076907e+14, 5.266042927583444e+15, -4.520313655093684e+16,
3552  3.157692701941383e+17, -1.817642904902012e+18, 8.707370090912989e+18,
3553  -3.498599158499494e+19, 1.186170493957938e+20, -3.408681448268105e+20,
3554  8.327925173944575e+20, -1.732759335262471e+21, 3.071495239478500e+21,
3555  -4.633677555133575e+21, 5.934150774303194e+21, -6.423619232920034e+21,
3556  5.839849717449368e+21, -4.418427829351906e+21, 2.746981777317360e+21,
3557  -1.378544874829898e+21, 5.443069194938188e+20, -1.627146166161762e+20,
3558  3.460155133741941e+19, -4.662146280112927e+18, 2.990786503802649e+17,
3559  0.000000000000000e-01, 5.315369270978286e+00, -2.800843064095075e+03,
3560  4.900224139921877e+05, -4.261558203433840e+07, 2.206354210150574e+09,
3561  -7.540878769771313e+10, 1.819175365822707e+12, -3.245589496559513e+13,
3562  4.431044900769581e+14, -4.750435903707279e+15, 4.080066038394767e+16,
3563  -2.851956961225284e+17, 1.642785899790599e+18, -7.875595013484737e+18,
3564  3.166934141851351e+19, -1.074644294009643e+20, 3.091013384752239e+20,
3565  -7.559132271023600e+20, 1.574408999942342e+21, -2.793807988826481e+21,
3566  4.219517259473626e+21, -5.410137053845813e+21, 5.863599367756335e+21,
3567  -5.337558212358710e+21, 4.043769184497504e+21, -2.517518733791446e+21,
3568  1.265191806068099e+21, -5.002850262989436e+20, 1.497812681253764e+20,
3569  -3.190085448905626e+19, 4.305131059057072e+18, -2.766285114923478e+17,
3570  0.000000000000000e-01, -4.710772351834030e+00, 2.482373368683492e+03,
3571  -4.343438634071739e+05, 3.777856440947868e+07, -1.956282178028853e+09,
3572  6.687710881826573e+10, -1.613799071688983e+12, 2.880102840436904e+13,
3573  -3.933509953446171e+14, 4.218785748675981e+15, -3.625111116519231e+16,
3574  2.535230396849270e+17, -1.461153893751222e+18, 7.009048271913450e+18,
3575  -2.820301208876073e+19, 9.576835312471221e+19, -2.756632919785344e+20,
3576  6.746687832309763e+20, -1.406360250100074e+21, 2.497787658823857e+21,
3577  -3.775905442111079e+21, 4.846020652107188e+21, -5.257496778824818e+21,
3578  4.790865278530114e+21, -3.633565158982738e+21, 2.264711978580421e+21,
3579  -1.139484606704540e+21, 4.511274997631573e+20, -1.352342175988863e+20,
3580  2.884004791547230e+19, -3.897279615275436e+18, 2.507669351857205e+17,
3581  0.000000000000000e-01, 4.070989770987400e+00, -2.145310206509185e+03,
3582  3.753936962817004e+05, -3.265459454227024e+07, 1.691185508550510e+09,
3583  -5.782472303217436e+10, 1.395652621524724e+12, -2.491398584416296e+13,
3584  3.403599167085817e+14, -3.651608452505086e+15, 3.138862675548854e+16,
3585  -2.196030665561983e+17, 1.266200972268635e+18, -6.076691812326445e+18,
3586  2.446363025550984e+19, -8.311520079137181e+19, 2.393790730533568e+20,
3587  -5.862224225217512e+20, 1.222781062900224e+21, -2.173219858365351e+21,
3588  3.287615107047680e+21, -4.222527251629046e+21, 4.584681175928391e+21,
3589  -4.181215238485294e+21, 3.173915831158933e+21, -1.979997675938663e+21,
3590  9.971596317435381e+20, -3.951620422561584e+20, 1.185761286177830e+20,
3591  -2.531374184616153e+19, 3.424415390856724e+18, -2.205841595819251e+17,
3592  0.000000000000000e-01, -3.358090451409268e+00, 1.769674233094550e+03,
3593  -3.096791496404924e+05, 2.694027470522958e+07, -1.395380783042074e+09,
3594  4.771664530498290e+10, -1.151859937920620e+12, 2.056566436202355e+13,
3595  -2.810129791321012e+14, 3.015587336970416e+15, -2.592812452685370e+16,
3596  1.814511218788989e+17, -1.046544742872117e+18, 5.024209499496014e+18,
3597  -2.023384009065594e+19, 6.877115067771995e+19, -1.981490581745830e+20,
3598  4.854671646250063e+20, -1.013093139325803e+21, 1.801437605201838e+21,
3599  -2.726610427990654e+21, 3.503909183048419e+21, -3.806619619529808e+21,
3600  3.473717880327268e+21, -2.638522642188920e+21, 1.647082019674793e+21,
3601  -8.300649678444784e+20, 3.291782934571713e+20, -9.884928188742345e+19,
3602  2.111857359313218e+19, -2.859159218719010e+18, 1.843238572103207e+17,
3603  0.000000000000000e-01, 2.488636218117664e+00, -1.311502616747683e+03,
3604  2.295099147207366e+05, -1.996696431094197e+07, 1.034261165808075e+09,
3605  -3.537054923192207e+10, 8.539117568460436e+11, -1.524770635014292e+13,
3606  2.083740755848528e+14, -2.236412246676083e+15, 1.923184048547382e+16,
3607  -1.346128075294067e+17, 7.765487558375990e+17, -3.728808938617731e+18,
3608  1.502032959138465e+19, -5.106384693104742e+19, 1.471677691807719e+20,
3609  -3.606628515829967e+20, 7.528686576360846e+20, -1.339136443296313e+21,
3610  2.027551807534738e+21, -2.606468672347013e+21, 2.832680005398635e+21,
3611  -2.585940609411422e+21, 1.964981315222245e+21, -1.227139920687813e+21,
3612  6.186996825719858e+20, -2.454684425809199e+20, 7.374666999744300e+19,
3613  -1.576324668155186e+19, 2.135204267310823e+18, -1.377242653770284e+17,
3614  0.000000000000000e-01, -1.000000000000000e+00, 5.270000000000000e+02,
3615  -9.222500000000000e+04, 8.023575000000000e+06, -4.156211850000000e+08,
3616  1.421424452700000e+10, -3.431724750090000e+11, 6.128079910875000e+12,
3617  -8.375042544862500e+13, 8.989212331485750e+14, -7.730722605077745e+15,
3618  5.411505823554421e+16, -3.122022590512166e+17, 1.499257002256941e+18,
3619  -6.039863923377964e+18, 2.053553733948508e+19, -5.919066644910405e+19,
3620  1.450751628654511e+20, -3.028762172103277e+20, 5.388008495636356e+20,
3621  -8.158984293392197e+20, 1.049012266293282e+21, -1.140230724231829e+21,
3622  1.041080226472539e+21, -7.912209721191298e+20, 4.942087918159488e+20,
3623  -2.492163992918032e+20, 9.889539654436636e+19, -2.971733590742043e+19,
3624  6.353361469862300e+18, -8.607780055942471e+17, 5.553406487704820e+16 };
3625 
3626  static const double *fem_coeff_gausslob[] =
3627  { 0, fem_coef_gausslob_1, fem_coef_gausslob_2, fem_coef_gausslob_3,
3628  fem_coef_gausslob_4, fem_coef_gausslob_5, fem_coef_gausslob_6, fem_coef_gausslob_7, fem_coef_gausslob_8,
3629  fem_coef_gausslob_9, fem_coef_gausslob_10, fem_coef_gausslob_11, fem_coef_gausslob_12, fem_coef_gausslob_13,
3630  fem_coef_gausslob_14, 0, fem_coef_gausslob_16, 0, 0, 0, 0, 0, 0, 0, fem_coef_gausslob_24, 0, 0, 0, 0, 0, 0, 0,
3631  fem_coef_gausslob_32, };
3632 
3633  const unsigned fem_coeff_gausslob_max_k = 33;
3634 
3635 
3636  class PK_GL_fem_ : public fem<base_poly> {
3637  public :
3638  PK_GL_fem_(unsigned k);
3639  };
3640 
3641  PK_GL_fem_::PK_GL_fem_(unsigned k) {
3642  cvr = bgeot::simplex_of_reference(1);
3643  dim_ = cvr->structure()->dim();
3644  is_standard_fem = is_equiv = is_pol = is_lag = true;
3645  es_degree = short_type(k);
3646  GMM_ASSERT1(k < fem_coeff_gausslob_max_k && fem_coeff_gausslob[k],
3647  "try another degree");
3648  init_cvs_node();
3649  std::stringstream sstr; sstr << "IM_GAUSSLOBATTO1D(" << k*2-1 << ")";
3650  pintegration_method gl_im = int_method_descriptor(sstr.str());
3651  std::vector<base_node> points(k+1);
3652  for (size_type i = 0; i < k+1; ++i) {
3653  points[i] = gl_im->approx_method()->point(i);
3654  }
3655  std::sort(points.begin(),points.end());
3656  for (size_type i = 0; i < k+1; ++i)
3657  add_node(lagrange_dof(1), points[i]);
3658  base_.resize(k+1);
3659  const double *coefs = fem_coeff_gausslob[k];
3660  for (size_type r = 0; r < k+1; r++) {
3661  base_[r] = base_poly(1,short_type(k));
3662  std::copy(coefs, coefs+k+1, base_[r].begin());
3663  coefs += k+1;
3664  }
3665  }
3666 
3667  static pfem PK_GL_fem(fem_param_list &params,
3668  std::vector<dal::pstatic_stored_object> &dependencies) {
3669  GMM_ASSERT1(params.size() == 1, "Bad number of parameters : "
3670  << params.size() << " should be 1.");
3671  GMM_ASSERT1(params[0].type() == 0, "Bad type of parameters");
3672  int k = int(::floor(params[0].num() + 0.01));
3673  pfem p = std::make_shared<PK_GL_fem_>(k);
3674  dependencies.push_back(p->ref_convex(0));
3675  dependencies.push_back(p->node_tab(0));
3676  return p;
3677  }
3678 
3679  /* ******************************************************************** */
3680  /* Hermite element on the segment */
3681  /* ******************************************************************** */
3682 
3683  struct hermite_segment__ : public fem<base_poly> {
3684  virtual void mat_trans(base_matrix &M, const base_matrix &G,
3685  bgeot::pgeometric_trans pgt) const;
3686  hermite_segment__();
3687  };
3688 
3689  void hermite_segment__::mat_trans(base_matrix &M,
3690  const base_matrix &G,
3691  bgeot::pgeometric_trans pgt) const {
3692  THREAD_SAFE_STATIC bgeot::pgeotrans_precomp pgp;
3693  THREAD_SAFE_STATIC bgeot::pgeometric_trans pgt_stored = nullptr;
3694  THREAD_SAFE_STATIC base_matrix K(1, 1);
3695  THREAD_SAFE_STATIC base_vector r(1);
3696  dim_type N = dim_type(G.nrows());
3697 
3698  if (pgt != pgt_stored) {
3699  gmm::resize(r, N);
3700  for (size_type i = 0; i < N; ++i) r[i] = ::exp(double(i));
3701  pgt_stored = pgt;
3702  pgp = bgeot::geotrans_precomp(pgt, node_tab(0), 0);
3703  gmm::resize(K, N, 1);
3704  }
3705  gmm::copy(gmm::identity_matrix(), M);
3706  // gradient at point 0
3707  gmm::mult(G, pgp->grad(1), K);
3708  if (N == 1) M(1, 1) = K(0,0);
3709  else M(1, 1) = gmm::mat_euclidean_norm(K)
3710  * gmm::sgn(gmm::vect_sp(gmm::mat_col(K, 0), r));
3711  // gradient at point 1
3712  if (!(pgt->is_linear())) gmm::mult(G, pgp->grad(3), K);
3713  if (N == 1) M(3, 3) = K(0,0);
3714  else M(3, 3) = gmm::mat_euclidean_norm(K)
3715  * gmm::sgn(gmm::vect_sp(gmm::mat_col(K, 0), r));
3716  }
3717 
3718  // Hermite element on the segment. when the real element lies in
3719  // a 2 or 3 dimensional domain, the element should still work if
3720  // the tangent coincides.
3721  hermite_segment__::hermite_segment__() {
3722  base_node pt(1);
3723  cvr = bgeot::simplex_of_reference(1);
3724  dim_ = cvr->structure()->dim();
3725  init_cvs_node();
3726  es_degree = 3;
3727  is_pol = true;
3728  is_standard_fem = is_lag = is_equiv = false;
3729  base_.resize(4);
3730 
3731  pt[0] = 0.0; add_node(lagrange_dof(1), pt);
3732  read_poly(base_[0], 1, "(1 - x)^2*(2*x + 1)");
3733 
3734  pt[0] = 0.0; add_node(derivative_dof(1, 0), pt);
3735  read_poly(base_[1], 1, "x*(x - 1)*(x - 1)");
3736 
3737  pt[0] = 1.0; add_node(lagrange_dof(1), pt);
3738  read_poly(base_[2], 1, "x*x*(3 - 2*x)");
3739 
3740  pt[0] = 1.0; add_node(derivative_dof(1, 0), pt);
3741  read_poly(base_[3], 1, "x*x*(x - 1)");
3742  }
3743 
3744  /* ******************************************************************** */
3745  /* Hermite element on the triangle */
3746  /* ******************************************************************** */
3747 
3748  struct hermite_triangle__ : public fem<base_poly> {
3749  virtual void mat_trans(base_matrix &M, const base_matrix &G,
3750  bgeot::pgeometric_trans pgt) const;
3751  hermite_triangle__();
3752  };
3753 
3754  void hermite_triangle__::mat_trans(base_matrix &M,
3755  const base_matrix &G,
3756  bgeot::pgeometric_trans pgt) const {
3757 
3758  THREAD_SAFE_STATIC bgeot::pgeotrans_precomp pgp;
3759  THREAD_SAFE_STATIC bgeot::pgeometric_trans pgt_stored = nullptr;
3760  THREAD_SAFE_STATIC base_matrix K(2, 2);
3761  dim_type N = dim_type(G.nrows());
3762 
3763  GMM_ASSERT1(N == 2, "Sorry, this version of hermite "
3764  "element works only in dimension two.")
3765  if (pgt != pgt_stored)
3766  { pgt_stored = pgt; pgp = bgeot::geotrans_precomp(pgt, node_tab(0), 0); }
3767  gmm::copy(gmm::identity_matrix(), M);
3768 
3769  gmm::mult(G, pgp->grad(0), K);
3770  for (size_type i = 0; i < 3; ++i) {
3771  if (i && !(pgt->is_linear())) gmm::mult(G, pgp->grad(i*3), K);
3772  gmm::copy(K, gmm::sub_matrix(M, gmm::sub_interval(1+3*i, 2)));
3773  }
3774  }
3775 
3776  hermite_triangle__::hermite_triangle__() {
3777  cvr = bgeot::simplex_of_reference(2);
3778  dim_ = cvr->structure()->dim();
3779  init_cvs_node();
3780  es_degree = 3;
3781  is_pol = true;
3782  is_standard_fem = is_lag = is_equiv = false;
3783  base_.resize(10);
3784 
3785  add_node(lagrange_dof(2), base_node(0.0, 0.0));
3786  read_poly(base_[0], 2, "(1 - x - y)*(1 + x + y - 2*x*x - 11*x*y - 2*y*y)");
3787 
3788  add_node(derivative_dof(2, 0), base_node(0.0, 0.0));
3789  read_poly(base_[1], 2, "x*(1 - x - y)*(1 - x - 2*y)");
3790 
3791  add_node(derivative_dof(2, 1), base_node(0.0, 0.0));
3792  read_poly(base_[2], 2, "y*(1 - x - y)*(1 - 2*x - y)");
3793 
3794  add_node(lagrange_dof(2), base_node(1.0, 0.0));
3795  read_poly(base_[3], 2, "-2*x*x*x + 7*x*x*y + 7*x*y*y + 3*x*x - 7*x*y");
3796 
3797  add_node(derivative_dof(2, 0), base_node(1.0, 0.0));
3798  read_poly(base_[4], 2, "x*x*x - 2*x*x*y - 2*x*y*y - x*x + 2*x*y");
3799 
3800  add_node(derivative_dof(2, 1), base_node(1.0, 0.0));
3801  read_poly(base_[5], 2, "x*y*(2*x + y - 1)");
3802 
3803  add_node(lagrange_dof(2), base_node(0.0, 1.0));
3804  read_poly(base_[6], 2, "7*x*x*y + 7*x*y*y - 2*y*y*y + 3*y*y - 7*x*y");
3805 
3806  add_node(derivative_dof(2, 0), base_node(0.0, 1.0));
3807  read_poly(base_[7], 2, "x*y*(x + 2*y - 1)");
3808 
3809  add_node(derivative_dof(2, 1), base_node(0.0, 1.0));
3810  read_poly(base_[8], 2, "y*y*y - 2*y*y*x - 2*y*x*x - y*y + 2*x*y");
3811 
3812  add_node(lagrange_dof(2), base_node(1.0/3.0, 1.0/3.0));
3813  read_poly(base_[9], 2, "27*x*y*(1 - x - y)");
3814 
3815  }
3816 
3817  /* ******************************************************************** */
3818  /* Hermite element on the tetrahedron */
3819  /* ******************************************************************** */
3820 
3821  struct hermite_tetrahedron__ : public fem<base_poly> {
3822  virtual void mat_trans(base_matrix &M, const base_matrix &G,
3823  bgeot::pgeometric_trans pgt) const;
3824  hermite_tetrahedron__();
3825  };
3826 
3827  void hermite_tetrahedron__::mat_trans(base_matrix &M,
3828  const base_matrix &G,
3829  bgeot::pgeometric_trans pgt) const {
3830  THREAD_SAFE_STATIC bgeot::pgeotrans_precomp pgp;
3831  THREAD_SAFE_STATIC bgeot::pgeometric_trans pgt_stored = nullptr;
3832  THREAD_SAFE_STATIC base_matrix K(3, 3);
3833  dim_type N = dim_type(G.nrows());
3834  GMM_ASSERT1(N == 3, "Sorry, this version of hermite "
3835  "element works only on dimension three.")
3836  if (pgt != pgt_stored)
3837  { pgt_stored = pgt; pgp = bgeot::geotrans_precomp(pgt, node_tab(0), 0); }
3838  gmm::copy(gmm::identity_matrix(), M);
3839 
3840  gmm::mult(G, pgp->grad(0), K);
3841  for (size_type k = 0; k < 4; ++k) {
3842  if (k && !(pgt->is_linear())) gmm::mult(G, pgp->grad(k*4), K);
3843  gmm::copy(K, gmm::sub_matrix(M, gmm::sub_interval(1+4*k, 3)));
3844  }
3845  }
3846 
3847  hermite_tetrahedron__::hermite_tetrahedron__() {
3848  cvr = bgeot::simplex_of_reference(3);
3849  dim_ = cvr->structure()->dim();
3850  init_cvs_node();
3851  es_degree = 3;
3852  is_pol = true;
3853  is_standard_fem = is_lag = is_equiv = false;
3854  base_.resize(20);
3855  std::stringstream s
3856  ( "1 - 3*x*x - 13*x*y - 13*x*z - 3*y*y - 13*y*z - 3*z*z + 2*x*x*x"
3857  "+ 13*x*x*y + 13*x*x*z + 13*x*y*y + 33*x*y*z + 13*x*z*z + 2*y*y*y"
3858  "+ 13*y*y*z + 13*y*z*z + 2*z*z*z;"
3859  "x - 2*x*x - 3*x*y - 3*x*z + x*x*x + 3*x*x*y + 3*x*x*z + 2*x*y*y"
3860  "+ 4*x*y*z + 2*x*z*z;"
3861  "y - 3*x*y - 2*y*y - 3*y*z + 2*x*x*y + 3*x*y*y + 4*x*y*z"
3862  "+ y*y*y + 3*y*y*z + 2*y*z*z;"
3863  "z - 3*x*z - 3*y*z - 2*z*z + 2*x*x*z + 4*x*y*z + 3*x*z*z"
3864  "+ 2*y*y*z + 3*y*z*z + z*z*z;"
3865  "3*x*x - 7*x*y - 7*x*z - 2*x*x*x + 7*x*x*y + 7*x*x*z + 7*x*y*y"
3866  "+ 7*x*y*z + 7*x*z*z;"
3867  "-x*x + 2*x*y + 2*x*z + x*x*x - 2*x*x*y - 2*x*x*z - 2*x*y*y"
3868  "- 2*x*y*z - 2*x*z*z;"
3869  "-x*y + 2*x*x*y + x*y*y;"
3870  "-x*z + 2*x*x*z + x*z*z;"
3871  "-7*x*y + 3*y*y - 7*y*z + 7*x*x*y + 7*x*y*y + 7*x*y*z - 2*y*y*y"
3872  "+ 7*y*y*z + 7*y*z*z;"
3873  "-x*y + x*x*y + 2*x*y*y;"
3874  "2*x*y - y*y + 2*y*z - 2*x*x*y - 2*x*y*y - 2*x*y*z + y*y*y"
3875  "- 2*y*y*z - 2*y*z*z;"
3876  "-y*z + 2*y*y*z + y*z*z;"
3877  "-7*x*z - 7*y*z + 3*z*z + 7*x*x*z + 7*x*y*z + 7*x*z*z + 7*y*y*z"
3878  "+ 7*y*z*z - 2*z*z*z;"
3879  "-x*z + x*x*z + 2*x*z*z;"
3880  "-y*z + y*y*z + 2*y*z*z;"
3881  "2*x*z + 2*y*z - z*z - 2*x*x*z - 2*x*y*z - 2*x*z*z - 2*y*y*z"
3882  "- 2*y*z*z + z*z*z;"
3883  "27*x*y*z;"
3884  "27*y*z - 27*x*y*z - 27*y*y*z - 27*y*z*z;"
3885  "27*x*z - 27*x*x*z - 27*x*y*z - 27*x*z*z;"
3886  "27*x*y - 27*x*x*y - 27*x*y*y - 27*x*y*z;");
3887 
3888  base_node pt(3);
3889  for (unsigned k = 0; k < 5; ++k) {
3890  for (unsigned i = 0; i < 4; ++i) {
3891  base_[k*4+i] = read_base_poly(3, s);
3892  pt[0] = pt[1] = pt[2] = ((k == 4) ? 1.0/3.0 : 0.0);
3893  if (k == 4 && i) pt[i-1] = 0.0;
3894  if (k < 4 && k) pt[k-1] = 1.0;
3895  if (k == 4 || i == 0) add_node(lagrange_dof(3), pt);
3896  else add_node(derivative_dof(3, dim_type(i-1)), pt);
3897  }
3898  }
3899  }
3900 
3901  static pfem Hermite_fem(fem_param_list &params,
3902  std::vector<dal::pstatic_stored_object> &dependencies) {
3903  GMM_ASSERT1(params.size() == 1, "Bad number of parameters : "
3904  << params.size() << " should be 1.");
3905  GMM_ASSERT1(params[0].type() == 0, "Bad type of parameters");
3906  int d = int(::floor(params[0].num() + 0.01));
3907  pfem p;
3908  switch(d) {
3909  case 1 : p = std::make_shared<hermite_segment__>(); break;
3910  case 2 : p = std::make_shared<hermite_triangle__>(); break;
3911  case 3 : p = std::make_shared<hermite_tetrahedron__>(); break;
3912  default : GMM_ASSERT1(false, "Sorry, Hermite element in dimension "
3913  << d << " not available");
3914  }
3915  dependencies.push_back(p->ref_convex(0));
3916  dependencies.push_back(p->node_tab(0));
3917  return pfem(p);
3918  }
3919 
3920  /* ******************************************************************** */
3921  /* Argyris element on the triangle */
3922  /* ******************************************************************** */
3923 
3924  struct argyris_triangle__ : public fem<base_poly> {
3925  virtual void mat_trans(base_matrix &M, const base_matrix &G,
3926  bgeot::pgeometric_trans pgt) const;
3927  argyris_triangle__();
3928  };
3929 
3930  void argyris_triangle__::mat_trans(base_matrix &M,
3931  const base_matrix &G,
3932  bgeot::pgeometric_trans pgt) const {
3933 
3934  THREAD_SAFE_STATIC bgeot::pgeotrans_precomp pgp;
3935  THREAD_SAFE_STATIC pfem_precomp pfp;
3936  THREAD_SAFE_STATIC bgeot::pgeometric_trans pgt_stored = nullptr;
3937  THREAD_SAFE_STATIC base_matrix K(2, 2);
3938  dim_type N = dim_type(G.nrows());
3939  GMM_ASSERT1(N == 2, "Sorry, this version of argyris "
3940  "element works only on dimension two.")
3941  if (pgt != pgt_stored) {
3942  pgt_stored = pgt;
3943  pgp = bgeot::geotrans_precomp(pgt, node_tab(0), 0);
3944  pfp = fem_precomp(std::make_shared<argyris_triangle__>(), node_tab(0), 0);
3945  }
3946  gmm::copy(gmm::identity_matrix(), M);
3947 
3948  gmm::mult(G, pgp->grad(0), K); // gradient at point (0, 0)
3949  for (unsigned k = 0; k < 3; ++k) {
3950  if (k && !(pgt->is_linear())) gmm::mult(G, pgp->grad(6*k), K);
3951  M(1+6*k, 1+6*k) = K(0,0); M(1+6*k, 2+6*k) = K(0,1);
3952  M(2+6*k, 1+6*k) = K(1,0); M(2+6*k, 2+6*k) = K(1,1);
3953  if (!(pgt->is_linear())) {
3954  base_matrix XX[2], H(2,4), B(2,2), X(2,2);
3955  XX[0] = XX[1] = base_matrix(2,2);
3956  gmm::copy(gmm::transposed(K), B); gmm::lu_inverse(B);
3957  gmm::mult(G, pgp->hessian(6*k), H);
3958  for (unsigned j = 0; j < 2; ++j) {
3959  XX[j](0,0) = B(0, j)*H(0, 0) + B(1, j)*H(1, 0);
3960  XX[j](0,1) = XX[j](1,0) = B(0, j)*H(0, 1) + B(1, j)*H(1, 1);
3961  XX[j](1,1) = B(0, j)*H(0, 3) + B(1, j)*H(1, 3);
3962  }
3963  for (unsigned j = 0; j < 2; ++j) {
3964  gmm::copy(gmm::scaled(XX[0], K(j,0)), X);
3965  gmm::add(gmm::scaled(XX[1], K(j,1)), X);
3966  M(1+j+6*k, 3+6*k) = X(0,0); M(1+j+6*k, 4+6*k) = X(1, 0);
3967  M(1+j+6*k, 5+6*k) = X(1, 1);
3968  }
3969  }
3970  scalar_type a = K(0,0), b = K(0,1), c = K(1,0), d = K(1,1);
3971  M(3+6*k, 3+6*k) = a*a; M(3+6*k, 4+6*k) = a*b; M(3+6*k, 5+6*k) = b*b;
3972  M(4+6*k, 3+6*k) = 2.0*a*c; M(4+6*k, 4+6*k) = b*c + a*d; M(4+6*k, 5+6*k) = 2.0*b*d;
3973  M(5+6*k, 3+6*k) = c*c; M(5+6*k, 4+6*k) = c*d; M(5+6*k, 5+6*k) = d*d;
3974  }
3975 
3976  THREAD_SAFE_STATIC base_matrix W(3, 21);
3977  base_small_vector norient(M_PI, M_PI * M_PI);
3978  if (pgt->is_linear()) gmm::lu_inverse(K);
3979  for (unsigned i = 18; i < 21; ++i) {
3980  if (!(pgt->is_linear()))
3981  { gmm::mult(G, pgp->grad(i), K); gmm::lu_inverse(K); }
3982  bgeot::base_small_vector n(2), v(2);
3983  gmm::mult(gmm::transposed(K), cvr->normals()[i-18], n);
3984  n /= gmm::vect_norm2(n);
3985 
3986  scalar_type ps = gmm::vect_sp(n, norient);
3987  if (ps < 0) n *= scalar_type(-1);
3988  if (gmm::abs(ps) < 1E-8)
3989  GMM_WARNING2("Argyris : The normal orientation may be incorrect");
3990  gmm::mult(K, n, v);
3991  const bgeot::base_tensor &t = pfp->grad(i);
3992  for (unsigned j = 0; j < 21; ++j)
3993  W(i-18, j) = t(j, 0, 0) * v[0] + t(j, 0, 1) * v[1];
3994  }
3995  THREAD_SAFE_STATIC base_matrix A(3,3);
3996  THREAD_SAFE_STATIC bgeot::base_vector w(3);
3997  THREAD_SAFE_STATIC bgeot::base_vector coeff(3);
3998  THREAD_SAFE_STATIC gmm::sub_interval SUBI(18, 3);
3999  THREAD_SAFE_STATIC gmm::sub_interval SUBJ(0, 3);
4000  gmm::copy(gmm::sub_matrix(W, SUBJ, SUBI), A);
4001  gmm::lu_inverse(A);
4002  gmm::copy(gmm::transposed(A), gmm::sub_matrix(M, SUBI));
4003 
4004  for (unsigned j = 0; j < 18; ++j) {
4005  gmm::mult(W, gmm::mat_row(M, j), w);
4006  gmm::mult(A, gmm::scaled(w, -1.0), coeff);
4007  gmm::copy(coeff, gmm::sub_vector(gmm::mat_row(M, j), SUBI));
4008  }
4009  }
4010 
4011  argyris_triangle__::argyris_triangle__() {
4012  cvr = bgeot::simplex_of_reference(2);
4013  dim_ = cvr->structure()->dim();
4014  init_cvs_node();
4015  es_degree = 5;
4016  is_pol = true;
4017  is_lag = false;
4018  is_standard_fem = is_equiv = false;
4019  base_.resize(21);
4020 
4021  std::stringstream s
4022  ("1 - 10*x^3 - 10*y^3 + 15*x^4 - 30*x*x*y*y"
4023  "+ 15*y*y*y*y - 6*x^5 + 30*x*x*x*y*y + 30*x*x*y*y*y - 6*y^5;"
4024  "x - 6*x*x*x - 11*x*y*y + 8*x*x*x*x + 10*x*x*y*y"
4025  "+ 18*x*y*y*y - 3*x*x*x*x*x + x*x*x*y*y - 10*x*x*y*y*y - 8*x*y*y*y*y;"
4026  "y - 11*x*x*y - 6*y*y*y + 18*x*x*x*y + 10*x*x*y*y"
4027  "+ 8*y*y*y*y - 8*x*x*x*x*y - 10*x*x*x*y*y + x*x*y*y*y - 3*y*y*y*y*y;"
4028  "0.5*x*x - 1.5*x*x*x + 1.5*x*x*x*x - 1.5*x*x*y*y"
4029  "- 0.5*x*x*x*x*x + 1.5*x*x*x*y*y + x*x*y*y*y;"
4030  "x*y - 4*x*x*y - 4*x*y*y + 5*x*x*x*y + 10*x*x*y*y"
4031  "+ 5*x*y*y*y - 2*x*x*x*x*y - 6*x*x*x*y*y - 6*x*x*y*y*y - 2*x*y*y*y*y;"
4032  "0.5*y*y - 1.5*y*y*y - 1.5*x*x*y*y + 1.5*y*y*y*y + x*x*x*y*y"
4033  "+ 1.5*x*x*y*y*y - 0.5*y*y*y*y*y;"
4034  "10*x^3 - 15*x^4 + 15*x*x*y*y + 6*x^5 - 15*x*x*x*y*y - 15*x*x*y*y*y;"
4035  "-4*x*x*x + 7*x*x*x*x - 3.5*x*x*y*y - 3*x*x*x*x*x + 3.5*x*x*x*y*y"
4036  "+ 3.5*x*x*y*y*y;"
4037  "-5*x*x*y + 14*x*x*x*y + 18.5*x*x*y*y - 8*x*x*x*x*y"
4038  "- 18.5*x*x*x*y*y - 13.5*x*x*y*y*y;"
4039  "0.5*x*x*x - x*x*x*x + 0.25*x*x*y*y + 0.5*x*x*x*x*x"
4040  "- 0.25*x*x*x*y*y - 0.25*x*x*y*y*y;"
4041  "x*x*y - 3*x*x*x*y - 3.5*x*x*y*y + 2*x*x*x*x*y + 3.5*x*x*x*y*y"
4042  "+ 2.5*x*x*y*y*y;"
4043  "1.25*x*x*y*y - 0.75*x*x*x*y*y - 1.25*x*x*y*y*y;"
4044  "10*y*y*y + 15*x*x*y*y - 15*y^4 - 15*x*x*x*y*y - 15*x*x*y*y*y + 6*y^5;"
4045  "-5*x*y*y + 18.5*x*x*y*y + 14*x*y*y*y - 13.5*x*x*x*y*y"
4046  "- 18.5*x*x*y*y*y - 8*x*y*y*y*y;"
4047  "-4*y*y*y - 3.5*x*x*y*y + 7*y*y*y*y + 3.5*x*x*x*y*y"
4048  "+ 3.5*x*x*y*y*y - 3*y*y*y*y*y;"
4049  "1.25*x*x*y*y - 1.25*x*x*x*y*y - 0.75*x*x*y*y*y;"
4050  "x*y*y - 3.5*x*x*y*y - 3*x*y*y*y + 2.5*x*x*x*y*y + 3.5*x*x*y*y*y"
4051  "+ 2*x*y*y*y*y;"
4052  "0.5*y*y*y + 0.25*x*x*y*y - y*y*y*y - 0.25*x*x*x*y*y"
4053  "- 0.25*x*x*y*y*y + 0.5*y*y*y*y*y;"
4054  "sqrt(2) * (-8*x*x*y*y + 8*x*x*x*y*y + 8*x*x*y*y*y);"
4055  "-16*x*y*y + 32*x*x*y*y + 32*x*y*y*y - 16*x*x*x*y*y"
4056  "- 32*x*x*y*y*y - 16*x*y*y*y*y;"
4057  "-16*x*x*y + 32*x*x*x*y + 32*x*x*y*y - 16*x*x*x*x*y"
4058  "- 32*x*x*x*y*y - 16*x*x*y*y*y;");
4059 
4060  base_node pt(2);
4061  for (unsigned k = 0; k < 7; ++k) {
4062  for (unsigned i = 0; i < 3; ++i) {
4063  base_[k*3+i] = read_base_poly(2, s);
4064  if (k == 6) {
4065  pt[0] = pt[1] = 0.5; if (i) pt[i-1] = 0.0;
4066  add_node(normal_derivative_dof(2), pt);
4067  }
4068  else {
4069  pt[0] = pt[1] = 0.0; if (k/2) pt[k/2-1] = 1.0;
4070  if (k & 1)
4071  add_node(second_derivative_dof(2, dim_type((i) ? 1:0),
4072  dim_type((i == 2) ? 1:0)), pt);
4073  else {
4074  if (i) add_node(derivative_dof(2, dim_type(i-1)), pt);
4075  else add_node(lagrange_dof(2), pt);
4076  }
4077  }
4078  }
4079  }
4080  }
4081 
4082  static pfem triangle_Argyris_fem(fem_param_list &params,
4083  std::vector<dal::pstatic_stored_object> &dependencies) {
4084  GMM_ASSERT1(params.size() == 0, "Bad number of parameters");
4085  pfem p = std::make_shared<argyris_triangle__>();
4086  dependencies.push_back(p->ref_convex(0));
4087  dependencies.push_back(p->node_tab(0));
4088  return p;
4089  }
4090 
4091  /* ******************************************************************** */
4092  /* Morley element on the triangle and tetrahedron */
4093  /* ******************************************************************** */
4094 
4095  struct morley_element__ : public fem<base_poly> {
4096  virtual void mat_trans(base_matrix &M, const base_matrix &G,
4097  bgeot::pgeometric_trans pgt) const;
4098  morley_element__(dim_type);
4099  };
4100 
4101  void morley_element__::mat_trans(base_matrix &M,
4102  const base_matrix &G,
4103  bgeot::pgeometric_trans pgt) const {
4104 
4105  THREAD_SAFE_STATIC bgeot::pgeotrans_precomp pgp;
4106  THREAD_SAFE_STATIC pfem_precomp pfp;
4107  THREAD_SAFE_STATIC bgeot::pgeometric_trans pgt_stored = nullptr;
4108  dim_type n = dim();
4109  dim_type N = dim_type(G.nrows());
4110  size_type nddl = base_.size();
4111  GMM_ASSERT1(N == n, "Sorry, this version of morley "
4112  "element works only for indentical dimensions.")
4113 
4114  if (pgt != pgt_stored) {
4115  pgt_stored = pgt;
4116  pgp = bgeot::geotrans_precomp(pgt, node_tab(0), 0);
4117  pfp = fem_precomp(std::make_shared<morley_element__>(n), node_tab(0), 0);
4118  }
4119  gmm::copy(gmm::identity_matrix(), M);
4120 
4121  THREAD_SAFE_STATIC base_matrix W(n+1, nddl);
4122  dim_type nfd = (n == 2) ? 3 : 6;
4123 
4124  base_matrix K(n, n);
4125  base_small_vector norient(n);
4126  norient[0] = M_PI;
4127  for (dim_type i = 1; i < n; ++i)
4128  norient[i] = M_PI * norient[i-1];
4129  if (pgt->is_linear())
4130  { gmm::mult(G, pgp->grad(0), K); gmm::lu_inverse(K); }
4131  for (unsigned i = nfd; i < nddl; ++i) {
4132  if (!(pgt->is_linear()))
4133  { gmm::mult(G, pgp->grad(i), K); gmm::lu_inverse(K); }
4134  bgeot::base_small_vector nn(n), v(n);
4135  gmm::mult(gmm::transposed(K), cvr->normals()[i-nfd], nn);
4136  nn /= gmm::vect_norm2(nn);
4137 
4138  scalar_type ps = gmm::vect_sp(nn, norient);
4139  if (ps < 0) nn *= scalar_type(-1);
4140  if (gmm::abs(ps) < 1E-8)
4141  GMM_WARNING2("Morley : The normal orientation may be incorrect");
4142  gmm::mult(K, nn, v);
4143  const bgeot::base_tensor &t = pfp->grad(i);
4144  for (unsigned j = 0; j < nddl; ++j)
4145  if (n == 2)
4146  W(i-nfd, j) = t(j, 0, 0) * v[0] + t(j, 0, 1) * v[1];
4147  else
4148  W(i-nfd, j) = t(j, 0, 0) * v[0] + t(j, 0, 1) * v[1] + t(j, 0, 2)*v[2];
4149  }
4150 
4151  base_matrix A(n+1, n+1);
4152  base_vector w(n+1);
4153  base_vector coeff(n+1);
4154  gmm::sub_interval SUBI(nfd, n+1);
4155  gmm::sub_interval SUBJ(0, n+1);
4156  gmm::copy(gmm::sub_matrix(W, SUBJ, SUBI), A);
4157  gmm::lu_inverse(A);
4158  gmm::copy(gmm::transposed(A), gmm::sub_matrix(M, SUBI));
4159 
4160  for (unsigned j = 0; j < nfd; ++j) {
4161  gmm::mult(W, gmm::mat_row(M, j), w);
4162  gmm::mult(A, gmm::scaled(w, -1.0), coeff);
4163  gmm::copy(coeff, gmm::sub_vector(gmm::mat_row(M, j), SUBI));
4164  }
4165  }
4166 
4167  morley_element__::morley_element__(dim_type n) {
4168  cvr = bgeot::simplex_of_reference(n);
4169  dim_ = cvr->structure()->dim();
4170  init_cvs_node();
4171  es_degree = 2;
4172  is_pol = true;
4173  is_standard_fem = is_lag = is_equiv = false;
4174 
4175  if (n == 2) {
4176  base_.resize(6);
4177 
4178  std::stringstream s("1 - x - y + 2*x*y; (x + y + x^2 - 2*x*y - y^2)/2;"
4179  "(x + y - x^2 - 2*x*y + y^2)/2;"
4180  "((x+y)^2 - x - y)*sqrt(2)/2; x*(x-1); y*(y-1);");
4181 
4182  for (unsigned k = 0; k < 6; ++k)
4183  base_[k] = read_base_poly(2, s);
4184 
4185  add_node(lagrange_dof(2), base_node(0.0, 0.0));
4186  add_node(lagrange_dof(2), base_node(1.0, 0.0));
4187  add_node(lagrange_dof(2), base_node(0.0, 1.0));
4188  add_node(normal_derivative_dof(2), base_node(0.5, 0.5));
4189  add_node(normal_derivative_dof(2), base_node(0.0, 0.5));
4190  add_node(normal_derivative_dof(2), base_node(0.5, 0.0));
4191  } else {
4192  base_.resize(10);
4193 
4194  std::stringstream s
4195  ("5/3 - 16/9*x - 28/9*y - 28/9*z + 8/9*x^2 + 8/3*x*y + 8/3*x*z"
4196  " - 4/9*y^2 + 20/3*y*z - 4/9*z^2;"
4197  "5/3 - 28/9*x - 16/9*y - 28/9*z - 4/9*x^2 + 8/3*x*y + 20/3*x*z"
4198  " + 8/9*y^2 + 8/3*y*z - 4/9*z^2;"
4199  "5/3 - 28/9*x - 28/9*y - 16/9*z - 4/9*x^2 + 20/3*x*y + 8/3*x*z"
4200  " - 4/9*y^2 + 8/3*y*z + 8/9*z^2;"
4201  "-4/3 + 20/9*x + 20/9*y + 32/9*z + 8/9*x^2 - 4/3*x*y - 16/3*x*z"
4202  " + 8/9*y^2 - 16/3*y*z - 16/9*z^2;"
4203  "-4/3 + 20/9*x + 32/9*y + 20/9*z + 8/9*x^2 - 16/3*x*y - 4/3*x*z"
4204  " - 16/9*y^2 - 16/3*y*z + 8/9*z^2;"
4205  "-4/3 + 32/9*x + 20/9*y + 20/9*z - 16/9*x^2 - 16/3*x*y - 16/3*x*z"
4206  " + 8/9*y^2 - 4/3*y*z + 8/9*z^2;"
4207  "sqrt(3)*(3/8 - x - y - z + 1/2*x^2 + 3/2*x*y + 3/2*x*z + 1/2*y^2"
4208  " + 3/2*y*z + 1/2*z^2);"
4209  "-1/8 - 2/3*x + 1/3*y + 1/3*z + 11/6*x^2 - 1/2*x*y - 1/2*x*z"
4210  " - 1/6*y^2 - 1/2*y*z - 1/6*z^2;"
4211  "-1/8 + 1/3*x - 2/3*y + 1/3*z - 1/6*x^2 - 1/2*x*y - 1/2*x*z"
4212  " + 11/6*y^2 - 1/2*y*z - 1/6*z^2;"
4213  "-1/8 + 1/3*x + 1/3*y - 2/3*z - 1/6*x^2 - 1/2*x*y - 1/2*x*z"
4214  " - 1/6*y^2 - 1/2*y*z + 11/6*z^2;");
4215 
4216  for (unsigned k = 0; k < 10; ++k)
4217  base_[k] = read_base_poly(3, s);
4218 
4219  add_node(lagrange_dof(3), base_node(0.5, 0.0, 0.0));
4220  add_node(lagrange_dof(3), base_node(0.0, 0.5, 0.0));
4221  add_node(lagrange_dof(3), base_node(0.0, 0.0, 0.5));
4222  add_node(lagrange_dof(3), base_node(0.5, 0.5, 0.0));
4223  add_node(lagrange_dof(3), base_node(0.5, 0.0, 0.5));
4224  add_node(lagrange_dof(3), base_node(0.0, 0.5, 0.5));
4225  add_node(normal_derivative_dof(3), base_node(1./3., 1./3., 1./3.));
4226  add_node(normal_derivative_dof(3), base_node(0.0, 1./3., 1./3.));
4227  add_node(normal_derivative_dof(3), base_node(1./3., 0.0, 1./3.));
4228  add_node(normal_derivative_dof(3), base_node(1./3., 1./3., 0.0));
4229  }
4230  }
4231 
4232  static pfem element_Morley_fem(fem_param_list &params,
4233  std::vector<dal::pstatic_stored_object> &dependencies) {
4234  GMM_ASSERT1(params.size() == 1, "Bad number of parameters");
4235  int n = dim_type(::floor(params[0].num() + 0.01));
4236  GMM_ASSERT1(n > 0 && n < 4, "Bad parameters");
4237  pfem p = std::make_shared<morley_element__>(dim_type(n));
4238  dependencies.push_back(p->ref_convex(0));
4239  dependencies.push_back(p->node_tab(0));
4240  return p;
4241  }
4242 
4243  /* ******************************************************************** */
4244  /* DISCONTINUOUS PK */
4245  /* ******************************************************************** */
4246 
4247  struct PK_discont_ : public PK_fem_ {
4248  public :
4249 
4250  PK_discont_(dim_type nc, short_type k, scalar_type alpha=scalar_type(0))
4251  : PK_fem_(nc, k) {
4252 
4253  std::fill(dof_types_.begin(),
4254  dof_types_.end(), lagrange_nonconforming_dof(nc));
4255 
4256  if (alpha != scalar_type(0)) {
4257  base_node G =
4258  gmm::mean_value(cv_node.points().begin(), cv_node.points().end());
4259  for (size_type i=0; i < cv_node.nb_points(); ++i)
4260  cv_node.points()[i] = (1-alpha)*cv_node.points()[i] + alpha*G;
4261  for (size_type d = 0; d < nc; ++d) {
4262  base_poly S(1,2);
4263  S[0] = -alpha * G[d] / (1-alpha);
4264  S[1] = 1. / (1-alpha);
4265  for (size_type j=0; j < nb_base(0); ++j)
4266  base_[j] = bgeot::poly_substitute_var(base_[j],S,d);
4267  }
4268  }
4269  }
4270  };
4271 
4272  static pfem PK_discontinuous_fem(fem_param_list &params,
4273  std::vector<dal::pstatic_stored_object> &dependencies) {
4274  GMM_ASSERT1(params.size() == 2 || params.size() == 3,
4275  "Bad number of parameters : "
4276  << params.size() << " should be 2 or 3.");
4277  GMM_ASSERT1(params[0].type() == 0 && params[1].type() == 0 &&
4278  (params.size() != 3 || params[2].type() == 0),
4279  "Bad type of parameters");
4280  int n = int(::floor(params[0].num() + 0.01));
4281  int k = int(::floor(params[1].num() + 0.01));
4282  scalar_type alpha = 0.;
4283  if (params.size() == 3) alpha = params[2].num();
4284  GMM_ASSERT1(n > 0 && n < 100 && k >= 0 && k <= 150 && alpha >= 0 &&
4285  alpha < 1 && double(n) == params[0].num()
4286  && double(k) == params[1].num(), "Bad parameters");
4287  pfem p = std::make_shared<PK_discont_>(dim_type(n), short_type(k), alpha);
4288  dependencies.push_back(p->ref_convex(0));
4289  dependencies.push_back(p->node_tab(0));
4290  return p;
4291  }
4292 
4293  /* ******************************************************************** */
4294  /* Connectable interior PK */
4295  /* ******************************************************************** */
4296 
4297  struct PK_conn_int_ : public PK_fem_ {
4298  public :
4299 
4300  PK_conn_int_(dim_type nc, short_type k)
4301  : PK_fem_(nc, k) {
4302  scalar_type alpha = 0.1;
4303 
4304  std::fill(dof_types_.begin(), dof_types_.end(), lagrange_dof(nc));
4305  if (alpha != scalar_type(0)) {
4306  base_node G =
4307  gmm::mean_value(cv_node.points().begin(), cv_node.points().end());
4308  for (size_type i=0; i < cv_node.nb_points(); ++i)
4309  cv_node.points()[i] = (1-alpha)*cv_node.points()[i] + alpha*G;
4310  for (size_type d = 0; d < nc; ++d) {
4311  base_poly S(1,2);
4312  S[0] = -alpha * G[d] / (1-alpha);
4313  S[1] = 1. / (1-alpha);
4314  for (size_type j=0; j < nb_base(0); ++j)
4315  base_[j] = bgeot::poly_substitute_var(base_[j],S,d);
4316  }
4317  }
4318  }
4319  };
4320 
4321  static pfem conn_int_PK_fem(fem_param_list &params,
4322  std::vector<dal::pstatic_stored_object> &dependencies) {
4323  GMM_ASSERT1(params.size() == 2, "Bad number of parameters : "
4324  << params.size() << " should be 2.");
4325  GMM_ASSERT1(params[0].type() == 0 && params[1].type() == 0,
4326  "Bad type of parameters");
4327  int n = int(::floor(params[0].num() + 0.01));
4328  int k = int(::floor(params[1].num() + 0.01));
4329  GMM_ASSERT1(n > 0 && n < 100 && k >= 0 && k <= 150
4330  && double(n) == params[0].num()
4331  && double(k) == params[1].num(), "Bad parameters");
4332  pfem p = std::make_shared<PK_conn_int_>(dim_type(n), short_type(k));
4333  dependencies.push_back(p->ref_convex(0));
4334  dependencies.push_back(p->node_tab(0));
4335  return p;
4336  }
4337 
4338  /* ******************************************************************** */
4339  /* Interior PK */
4340  /* ******************************************************************** */
4341  /* Interior PK element for arbitrary shape */
4342  /* (equivalent to DISCONTINUOUS_PK(n,k,0.1) for simplicies */
4343 
4344 
4345  struct PK_int_ : public PK_fem_ {
4346  public :
4347 
4348  PK_int_(dim_type nc, short_type k, bgeot::pconvex_ref cvr_)
4349  : PK_fem_(nc, k) {
4350  cvr = cvr_;
4351 
4352  scalar_type alpha = 0.1;
4353  std::fill(dof_types_.begin(),
4354  dof_types_.end(), lagrange_nonconforming_dof(nc));
4355 
4356  if (alpha != scalar_type(0)) {
4357  base_node G =
4358  gmm::mean_value(cv_node.points().begin(), cv_node.points().end());
4359  for (size_type i=0; i < cv_node.nb_points(); ++i)
4360  cv_node.points()[i] = (1-alpha)*cv_node.points()[i] + alpha*G;
4361  for (size_type d = 0; d < nc; ++d) {
4362  base_poly S(1,2);
4363  S[0] = -alpha * G[d] / (1-alpha);
4364  S[1] = 1. / (1-alpha);
4365  for (size_type j=0; j < nb_base(0); ++j)
4366  base_[j] = bgeot::poly_substitute_var(base_[j],S,d);
4367  }
4368  }
4369  }
4370  };
4371 
4372  static pfem simplex_IPK_fem(fem_param_list &params,
4373  std::vector<dal::pstatic_stored_object> &dependencies) {
4374  GMM_ASSERT1(params.size() == 2, "Bad number of parameters : "
4375  << params.size() << " should be 2.");
4376  GMM_ASSERT1(params[0].type() == 0 && params[1].type() == 0,
4377  "Bad type of parameters");
4378  int n = int(::floor(params[0].num() + 0.01));
4379  int k = int(::floor(params[1].num() + 0.01));
4380  GMM_ASSERT1(n > 0 && n < 100 && k >= 0 && k <= 150
4381  && double(n) == params[0].num()
4382  && double(k) == params[1].num(), "Bad parameters");
4383  pfem p = std::make_shared<PK_int_>(dim_type(n), short_type(k),
4384  bgeot::simplex_of_reference(dim_type(n)));
4385  dependencies.push_back(p->ref_convex(0));
4386  dependencies.push_back(p->node_tab(0));
4387  return p;
4388  }
4389 
4390  static pfem parallelepiped_IPK_fem(fem_param_list &params,
4391  std::vector<dal::pstatic_stored_object> &dependencies) {
4392  GMM_ASSERT1(params.size() == 2, "Bad number of parameters : "
4393  << params.size() << " should be 2.");
4394  GMM_ASSERT1(params[0].type() == 0 && params[1].type() == 0,
4395  "Bad type of parameters");
4396  int n = int(::floor(params[0].num() + 0.01));
4397  int k = int(::floor(params[1].num() + 0.01));
4398  GMM_ASSERT1(n > 0 && n < 100 && k >= 0 && k <= 150
4399  && double(n) == params[0].num()
4400  && double(k) == params[1].num(), "Bad parameters");
4401  pfem p = std::make_shared<PK_int_>(dim_type(n), short_type(k),
4402  bgeot::parallelepiped_of_reference(dim_type(n)));
4403  dependencies.push_back(p->ref_convex(0));
4404  dependencies.push_back(p->node_tab(0));
4405  return p;
4406  }
4407 
4408  static pfem prism_IPK_fem(fem_param_list &params,
4409  std::vector<dal::pstatic_stored_object> &dependencies) {
4410  GMM_ASSERT1(params.size() == 2, "Bad number of parameters : "
4411  << params.size() << " should be 2.");
4412  GMM_ASSERT1(params[0].type() == 0 && params[1].type() == 0,
4413  "Bad type of parameters");
4414  int n = int(::floor(params[0].num() + 0.01));
4415  int k = int(::floor(params[1].num() + 0.01));
4416  GMM_ASSERT1(n > 0 && n < 100 && k >= 0 && k <= 150
4417  && double(n) == params[0].num()
4418  && double(k) == params[1].num(), "Bad parameters");
4419  pfem p = std::make_shared<PK_int_>(dim_type(n), short_type(k),
4420  bgeot::prism_of_reference(dim_type(n)));
4421  dependencies.push_back(p->ref_convex(0));
4422  dependencies.push_back(p->node_tab(0));
4423  return p;
4424  }
4425 
4426 
4427  /* ******************************************************************** */
4428  /* PK element with a bubble base function */
4429  /* ******************************************************************** */
4430 
4431  struct PK_with_cubic_bubble_ : public PK_fem_ {
4432  PK_with_cubic_bubble_(dim_type nc, short_type k);
4433  };
4434 
4435  PK_with_cubic_bubble_::PK_with_cubic_bubble_(dim_type nc, short_type k)
4436  : PK_fem_(nc, k) {
4437  unfreeze_cvs_node();
4438  is_lag = false; es_degree = short_type(nc+1);
4439  base_node pt(nc);
4440  size_type j;
4441  PK_fem_ P1(nc, 1);
4442 
4443  pt.fill(1./(nc+1)); /* barycenter of the convex */
4444 
4445  add_node(bubble1_dof(nc), pt);
4446  base_.resize(nb_dof(0));
4447 
4448  j = nb_dof(0) - 1;
4449  base_[j] = base_poly(nc, 0);
4450  base_[j].one();
4451  for (size_type i = 0; i < P1.nb_dof(0); i++) base_[j] *= P1.base()[i];
4452  }
4453 
4454  static pfem PK_with_cubic_bubble(fem_param_list &params,
4455  std::vector<dal::pstatic_stored_object> &dependencies) {
4456  GMM_ASSERT1(params.size() == 2, "Bad number of parameters : "
4457  << params.size() << " should be 2.");
4458  GMM_ASSERT1(params[0].type() == 0 && params[1].type() == 0,
4459  "Bad type of parameters");
4460  int n = int(::floor(params[0].num() + 0.01));
4461  int k = int(::floor(params[1].num() + 0.01));
4462  GMM_ASSERT1(k < n+1, "dimensions mismatch");
4463  GMM_ASSERT1(n > 0 && n < 100 && k >= 0 && k <= 150 &&
4464  double(n) == params[0].num() && double(k) == params[1].num(),
4465  "Bad parameters");
4466  pfem p = std::make_shared<PK_with_cubic_bubble_>(dim_type(n),
4467  short_type(k));
4468  dependencies.push_back(p->ref_convex(0));
4469  dependencies.push_back(p->node_tab(0));
4470  return p;
4471  }
4472 
4473  /* ******************************************************************** */
4474  /* classical fem */
4475  /* ******************************************************************** */
4476 
4477  static pfem classical_fem_(bgeot::pgeometric_trans pgt,
4478  short_type k, bool complete=false,
4479  bool discont=false, scalar_type alpha=0) {
4480  THREAD_SAFE_STATIC bgeot::pgeometric_trans pgt_last = nullptr;
4481  THREAD_SAFE_STATIC short_type k_last = short_type(-1);
4482  THREAD_SAFE_STATIC pfem fem_last = nullptr;
4483  THREAD_SAFE_STATIC bool complete_last = 0;
4484  THREAD_SAFE_STATIC bool discont_last = 0;
4485  THREAD_SAFE_STATIC scalar_type alpha_last = 0;
4486 
4487  bool found = false;
4488  if (pgt_last == pgt && k_last == k && complete_last == complete &&
4489  discont_last == discont && alpha_last == alpha)
4490  return fem_last;
4491 
4492  dim_type n = pgt->structure()->dim();
4493  dim_type nbp = dim_type(pgt->basic_structure()->nb_points());
4494  std::stringstream name;
4495  std::string suffix(discont ? "_DISCONTINUOUS" : "");
4496  GMM_ASSERT2(discont || alpha == scalar_type(0),
4497  "Cannot use an alpha parameter in continuous elements.");
4498  std::stringstream arg_;
4499  if (discont && alpha != scalar_type(0))
4500  arg_ << "," << alpha;
4501  std::string arg(arg_.str());
4502 
4503  // Identifying if it is a torus structure
4504  if (bgeot::is_torus_geom_trans(pgt) && n == 3) n = 2;
4505 
4506  /* Identifying P1-simplexes. */
4507  if (nbp == n+1)
4508  if (pgt->basic_structure() == bgeot::simplex_structure(n)) {
4509  name << "FEM_PK" << suffix << "(" << n << "," << k << arg << ")";
4510  found = true;
4511  }
4512 
4513  /* Identifying Q1-parallelepiped. */
4514  if (!found && nbp == (size_type(1) << n))
4515  if (pgt->basic_structure() == bgeot::parallelepiped_structure(n)) {
4516  if (!complete && k == 2 && (n == 2 || n == 3) &&
4517  pgt->structure() == bgeot::Q2_incomplete_structure(n)) {
4518  GMM_ASSERT2(alpha == scalar_type(0),
4519  "Cannot use an alpha parameter in incomplete Q2"
4520  " elements.");
4521  name << "FEM_Q2_INCOMPLETE" << suffix << "(" << n << ")";
4522  } else
4523  name << "FEM_QK" << suffix << "(" << n << "," << k << arg << ")";
4524  found = true;
4525  }
4526 
4527  /* Identifying Q1-prisms. */
4528  if (!found && nbp == 2 * n)
4529  if (pgt->basic_structure() == bgeot::prism_P1_structure(n)) {
4530  if (!complete && k == 2 && n == 3 &&
4531  pgt->structure() == bgeot::prism_incomplete_P2_structure()) {
4532  GMM_ASSERT2(alpha == scalar_type(0),
4533  "Cannot use an alpha parameter in incomplete prism"
4534  " elements.");
4535  name << "FEM_PRISM_INCOMPLETE_P2" << suffix;
4536  } else
4537  name << "FEM_PRISM_PK" << suffix << "(" << n << "," << k << arg << ")";
4538  found = true;
4539  }
4540 
4541  /* Identifying pyramids. */
4542  if (!found && nbp == 5)
4543  if (pgt->basic_structure() == bgeot::pyramid_QK_structure(1)) {
4544  if (!complete && k == 2 &&
4545  pgt->structure() == bgeot::pyramid_Q2_incomplete_structure()) {
4546  GMM_ASSERT2(alpha == scalar_type(0),
4547  "Cannot use an alpha parameter in incomplete pyramid"
4548  " elements.");
4549  name << "FEM_PYRAMID_Q2_INCOMPLETE" << suffix;
4550  } else
4551  name << "FEM_PYRAMID_QK" << suffix << "(" << k << arg << ")";
4552  found = true;;
4553  }
4554 
4555  // To be completed
4556 
4557  GMM_ASSERT1(found, "This element is not taken into account. Contact us");
4558  fem_last = fem_descriptor(name.str());
4559  pgt_last = pgt;
4560  k_last = k;
4561  complete_last = complete;
4562  discont_last = discont;
4563  alpha_last = alpha;
4564  return fem_last;
4565  }
4566 
4568  bool complete) {
4569  return classical_fem_(pgt, k, complete);
4570  }
4571 
4573  scalar_type alpha, bool complete) {
4574  return classical_fem_(pgt, k, complete, true, alpha);
4575  }
4576 
4577  /* ******************************************************************** */
4578  /* Naming system */
4579  /* ******************************************************************** */
4580 
4581  pfem structured_composite_fem_method(fem_param_list &params,
4582  std::vector<dal::pstatic_stored_object> &dependencies);
4583  pfem PK_composite_hierarch_fem(fem_param_list &params,
4584  std::vector<dal::pstatic_stored_object> &dependencies);
4585  pfem PK_composite_full_hierarch_fem(fem_param_list &params,
4586  std::vector<dal::pstatic_stored_object> &dependencies);
4587  pfem HCT_triangle_fem(fem_param_list &params,
4588  std::vector<dal::pstatic_stored_object> &dependencies);
4589  pfem reduced_HCT_triangle_fem(fem_param_list &params,
4590  std::vector<dal::pstatic_stored_object> &dependencies);
4591  pfem reduced_quadc1p3_fem(fem_param_list &params,
4592  std::vector<dal::pstatic_stored_object> &dependencies);
4593  pfem quadc1p3_fem(fem_param_list &params,
4594  std::vector<dal::pstatic_stored_object> &dependencies);
4595  pfem P1bubbletriangle_fem(fem_param_list &params,
4596  std::vector<dal::pstatic_stored_object> &dependencies);
4597  pfem hho_method(fem_param_list &params,
4598  std::vector<dal::pstatic_stored_object> &dependencies);
4599 
4600  struct fem_naming_system : public dal::naming_system<virtual_fem> {
4601  fem_naming_system() : dal::naming_system<virtual_fem>("FEM") {
4602  add_suffix("HERMITE", Hermite_fem);
4603  add_suffix("ARGYRIS", triangle_Argyris_fem);
4604  add_suffix("MORLEY", element_Morley_fem);
4605  add_suffix("PK", PK_fem);
4606  add_suffix("QK", QK_fem);
4607  add_suffix("QK_DISCONTINUOUS", QK_discontinuous_fem);
4608  add_suffix("PRISM_PK", prism_PK_fem);
4609  add_suffix("PK_PRISM", prism_PK_fem); // for backwards compatibility
4610  add_suffix("PK_DISCONTINUOUS", PK_discontinuous_fem);
4611  add_suffix("PRISM_PK_DISCONTINUOUS", prism_PK_discontinuous_fem);
4612  add_suffix("PK_PRISM_DISCONTINUOUS", prism_PK_discontinuous_fem); // for backwards compatibility
4613  add_suffix("SIMPLEX_IPK", simplex_IPK_fem);
4614  add_suffix("PRISM_IPK", prism_IPK_fem);
4615  add_suffix("QUAD_IPK", parallelepiped_IPK_fem);
4616  add_suffix("SIMPLEX_CIPK", conn_int_PK_fem);
4617  add_suffix("PK_WITH_CUBIC_BUBBLE", PK_with_cubic_bubble);
4618  add_suffix("PRODUCT", product_fem);
4619  add_suffix("P1_NONCONFORMING", P1_nonconforming_fem);
4620  add_suffix("P1_BUBBLE_FACE", P1_with_bubble_on_a_face);
4621  add_suffix("P1_BUBBLE_FACE_LAG", P1_with_bubble_on_a_face_lagrange);
4622  add_suffix("P1_PIECEWISE_LINEAR_BUBBLE", P1bubbletriangle_fem);
4623  add_suffix("GEN_HIERARCHICAL", gen_hierarchical_fem);
4624  add_suffix("PK_HIERARCHICAL", PK_hierarch_fem);
4625  add_suffix("QK_HIERARCHICAL", QK_hierarch_fem);
4626  add_suffix("PRISM_PK_HIERARCHICAL", prism_PK_hierarch_fem);
4627  add_suffix("PK_PRISM_HIERARCHICAL", prism_PK_hierarch_fem); // for backwards compatibility
4628  add_suffix("STRUCTURED_COMPOSITE", structured_composite_fem_method);
4629  add_suffix("PK_HIERARCHICAL_COMPOSITE", PK_composite_hierarch_fem);
4630  add_suffix("PK_FULL_HIERARCHICAL_COMPOSITE",
4631  PK_composite_full_hierarch_fem);
4632  add_suffix("PK_GAUSSLOBATTO1D", PK_GL_fem);
4633  add_suffix("QUAD_CIPK", CIPK_SQUARE);
4634  add_suffix("Q2_INCOMPLETE", Q2_incomplete_fem);
4635  add_suffix("Q2_INCOMPLETE_DISCONTINUOUS", Q2_incomplete_discontinuous_fem);
4636  add_suffix("HCT_TRIANGLE", HCT_triangle_fem);
4637  add_suffix("REDUCED_HCT_TRIANGLE", reduced_HCT_triangle_fem);
4638  add_suffix("QUADC1_COMPOSITE", quadc1p3_fem);
4639  add_suffix("REDUCED_QUADC1_COMPOSITE", reduced_quadc1p3_fem);
4640  add_suffix("HHO", hho_method);
4641  add_suffix("RT0", P1_RT0);
4642  add_suffix("RTK", RTk);
4643  add_suffix("BDMK", BDMk);
4644  add_suffix("RT0Q", P1_RT0Q);
4645  add_suffix("NEDELEC", P1_nedelec);
4646  add_suffix("PYRAMID_QK", pyramid_QK_fem);
4647  add_suffix("PYRAMID_QK_DISCONTINUOUS", pyramid_QK_disc_fem);
4648  add_suffix("PYRAMID_LAGRANGE", pyramid_QK_fem); // for backwards compatibility
4649  add_suffix("PYRAMID_DISCONTINUOUS_LAGRANGE", pyramid_QK_disc_fem); // for backwards compatibility
4650  add_suffix("PYRAMID_Q2_INCOMPLETE", pyramid_Q2_incomplete_fem);
4651  add_suffix("PYRAMID_Q2_INCOMPLETE_DISCONTINUOUS",
4652  pyramid_Q2_incomplete_disc_fem);
4653  add_suffix("PRISM_INCOMPLETE_P2", prism_incomplete_P2_fem);
4654  add_suffix("PRISM_INCOMPLETE_P2_DISCONTINUOUS",
4655  prism_incomplete_P2_disc_fem);
4656  }
4657  };
4658 
4659  // get a fem descriptor from a string name of a fem.
4660  pfem fem_descriptor(const std::string &name) {
4661  size_type i = 0;
4662  pfem pf = dal::singleton<fem_naming_system>::instance().method(name, i);
4663  const_cast<virtual_fem &>(*pf).debug_name()
4664  = dal::singleton<fem_naming_system>::instance().shorter_name_of_method(pf);
4665  return pf;
4666  }
4667 
4668  // get the string name of a fem descriptor.
4669  std::string name_of_fem(pfem p) {
4670 
4672  auto *p_torus = dynamic_cast<const torus_fem *>(p.get());
4673  if (p_torus) return instance.shorter_name_of_method(p_torus->get_original_pfem());
4674  return instance.shorter_name_of_method(p);
4675 
4677  shorter_name_of_method(p);
4678  }
4679 
4680  // allows the add of a fem.
4681  void add_fem_name(std::string name,
4683  dal::singleton<fem_naming_system>::instance().add_suffix(name, f);
4684  }
4685 
4686  /* ******************************************************************** */
4687  /* Aliases functions */
4688  /* ******************************************************************** */
4689 
4690  pfem PK_fem(size_type n, short_type k) {
4691  THREAD_SAFE_STATIC pfem pf = nullptr;
4692  THREAD_SAFE_STATIC size_type d = size_type(-2);
4693  THREAD_SAFE_STATIC short_type r = short_type(-2);
4694  if (d != n || r != k) {
4695  std::stringstream name;
4696  name << "FEM_PK(" << n << "," << k << ")";
4697  pf = fem_descriptor(name.str());
4698  d = n; r = k;
4699  }
4700  return pf;
4701  }
4702 
4703  pfem QK_fem(size_type n, short_type k) {
4704  THREAD_SAFE_STATIC pfem pf = nullptr;
4705  THREAD_SAFE_STATIC size_type d = size_type(-2);
4706  THREAD_SAFE_STATIC short_type r = short_type(-2);
4707  if (d != n || r != k) {
4708  std::stringstream name;
4709  name << "FEM_QK(" << n << "," << k << ")";
4710  pf = fem_descriptor(name.str());
4711  d = n; r = k;
4712  }
4713  return pf;
4714  }
4715 
4716  pfem prism_PK_fem(size_type n, short_type k) {
4717  THREAD_SAFE_STATIC pfem pf = nullptr;
4718  THREAD_SAFE_STATIC size_type d = size_type(-2);
4719  THREAD_SAFE_STATIC short_type r = short_type(-2);
4720  if (d != n || r != k) {
4721  std::stringstream name;
4722  name << "FEM_PRISM_PK(" << n << "," << k << ")";
4723  pf = fem_descriptor(name.str());
4724  d = n; r = k;
4725  }
4726  return pf;
4727  }
4728 
4729 
4730  /* ********************************************************************* */
4731  /* Precomputation on fem. */
4732  /* ********************************************************************* */
4733 
4734  DAL_DOUBLE_KEY(pre_fem_key_, pfem, bgeot::pstored_point_tab);
4735 
4736  fem_precomp_::fem_precomp_(const pfem pff, const bgeot::pstored_point_tab ps) :
4737  pf(pff), pspt(ps) {
4738  DAL_STORED_OBJECT_DEBUG_CREATED(this, "Fem_precomp");
4739  for (const auto &p : *pspt)
4740  GMM_ASSERT1(p.size() == pf->dim(), "dimensions mismatch");
4741  }
4742 
4743  void fem_precomp_::init_val() const {
4744  c.resize(pspt->size());
4745  for (size_type i = 0; i < pspt->size(); ++i)
4746  pf->base_value((*pspt)[i], c[i]);
4747  }
4748 
4749  void fem_precomp_::init_grad() const {
4750  pc.resize(pspt->size());
4751  for (size_type i = 0; i < pspt->size(); ++i)
4752  pf->grad_base_value((*pspt)[i], pc[i]);
4753  }
4754 
4755  void fem_precomp_::init_hess() const {
4756  hpc.resize(pspt->size());
4757  for (size_type i = 0; i < pspt->size(); ++i)
4758  pf->hess_base_value((*pspt)[i], hpc[i]);
4759  }
4760 
4761  pfem_precomp fem_precomp(pfem pf, bgeot::pstored_point_tab pspt,
4762  dal::pstatic_stored_object dep) {
4763  dal::pstatic_stored_object_key pk = std::make_shared<pre_fem_key_>(pf,pspt);
4764  dal::pstatic_stored_object o = dal::search_stored_object(pk);
4765  if (o) return std::dynamic_pointer_cast<const fem_precomp_>(o);
4766  pfem_precomp p = std::make_shared<fem_precomp_>(pf, pspt);
4767  dal::add_stored_object(pk, p, pspt, dal::AUTODELETE_STATIC_OBJECT);
4769  if (dep) dal::add_dependency(p, dep);
4770  return p;
4771  }
4772 
4773  void fem_precomp_pool::clear() {
4774  for (const pfem_precomp &p : precomps)
4775  dal::del_stored_object(p, true);
4776  precomps.clear();
4777  }
4778 
4779 
4780 } /* end of namespace getfem. */
Provides mesh of torus.
const base_matrix & K() const
See getfem kernel doc for these matrices.
const base_matrix & G() const
matrix whose columns are the vertices of the convex
size_type ii_
if pgp != 0, it is the same as pgp's one
const base_node & xref() const
coordinates of the current point, in the reference convex.
Vector of integer (16 bits type) which represent the powers of a monomial.
Definition: bgeot_poly.h:64
Associate a name to a method descriptor and store method descriptors.
static T & instance()
Instance from the current thread.
structure passed as the argument of fem interpolation functions.
Definition: getfem_fem.h:750
Torus fem, the real grad base value is modified to compute radial grad of F/R.
Definition: getfem_torus.h:52
Base class for finite element description.
Definition: getfem_fem.h:256
Naming system.
A simple singleton implementation.
a balanced tree stored in a dal::dynamic_array
Miscelleanous assembly routines for common terms. Use the low-level generic assembly....
Definition of the finite element methods.
Integration methods (exact and approximated) on convexes.
Tools for multithreaded, OpenMP and Boost based parallelization.
Provides mesh and mesh fem of torus.
Miscelleanous algorithms on containers.
void copy(const L1 &l1, L2 &l2)
*‍/
Definition: gmm_blas.h:978
number_traits< typename linalg_traits< V >::value_type >::magnitude_type vect_norm2(const V &v)
Euclidean norm of a vector.
Definition: gmm_blas.h:558
void fill(L &l, typename gmm::linalg_traits< L >::value_type x)
*‍/
Definition: gmm_blas.h:104
number_traits< typename linalg_traits< M >::value_type >::magnitude_type mat_euclidean_norm(const M &m)
Euclidean norm of a matrix.
Definition: gmm_blas.h:637
void resize(V &v, size_type n)
*‍/
Definition: gmm_blas.h:210
void clean(L &l, double threshold)
Clean a vector or matrix (replace near-zero entries with zeroes).
void mult(const L1 &l1, const L2 &l2, L3 &l3)
*‍/
Definition: gmm_blas.h:1664
strongest_value_type< V1, V2 >::value_type vect_sp(const V1 &v1, const V2 &v2)
*‍/
Definition: gmm_blas.h:264
void add(const L1 &l1, L2 &l2)
*‍/
Definition: gmm_blas.h:1277
void lu_inverse(const DenseMatrixLU &LU, const Pvector &pvector, const DenseMatrix &AInv_)
Given an LU factored matrix, build the inverse of the matrix.
Definition: gmm_dense_lu.h:212
pdof_description derivative_dof(dim_type d, dim_type r)
Description of a unique dof of derivative type.
Definition: getfem_fem.cc:488
int dof_description_compare(pdof_description a, pdof_description b)
Gives a total order on the dof description compatible with the identification.
Definition: getfem_fem.cc:607
pdof_description second_derivative_dof(dim_type d, dim_type num_der1, dim_type num_der2)
Description of a unique dof of second derivative type.
Definition: getfem_fem.cc:497
pdof_description mean_value_dof(dim_type d)
Description of a unique dof of mean value type.
Definition: getfem_fem.cc:535
bool dof_linkable(pdof_description)
Says if the dof is linkable.
Definition: getfem_fem.cc:616
bool dof_compatibility(pdof_description, pdof_description)
Says if the two dofs can be identified.
Definition: getfem_fem.cc:619
pdof_description xfem_dof(pdof_description p, size_type ind)
Description of a special dof for Xfem.
Definition: getfem_fem.cc:434
pdof_description lagrange_dof(dim_type d)
Description of a unique dof of lagrange type (value at the node).
Definition: getfem_fem.cc:391
size_type dof_xfem_index(pdof_description)
Returns the xfem_index of dof (0 for normal dof)
Definition: getfem_fem.cc:622
pdof_description global_dof(dim_type d)
Description of a global dof, i.e.
Definition: getfem_fem.cc:543
pdof_description normal_derivative_dof(dim_type d)
Description of a unique dof of normal derivative type (normal derivative at the node,...
Definition: getfem_fem.cc:508
dof_description * pdof_description
Type representing a pointer on a dof_description.
Definition: getfem_fem.h:160
pdof_description product_dof(pdof_description pnd1, pdof_description pnd2)
Product description of the descriptions *pnd1 and *pnd2.
Definition: getfem_fem.cc:553
void add_node(const pdof_description &d, const base_node &pt, const dal::bit_vector &faces)
internal function adding a node to an element for the creation of a finite element method.
Definition: getfem_fem.cc:649
virtual void real_hess_base_value(const fem_interpolation_context &c, base_tensor &t, bool withM=true) const
Give the hessian of all components of the base functions at the current point of the fem_interpolatio...
Definition: getfem_fem.cc:318
size_type convex_num() const
get the current convex number
Definition: getfem_fem.cc:53
std::shared_ptr< const getfem::virtual_fem > pfem
type of pointer on a fem description
Definition: getfem_fem.h:244
virtual void real_grad_base_value(const fem_interpolation_context &c, base_tensor &t, bool withM=true) const
Give the gradient of all components of the base functions at the current point of the fem_interpolati...
Definition: getfem_fem.cc:314
bool have_pfp() const
true if a fem_precomp_ has been supplied.
Definition: getfem_fem.h:760
const base_matrix & M() const
non tau-equivalent transformation matrix.
Definition: getfem_fem.cc:44
virtual size_type nb_base(size_type cv) const
Number of basis functions.
Definition: getfem_fem.h:299
const fem< bgeot::polynomial_composite > * ppolycompfem
Polynomial composite FEM.
Definition: getfem_fem.h:601
pfem fem_descriptor(const std::string &name)
get a fem descriptor from its string name.
Definition: getfem_fem.cc:4660
void hess_base_value(base_tensor &t, bool withM=true) const
fill the tensor with the hessian of the base functions (taken at point this->xref())
Definition: getfem_fem.cc:256
bool have_pf() const
true if the pfem is available.
Definition: getfem_fem.h:762
pfem classical_discontinuous_fem(bgeot::pgeometric_trans pg, short_type k, scalar_type alpha=0, bool complete=false)
Give a pointer on the structures describing the classical polynomial discontinuous fem of degree k on...
Definition: getfem_fem.cc:4572
void grad_base_value(base_tensor &t, bool withM=true) const
fill the tensor with the gradient of the base functions (taken at point this->xref())
Definition: getfem_fem.cc:203
pfem classical_fem(bgeot::pgeometric_trans pgt, short_type k, bool complete=false)
Give a pointer on the structures describing the classical polynomial fem of degree k on a given conve...
Definition: getfem_fem.cc:4567
void base_value(base_tensor &t, bool withM=true) const
fill the tensor with the values of the base functions (taken at point this->xref())
Definition: getfem_fem.cc:121
short_type face_num() const
get the current face number
Definition: getfem_fem.cc:62
const pfem pf() const
get the current FEM descriptor
Definition: getfem_fem.h:782
pfem_precomp fem_precomp(pfem pf, bgeot::pstored_point_tab pspt, dal::pstatic_stored_object dep)
Handles precomputations for FEM.
Definition: getfem_fem.cc:4761
bool is_on_face() const
On a face ?
Definition: getfem_fem.cc:68
pfem_precomp pfp() const
get the current fem_precomp_
Definition: getfem_fem.h:794
const fem< bgeot::base_poly > * ppolyfem
Classical polynomial FEM.
Definition: getfem_fem.h:599
virtual size_type nb_dof(size_type) const
Number of degrees of freedom.
Definition: getfem_fem.h:296
virtual void real_base_value(const fem_interpolation_context &c, base_tensor &t, bool withM=true) const
Give the value of all components of the base functions at the current point of the fem_interpolation_...
Definition: getfem_fem.cc:310
std::string name_of_fem(pfem p)
get the string name of a fem descriptor.
Definition: getfem_fem.cc:4669
Basic Geometric Tools.
pconvex_structure prism_incomplete_P2_structure()
Give a pointer on the 3D quadratic incomplete prism structure.
pconvex_ref convex_ref_product(pconvex_ref a, pconvex_ref b)
tensorial product of two convex ref.
pconvex_structure pyramid_Q2_incomplete_structure()
Give a pointer on the 3D quadratic incomplete pyramid structure.
gmm::uint16_type short_type
used as the common short type integer in the library
Definition: bgeot_config.h:73
pconvex_structure pyramid_QK_structure(dim_type k)
Give a pointer on the 3D pyramid structure for a degree k = 1 or 2.
base_poly read_base_poly(short_type n, std::istream &f)
read a base_poly on the stream ist.
Definition: bgeot_poly.cc:211
pconvex_ref pyramid_QK_of_reference(dim_type k)
pyramidal element of reference of degree k (k = 1 or 2 only)
polynomial< T > poly_substitute_var(const polynomial< T > &P, const polynomial< T > &S, size_type subs_dim)
polynomial variable substitution
Definition: bgeot_poly.h:587
pconvex_ref simplex_of_reference(dim_type nc, short_type K)
returns a simplex of reference of dimension nc and degree k
void structured_mesh_for_convex(pconvex_ref cvr, short_type k, pbasic_mesh &pm, pmesh_precomposite &pmp, bool force_simplexification)
This function returns a mesh in pm which contains a refinement of the convex cvr if force_simplexific...
pconvex_structure parallelepiped_structure(dim_type nc, dim_type k)
Give a pointer on the structures of a parallelepiped of dimension d.
pconvex_structure Q2_incomplete_structure(dim_type nc)
Give a pointer on the structures of a incomplete Q2 quadrilateral/hexahedral of dimension d = 2 or 3.
pconvex_structure prism_P1_structure(dim_type nc)
Give a pointer on the structures of a prism of dimension d.
pconvex_ref parallelepiped_of_reference(dim_type nc, dim_type k)
parallelepiped of reference of dimension nc (and degree 1)
pconvex_structure simplex_structure(dim_type nc)
Give a pointer on the structures of a simplex of dimension d.
size_t size_type
used as the common size type in the library
Definition: bgeot_poly.h:49
std::shared_ptr< const bgeot::geometric_trans > pgeometric_trans
pointer type for a geometric transformation
size_type alpha(short_type n, short_type d)
Return the value of which is the number of monomials of a polynomial of variables and degree .
Definition: bgeot_poly.cc:47
pconvex_ref prism_of_reference(dim_type nc)
prism of reference of dimension nc (and degree 1)
Dynamic Array Library.
void add_stored_object(pstatic_stored_object_key k, pstatic_stored_object o, permanence perm)
Add an object with two optional dependencies.
void add_dependency(pstatic_stored_object o1, pstatic_stored_object o2)
Add a dependency, object o1 will depend on object o2.
void del_stored_object(const pstatic_stored_object &o, bool ignore_unstored)
Delete an object and the object which depend on it.
pstatic_stored_object search_stored_object(pstatic_stored_object_key k)
Gives a pointer to an object from a key pointer.
bool exists_stored_object(pstatic_stored_object o)
Test if an object is stored.
GEneric Tool for Finite Element Methods.
pintegration_method int_method_descriptor(std::string name, bool throw_if_not_found=true)
Get an integration method from its name .