GetFEM++  5.3
getfem_fem_composite.cc
1 /*===========================================================================
2 
3  Copyright (C) 2002-2017 Yves Renard
4 
5  This file is a part of GetFEM++
6 
7  GetFEM++ is free software; you can redistribute it and/or modify it
8  under the terms of the GNU Lesser General Public License as published
9  by the Free Software Foundation; either version 3 of the License, or
10  (at your option) any later version along with the GCC Runtime Library
11  Exception either version 3.1 or (at your option) any later version.
12  This program is distributed in the hope that it will be useful, but
13  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15  License and GCC Runtime Library Exception for more details.
16  You should have received a copy of the GNU Lesser General Public License
17  along with this program; if not, write to the Free Software Foundation,
18  Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19 
20 ===========================================================================*/
21 
22 
25 #include "getfem/getfem_mesh_fem.h"
27 
28 namespace getfem {
29 
30  typedef const fem<bgeot::polynomial_composite> * ppolycompfem;
31 
32  static pfem composite_fe_method(const bgeot::mesh_precomposite &mp,
33  const mesh_fem &mf, bgeot::pconvex_ref cr) {
34 
35  GMM_ASSERT1(!mf.is_reduced(),
36  "Sorry, does not work for reduced mesh_fems");
37  auto p = std::make_shared<fem<bgeot::polynomial_composite>>();
38  p->mref_convex() = cr;
39  p->dim() = cr->structure()->dim();
40  p->is_polynomialcomp() = p->is_equivalent() = p->is_standard() = true;
41  p->is_polynomial() = false;
42  p->is_lagrange() = true;
43  p->estimated_degree() = 0;
44  p->init_cvs_node();
45 
46  std::vector<bgeot::polynomial_composite> base(mf.nb_basic_dof());
47  std::fill(base.begin(), base.end(), bgeot::polynomial_composite(mp));
48  std::vector<pdof_description> dofd(mf.nb_basic_dof());
49 
50  for (dal::bv_visitor cv(mf.convex_index()); !cv.finished(); ++cv) {
51  pfem pf1 = mf.fem_of_element(cv);
52  if (!pf1->is_lagrange()) p->is_lagrange() = false;
53  if (!(pf1->is_equivalent() && pf1->is_polynomial())) {
54  GMM_ASSERT1(false, "Only for polynomial and equivalent fem.");
55  }
56  ppolyfem pf = ppolyfem(pf1.get());
57  p->estimated_degree() = std::max(p->estimated_degree(),
58  pf->estimated_degree());
59  for (size_type k = 0; k < pf->nb_dof(cv); ++k) {
60  size_type igl = mf.ind_basic_dof_of_element(cv)[k];
61  base_poly fu = pf->base()[k];
62  base[igl].set_poly_of_subelt(cv, fu);
63  dofd[igl] = pf->dof_types()[k];
64  }
65  }
66  p->base().resize(mf.nb_basic_dof());
67  for (size_type k = 0; k < mf.nb_basic_dof(); ++k) {
68  p->add_node(dofd[k], mf.point_of_basic_dof(k));
69  p->base()[k] = base[k];
70  }
71  return p;
72  }
73 
74  typedef dal::naming_system<virtual_fem>::param_list fem_param_list;
75 
76  pfem structured_composite_fem_method(fem_param_list &params,
77  std::vector<dal::pstatic_stored_object> &dependencies) {
78  GMM_ASSERT1(params.size() == 2, "Bad number of parameters : "
79  << params.size() << " should be 2.");
80  GMM_ASSERT1(params[0].type() == 1 && params[1].type() == 0,
81  "Bad type of parameters");
82  pfem pf = params[0].method();
83  int k = int(::floor(params[1].num() + 0.01));
84  GMM_ASSERT1(((pf->is_polynomial()) || !(pf->is_equivalent())) && k > 0
85  && k <= 150 && double(k) == params[1].num(), "Bad parameters");
86  bgeot::pbasic_mesh pm;
87  bgeot::pmesh_precomposite pmp;
88 
89  structured_mesh_for_convex(pf->ref_convex(0), short_type(k), pm, pmp);
90 
91  mesh m(*pm);
92  mesh_fem mf(m);
93  mf.set_finite_element(pm->convex_index(), pf);
94  pfem p = composite_fe_method(*pmp, mf, pf->ref_convex(0));
95  dependencies.push_back(p->ref_convex(0));
96  dependencies.push_back(p->node_tab(0));
97  return p;
98  }
99 
100  pfem PK_composite_hierarch_fem(fem_param_list &params,
101  std::vector<dal::pstatic_stored_object> &) {
102  GMM_ASSERT1(params.size() == 3, "Bad number of parameters : "
103  << params.size() << " should be 3.");
104  GMM_ASSERT1(params[0].type() == 0 && params[1].type() == 0 &&
105  params[2].type() == 0, "Bad type of parameters");
106  int n = int(::floor(params[0].num() + 0.01));
107  int k = int(::floor(params[1].num() + 0.01));
108  int s = int(::floor(params[2].num() + 0.01)), t;
109  GMM_ASSERT1(n > 0 && n < 100 && k > 0 && k <= 150 && s > 0 && s <= 150 &&
110  (!(s & 1) || (s == 1)) && double(s) == params[2].num() &&
111  double(n) == params[0].num() && double(k) == params[1].num(),
112  "Bad parameters");
113  std::stringstream name;
114  if (s == 1)
115  name << "FEM_STRUCTURED_COMPOSITE(FEM_PK(" << n << "," << k << "),1)";
116  else {
117  for (t = 2; t <= s; ++t) if ((s % t) == 0) break;
118  name << "FEM_GEN_HIERARCHICAL(FEM_PK_HIERARCHICAL_COMPOSITE(" << n
119  << "," << k << "," << s/t << "), FEM_STRUCTURED_COMPOSITE(FEM_PK("
120  << n << "," << k << ")," << s << "))";
121  }
122  return fem_descriptor(name.str());
123  }
124 
125  pfem PK_composite_full_hierarch_fem(fem_param_list &params,
126  std::vector<dal::pstatic_stored_object> &) {
127  GMM_ASSERT1(params.size() == 3, "Bad number of parameters : "
128  << params.size() << " should be 3.");
129  GMM_ASSERT1(params[0].type() == 0 && params[1].type() == 0 &&
130  params[2].type() == 0, "Bad type of parameters");
131  int n = int(::floor(params[0].num() + 0.01));
132  int k = int(::floor(params[1].num() + 0.01));
133  int s = int(::floor(params[2].num() + 0.01)), t;
134  GMM_ASSERT1(n > 0 && n < 100 && k > 0 && k <= 150 && s > 0 && s <= 150 &&
135  (!(s & 1) || (s == 1)) && double(s) == params[2].num() &&
136  double(n) == params[0].num() && double(k) == params[1].num(),
137  "Bad parameters");
138  std::stringstream name;
139  if (s == 1)
140  name << "FEM_STRUCTURED_COMPOSITE(FEM_PK_HIERARCHICAL(" << n << ","
141  << k << "),1)";
142  else {
143  for (t = 2; t <= s; ++t) if ((s % t) == 0) break;
144  name << "FEM_GEN_HIERARCHICAL(FEM_PK_FULL_HIERARCHICAL_COMPOSITE(" << n
145  << "," << k << "," << s/t
146  << "), FEM_STRUCTURED_COMPOSITE(FEM_PK_HIERARCHICAL("
147  << n << "," << k << ")," << s << "))";
148  }
149  return fem_descriptor(name.str());
150  }
151 
152 
153  /* ******************************************************************** */
154  /* P1 with piecewise linear bubble function on a triangle. */
155  /* ******************************************************************** */
156 
157  struct P1bubbletriangle__ : public fem<bgeot::polynomial_composite> {
158  mesh m;
159  bgeot::mesh_precomposite mp;
160  P1bubbletriangle__(void);
161  };
162 
163  P1bubbletriangle__::P1bubbletriangle__(void) {
164 
165  m.clear();
166  size_type i0 = m.add_point(base_node(1.0/3.0, 1.0/3.0));
167  size_type i1 = m.add_point(base_node(0.0, 0.0));
168  size_type i2 = m.add_point(base_node(1.0, 0.0));
169  size_type i3 = m.add_point(base_node(0.0, 1.0));
170  m.add_triangle(i0, i2, i3);
171  m.add_triangle(i0, i3, i1);
172  m.add_triangle(i0, i1, i2);
173  mp = bgeot::mesh_precomposite(m);
174 
175  std::stringstream s("1-x-y;1-x-y;1-x-y;x;x;x;y;y;y;3-3*x-3*y;3*x;3*y;");
176 
177  bgeot::pconvex_ref cr = bgeot::simplex_of_reference(2);
178  mref_convex() = cr;
179  dim() = cr->structure()->dim();
180  is_polynomialcomp() = true;
181  is_equivalent() = true;
182  is_polynomial() = false;
183  is_lagrange() = false;
184  is_standard() = true;
185  estimated_degree() = 3;
186  init_cvs_node();
187 
188  base()=std::vector<bgeot::polynomial_composite>
189  (4, bgeot::polynomial_composite(mp, false));
190  for (size_type k = 0; k < 4; ++k)
191  for (size_type ic = 0; ic < 3; ++ic)
192  base()[k].set_poly_of_subelt(ic, bgeot::read_base_poly(2, s));
193 
194  for (size_type i = 0; i < 3; ++i) {
195  base_node pt(0.0, 0.0);
196  if (i) pt[i-1] = 1.0;
197  add_node(lagrange_dof(2), pt);
198  }
199 
200  add_node(bubble1_dof(2), base_node(1.0/3.0, 1.0/3.0));
201  }
202 
203 
204  pfem P1bubbletriangle_fem
205  (fem_param_list &params,
206  std::vector<dal::pstatic_stored_object> &dependencies) {
207  GMM_ASSERT1(params.size() == 0, "Bad number of parameters : "
208  << params.size() << " should be 0.");
209  pfem p = std::make_shared<P1bubbletriangle__>();
210  dependencies.push_back(p->ref_convex(0));
211  dependencies.push_back(p->node_tab(0));
212  return p;
213  }
214 
215  /* ******************************************************************** */
216  /* Hsieh-Clough-Tocher C^1 element (composite P3) */
217  /* ******************************************************************** */
218 
219  struct HCT_triangle__ : public fem<bgeot::polynomial_composite> {
220  virtual void mat_trans(base_matrix &M, const base_matrix &G,
221  bgeot::pgeometric_trans pgt) const;
222  mesh m;
223  mutable bgeot::base_small_vector true_normals[3];
224  mutable bgeot::mesh_precomposite mp;
225  mutable bgeot::pgeotrans_precomp pgp;
226  mutable pfem_precomp pfp;
227  mutable bgeot::pgeometric_trans pgt_stored;
228  mutable base_matrix K;
229 
230  HCT_triangle__(void);
231  };
232 
233  void HCT_triangle__::mat_trans(base_matrix &M, const base_matrix &G,
234  bgeot::pgeometric_trans pgt) const {
235 
236  dim_type N = dim_type(G.nrows());
237 
238  GMM_ASSERT1(N == 2, "Sorry, this version of HCT "
239  "element works only on dimension two.");
240  if (pgt != pgt_stored) {
241  pgt_stored = pgt;
242  pgp = bgeot::geotrans_precomp(pgt, node_tab(0), 0);
243  pfp = fem_precomp(std::make_shared<HCT_triangle__>(), node_tab(0), 0);
244  }
245  gmm::copy(gmm::identity_matrix(), M);
246 
247  gmm::mult(G, pgp->grad(0), K);
248  for (size_type i = 0; i < 3; ++i) {
249  if (i && !(pgt->is_linear())) gmm::mult(G, pgp->grad(3*i), K);
250  gmm::copy(K, gmm::sub_matrix(M, gmm::sub_interval(1+3*i, 2)));
251  }
252 
253  // take the normal derivatives into account
254  static base_matrix W(3, 12);
255  base_small_vector norient(M_PI, M_PI * M_PI);
256  if (pgt->is_linear()) gmm::lu_inverse(K);
257  for (unsigned i = 9; i < 12; ++i) {
258  if (!(pgt->is_linear()))
259  { gmm::mult(G, pgp->grad(i), K); gmm::lu_inverse(K); }
260  bgeot::base_small_vector n(2), v(2);
261  gmm::mult(gmm::transposed(K), cvr->normals()[i-9], n);
262  n /= gmm::vect_norm2(n);
263 
264  scalar_type ps = gmm::vect_sp(n, norient);
265  if (ps < 0) n *= scalar_type(-1);
266  true_normals[i-9] = n;
267 
268  if (gmm::abs(ps) < 1E-8)
269  GMM_WARNING2("HCT_triangle : "
270  "The normal orientation may be not correct");
271  gmm::mult(K, n, v);
272  const bgeot::base_tensor &t = pfp->grad(i);
273  // cout << "t = " << t << endl;
274  for (unsigned j = 0; j < 12; ++j)
275  W(i-9, j) = t(j, 0, 0) * v[0] + t(j, 0, 1) * v[1];
276  }
277 
278  static base_matrix A(3, 3);
279  static bgeot::base_vector w(3), coeff(3);
280  static gmm::sub_interval SUBI(9, 3), SUBJ(0, 3);
281  gmm::copy(gmm::sub_matrix(W, SUBJ, SUBI), A);
282  gmm::lu_inverse(A);
283  gmm::copy(gmm::transposed(A), gmm::sub_matrix(M, SUBI));
284 
285  for (unsigned j = 0; j < 9; ++j) {
286  gmm::mult(W, gmm::mat_row(M, j), w);
287  gmm::mult(A, gmm::scaled(w, -1.0), coeff);
288  gmm::copy(coeff, gmm::sub_vector(gmm::mat_row(M, j), SUBI));
289  }
290  }
291 
292  HCT_triangle__::HCT_triangle__(void) : pgt_stored(0), K(2, 2) {
293 
294  m.clear();
295  size_type i0 = m.add_point(base_node(1.0/3.0, 1.0/3.0));
296  size_type i1 = m.add_point(base_node(0.0, 0.0));
297  size_type i2 = m.add_point(base_node(1.0, 0.0));
298  size_type i3 = m.add_point(base_node(0.0, 1.0));
299  m.add_triangle(i0, i2, i3);
300  m.add_triangle(i0, i3, i1);
301  m.add_triangle(i0, i1, i2);
302  mp = bgeot::mesh_precomposite(m);
303 
304 
305  std::stringstream s
306  ("-1 + 9*x + 9*y - 15*x^2 - 30*x*y - 15*y^2 + 7*x^3 + 21*x^2*y + 21*x*y^2 + 7*y^3;"
307  "1 - 3*x^2 - 3*y^2 + 3*x^3 - 3*x^2*y + 2*y^3;"
308  "1 - 3*x^2 - 3*y^2 + 2*x^3 - 3*x*y^2 + 3*y^3;"
309  "-1/6 + 5/2*x - 9/2*x^2 - 4*x*y + 1/2*y^2 + 13/6*x^3 + 4*x^2*y + 3/2*x*y^2 - 1/3*y^3;"
310  "x - 1/2*x^2 - 3*x*y - 7/6*x^3 + 2*x^2*y + 2*x*y^2;"
311  "x - 2*x^2 - 3/2*y^2 + x^3 - 1/2*x*y^2 + 7/3*y^3;"
312  "-1/6 + 5/2*y + 1/2*x^2 - 4*x*y - 9/2*y^2 - 1/3*x^3 + 3/2*x^2*y + 4*x*y^2 + 13/6*y^3;"
313  "y - 3/2*x^2 - 2*y^2 + 7/3*x^3 - 1/2*x^2*y + y^3;"
314  "y - 3*x*y - 1/2*y^2 + 2*x^2*y + 2*x*y^2 - 7/6*y^3;"
315  "1 - 9/2*x - 9/2*y + 9*x^2 + 15*x*y + 6*y^2 - 9/2*x^3 - 21/2*x^2*y - 21/2*x*y^2 - 5/2*y^3;"
316  "3*x^2 - 5/2*x^3 + 3/2*x^2*y;"
317  "3*x^2 - 2*x^3 + 3/2*x*y^2 - 1/2*y^3;"
318  "-1/6 + 3/4*x + 3/4*y - 2*x^2 - 5/2*x*y - y^2 + 17/12*x^3 + 7/4*x^2*y + 7/4*x*y^2 + 5/12*y^3;"
319  "-x^2 + 13/12*x^3 - 1/4*x^2*y;"
320  "-x^2 + x^3 - 1/4*x*y^2 + 1/12*y^3;"
321  "2/3 - 13/4*x - 11/4*y + 9/2*x^2 + 19/2*x*y + 7/2*y^2 - 23/12*x^3 - 23/4*x^2*y - 25/4*x*y^2 - 17/12*y^3;"
322  "-1/2*x^2 + 5/12*x^3 + 9/4*x^2*y;"
323  "-x*y + 1/2*y^2 + 2*x^2*y + 7/4*x*y^2 - 13/12*y^3;"
324  "1 - 9/2*x - 9/2*y + 6*x^2 + 15*x*y + 9*y^2 - 5/2*x^3 - 21/2*x^2*y - 21/2*x*y^2 - 9/2*y^3;"
325  "3*y^2 - 1/2*x^3 + 3/2*x^2*y - 2*y^3;"
326  "3*y^2 + 3/2*x*y^2 - 5/2*y^3;"
327  "2/3 - 11/4*x - 13/4*y + 7/2*x^2 + 19/2*x*y + 9/2*y^2 - 17/12*x^3 - 25/4*x^2*y - 23/4*x*y^2 - 23/12*y^3;"
328  "1/2*x^2 - x*y - 13/12*x^3 + 7/4*x^2*y + 2*x*y^2;"
329  "-1/2*y^2 + 9/4*x*y^2 + 5/12*y^3;"
330  "-1/6 + 3/4*x + 3/4*y - x^2 - 5/2*x*y - 2*y^2 + 5/12*x^3 + 7/4*x^2*y + 7/4*x*y^2 + 17/12*y^3;"
331  "-y^2 + 1/12*x^3 - 1/4*x^2*y + y^3;"
332  "-y^2 - 1/4*x*y^2 + 13/12*y^3;"
333  "-sqrt(2)*2/3 + sqrt(2)*3*x + sqrt(2)*3*y - sqrt(2)*4*x^2 - sqrt(2)*10*x*y - sqrt(2)*4*y^2 + sqrt(2)*5/3*x^3 + sqrt(2)*7*x^2*y + sqrt(2)*7*x*y^2 + sqrt(2)*5/3*y^3;"
334  "sqrt(2)*1/3*x^3 - sqrt(2)*x^2*y;"
335  "-sqrt(2)*x*y^2 + sqrt(2)*1/3*y^3;"
336  "2/3 - 2*x - 4*y + 2*x^2 + 8*x*y + 6*y^2 - 2/3*x^3 - 4*x^2*y - 6*x*y^2 - 8/3*y^3;"
337  "2*x^2 - 4*x*y - 10/3*x^3 + 4*x^2*y + 4*x*y^2;"
338  "-2*y^2 + 2*x*y^2 + 8/3*y^3;"
339  "2/3 - 4*x - 2*y + 6*x^2 + 8*x*y + 2*y^2 - 8/3*x^3 - 6*x^2*y - 4*x*y^2 - 2/3*y^3;"
340  "-2*x^2 + 8/3*x^3 + 2*x^2*y;"
341  "-4*x*y + 2*y^2 + 4*x^2*y + 4*x*y^2 - 10/3*y^3;");
342 
343  bgeot::pconvex_ref cr = bgeot::simplex_of_reference(2);
344  mref_convex() = cr;
345  dim() = cr->structure()->dim();
346  is_polynomialcomp() = true;
347  is_equivalent() = false;
348  is_polynomial() = false;
349  is_lagrange() = false;
350  is_standard() = false;
351  estimated_degree() = 5;
352  init_cvs_node();
353 
354  base()=std::vector<bgeot::polynomial_composite>
355  (12, bgeot::polynomial_composite(mp, false));
356  for (size_type k = 0; k < 12; ++k)
357  for (size_type ic = 0; ic < 3; ++ic)
358  base()[k].set_poly_of_subelt(ic, bgeot::read_base_poly(2, s));
359 
360  for (size_type i = 0; i < 3; ++i) {
361  base_node pt(0.0, 0.0);
362  if (i) pt[i-1] = 1.0;
363  add_node(lagrange_dof(2), pt);
364  add_node(derivative_dof(2, 0), pt);
365  add_node(derivative_dof(2, 1), pt);
366  }
367 
368  add_node(normal_derivative_dof(2), base_node(0.5, 0.5));
369  add_node(normal_derivative_dof(2), base_node(0.0, 0.5));
370  add_node(normal_derivative_dof(2), base_node(0.5, 0.0));
371  }
372 
373  pfem HCT_triangle_fem
374  (fem_param_list &params,
375  std::vector<dal::pstatic_stored_object> &dependencies) {
376  GMM_ASSERT1(params.size() == 0, "Bad number of parameters : "
377  << params.size() << " should be 0.");
378  pfem p = std::make_shared<HCT_triangle__>();
379  dependencies.push_back(p->ref_convex(0));
380  dependencies.push_back(p->node_tab(0));
381  return p;
382  }
383 
384 
385  /* ******************************************************************** */
386  /* Reduced Hsieh-Clough-Tocher C^1 element (composite P3) */
387  /* ******************************************************************** */
388 
389  struct reduced_HCT_triangle__ : public fem<bgeot::polynomial_composite> {
390  const HCT_triangle__ *HCT;
391  virtual void mat_trans(base_matrix &M, const base_matrix &G,
392  bgeot::pgeometric_trans pgt) const;
393  virtual size_type nb_base(size_type) const { return 12; }
394  mutable base_matrix P, Mhct;
395  reduced_HCT_triangle__(void);
396  };
397 
398  void reduced_HCT_triangle__::mat_trans(base_matrix &M, const base_matrix &G,
399  bgeot::pgeometric_trans pgt) const {
400  HCT->mat_trans(Mhct, G, pgt);
401 
402  P(10, 1)=HCT->true_normals[1][0]*0.5; P(11, 1)=HCT->true_normals[2][0]*0.5;
403  P(10, 2)=HCT->true_normals[1][1]*0.5; P(11, 2)=HCT->true_normals[2][1]*0.5;
404 
405  P( 9, 4)=HCT->true_normals[0][0]*0.5; P(11, 4)=HCT->true_normals[2][0]*0.5;
406  P( 9, 5)=HCT->true_normals[0][1]*0.5; P(11, 5)=HCT->true_normals[2][1]*0.5;
407 
408  P( 9, 7)=HCT->true_normals[0][0]*0.5; P(10, 7)=HCT->true_normals[1][0]*0.5;
409  P( 9, 8)=HCT->true_normals[0][1]*0.5; P(10, 8)=HCT->true_normals[1][1]*0.5;
410 
411  gmm::mult(gmm::transposed(P), Mhct, M);
412  }
413 
414  reduced_HCT_triangle__::reduced_HCT_triangle__(void)
415  : P(12, 9), Mhct(12, 12) {
416  HCT = dynamic_cast<const HCT_triangle__ *>
417  (&(*fem_descriptor("FEM_HCT_TRIANGLE")));
418 
419  bgeot::pconvex_ref cr = bgeot::simplex_of_reference(2);
420  mref_convex() = cr;
421  dim() = cr->structure()->dim();
422  is_polynomialcomp() = true;
423  is_equivalent() = false;
424  is_polynomial() = false;
425  is_lagrange() = false;
426  is_standard() = false;
427  estimated_degree() = 5;
428  base() = HCT->base();
429 
430  gmm::copy(gmm::identity_matrix(), P);
431  init_cvs_node();
432 
433  for (size_type i = 0; i < 3; ++i) {
434  base_node pt(0.0, 0.0);
435  if (i) pt[i-1] = 1.0;
436  add_node(lagrange_dof(2), pt);
437  add_node(derivative_dof(2, 0), pt);
438  add_node(derivative_dof(2, 1), pt);
439  }
440  }
441 
442 
443  pfem reduced_HCT_triangle_fem
444  (fem_param_list &params,
445  std::vector<dal::pstatic_stored_object> &dependencies) {
446  GMM_ASSERT1(params.size() == 0, "Bad number of parameters : "
447  << params.size() << " should be 0.");
448  pfem p = std::make_shared<reduced_HCT_triangle__>();
449  dependencies.push_back(p->ref_convex(0));
450  dependencies.push_back(p->node_tab(0));
451  return p;
452  }
453 
454 
455  /* ******************************************************************** */
456  /* C1 composite element on quadrilateral (piecewise P3, FVS element). */
457  /* ******************************************************************** */
458 
459  struct quadc1p3__ : public fem<bgeot::polynomial_composite> {
460  virtual void mat_trans(base_matrix &M, const base_matrix &G,
461  bgeot::pgeometric_trans pgt) const;
462  mesh m;
463  mutable bgeot::mesh_precomposite mp;
464  mutable bgeot::pgeotrans_precomp pgp;
465  mutable pfem_precomp pfp;
466  mutable bgeot::pgeometric_trans pgt_stored;
467  mutable base_matrix K;
468  mutable bgeot::base_small_vector true_normals[4];
469  quadc1p3__(void);
470  };
471 
472  void quadc1p3__::mat_trans(base_matrix &M, const base_matrix &G,
473  bgeot::pgeometric_trans pgt) const {
474 
475  dim_type N = dim_type(G.nrows());
476 
477  GMM_ASSERT1(N == 2, "Sorry, this version of reduced HCT "
478  "element works only on dimension two.");
479  if (pgt != pgt_stored) {
480  pgt_stored = pgt;
481  pgp = bgeot::geotrans_precomp(pgt, node_tab(0), 0);
482  pfp = fem_precomp(std::make_shared<quadc1p3__>(), node_tab(0), 0);
483  }
484  gmm::copy(gmm::identity_matrix(), M);
485 
486  gmm::mult(G, pgp->grad(0), K);
487  for (size_type i = 0; i < 4; ++i) {
488  if (i && !(pgt->is_linear())) gmm::mult(G, pgp->grad(3*i), K);
489  gmm::copy(K, gmm::sub_matrix(M, gmm::sub_interval(1+3*i, 2)));
490  }
491 
492  // take the normal derivatives into account
493  static base_matrix W(4, 16);
494  base_small_vector norient(M_PI, M_PI * M_PI);
495  if (pgt->is_linear()) gmm::lu_inverse(K);
496  for (unsigned i = 12; i < 16; ++i) {
497  if (!(pgt->is_linear()))
498  { gmm::mult(G, pgp->grad(i), K); gmm::lu_inverse(K); }
499  bgeot::base_small_vector n(2), v(2);
500  gmm::mult(gmm::transposed(K), cvr->normals()[i-12], n);
501  n /= gmm::vect_norm2(n);
502 
503  scalar_type ps = gmm::vect_sp(n, norient);
504  if (ps < 0) n *= scalar_type(-1);
505  true_normals[i-12] = n;
506  if (gmm::abs(ps) < 1E-8)
507  GMM_WARNING2("FVS_quadrilateral : "
508  "The normal orientation may be not correct");
509  gmm::mult(K, n, v);
510  const bgeot::base_tensor &t = pfp->grad(i);
511  for (unsigned j = 0; j < 16; ++j)
512  W(i-12, j) = t(j, 0, 0) * v[0] + t(j, 0, 1) * v[1];
513  }
514 
515  static base_matrix A(4, 4);
516  static bgeot::base_vector w(4), coeff(4);
517  static gmm::sub_interval SUBI(12, 4), SUBJ(0, 4);
518  gmm::copy(gmm::sub_matrix(W, SUBJ, SUBI), A);
519  gmm::lu_inverse(A);
520  gmm::copy(gmm::transposed(A), gmm::sub_matrix(M, SUBI));
521 
522  for (unsigned j = 0; j < 12; ++j) {
523  gmm::mult(W, gmm::mat_row(M, j), w);
524  gmm::mult(A, gmm::scaled(w, -1.0), coeff);
525  gmm::copy(coeff, gmm::sub_vector(gmm::mat_row(M, j), SUBI));
526  }
527  }
528 
529  quadc1p3__::quadc1p3__(void) : pgt_stored(0), K(2, 2) {
530 
531  m.clear();
532  size_type i0 = m.add_point(base_node(0.0, 0.0));
533  size_type i1 = m.add_point(base_node(1.0, 0.0));
534  size_type i2 = m.add_point(base_node(0.0, 1.0));
535  size_type i3 = m.add_point(base_node(1.0, 1.0));
536  size_type i4 = m.add_point(base_node(0.5, 0.5));
537  m.add_triangle(i1, i3, i4);
538  m.add_triangle(i2, i0, i4);
539  m.add_triangle(i3, i2, i4);
540  m.add_triangle(i0, i1, i4);
541  mp = bgeot::mesh_precomposite(m);
542 
543  std::stringstream s
544  ("2 - 3*x - 3*y + 6*x*y + x^3 - 3*x^2*y;"
545  "1 - 3*x^2 - 3*y^2 + x^3 + 3*x^2*y + 2*y^3;"
546  "2 - 3*x - 3*y + 6*x*y - 3*x*y^2 + y^3;"
547  "1 - 3*x^2 - 3*y^2 + 2*x^3 + 3*x*y^2 + y^3;"
548  "1/6 + 1/2*x - y - 3/2*x^2 + 2*x*y + 5/6*x^3 - x^2*y;"
549  "x - 1/2*x^2 - 3*x*y + 1/6*x^3 + x^2*y + 2*x*y^2;"
550  "1/6 + 1/2*x - y - x*y + 3/2*y^2 + 1/2*x*y^2 - 2/3*y^3;"
551  "x - 2*x^2 - 3/2*y^2 + x^3 + 3/2*x*y^2 + 2/3*y^3;"
552  "1/6 - x + 1/2*y + 3/2*x^2 - x*y - 2/3*x^3 + 1/2*x^2*y;"
553  "y - 3/2*x^2 - 2*y^2 + 2/3*x^3 + 3/2*x^2*y + y^3;"
554  "1/6 - x + 1/2*y + 2*x*y - 3/2*y^2 - x*y^2 + 5/6*y^3;"
555  "y - 3*x*y - 1/2*y^2 + 2*x^2*y + x*y^2 + 1/6*y^3;"
556  "-1 + 3*x + 3*y - 6*x*y - 3*y^2 - x^3 + 3*x^2*y + 2*y^3;"
557  "3*x^2 - x^3 - 3*x^2*y;"
558  "-1 + 3*x + 3*y - 6*x*y - 3*y^2 + 3*x*y^2 + y^3;"
559  "3*x^2 - 2*x^3 - 3*x*y^2 + y^3;"
560  "-2/3 + 1/2*x + 2*y - x*y - 2*y^2 + 1/6*x^3 - x^2*y + 2*x*y^2;"
561  "-x^2 + 5/6*x^3 + x^2*y;"
562  "-2/3 + 1/2*x + 2*y - x*y - 2*y^2 + 1/2*x*y^2 + 2/3*y^3;"
563  "-x^2 + x^3 + 3/2*x*y^2 - 2/3*y^3;"
564  "-5/6 + x + 5/2*y + 1/2*x^2 - 3*x*y - 2*y^2 - 2/3*x^3 + 3/2*x^2*y + y^3;"
565  "-1/2*x^2 + 2/3*x^3 + 1/2*x^2*y;"
566  "-5/6 + x + 5/2*y - 2*x*y - 5/2*y^2 + x*y^2 + 5/6*y^3;"
567  "-x*y + 1/2*y^2 + 2*x^2*y - x*y^2 + 1/6*y^3;"
568  "-1 + 3*x + 3*y - 3*x^2 - 6*x*y + x^3 + 3*x^2*y;"
569  "3*y^2 + x^3 - 3*x^2*y - 2*y^3;"
570  "-1 + 3*x + 3*y - 3*x^2 - 6*x*y + 2*x^3 + 3*x*y^2 - y^3;"
571  "3*y^2 - 3*x*y^2 - y^3;"
572  "-5/6 + 5/2*x + y - 5/2*x^2 - 2*x*y + 5/6*x^3 + x^2*y;"
573  "1/2*x^2 - x*y + 1/6*x^3 - x^2*y + 2*x*y^2;"
574  "-5/6 + 5/2*x + y - 2*x^2 - 3*x*y + 1/2*y^2 + x^3 + 3/2*x*y^2 - 2/3*y^3;"
575  "-1/2*y^2 + 1/2*x*y^2 + 2/3*y^3;"
576  "-2/3 + 2*x + 1/2*y - 2*x^2 - x*y + 2/3*x^3 + 1/2*x^2*y;"
577  "-y^2 - 2/3*x^3 + 3/2*x^2*y + y^3;"
578  "-2/3 + 2*x + 1/2*y - 2*x^2 - x*y + 2*x^2*y - x*y^2 + 1/6*y^3;"
579  "-y^2 + x*y^2 + 5/6*y^3;"
580  "1 - 3*x - 3*y + 3*x^2 + 6*x*y + 3*y^2 - x^3 - 3*x^2*y - 2*y^3;"
581  "-x^3 + 3*x^2*y;"
582  "1 - 3*x - 3*y + 3*x^2 + 6*x*y + 3*y^2 - 2*x^3 - 3*x*y^2 - y^3;"
583  "3*x*y^2 - y^3;"
584  "-2/3 + 3/2*x + 2*y - x^2 - 3*x*y - 2*y^2 + 1/6*x^3 + x^2*y + 2*x*y^2;"
585  "5/6*x^3 - x^2*y;"
586  "-2/3 + 3/2*x + 2*y - x^2 - 3*x*y - 2*y^2 + x^3 + 3/2*x*y^2 + 2/3*y^3;"
587  "1/2*x*y^2 - 2/3*y^3;"
588  "-2/3 + 2*x + 3/2*y - 2*x^2 - 3*x*y - y^2 + 2/3*x^3 + 3/2*x^2*y + y^3;"
589  "-2/3*x^3 + 1/2*x^2*y;"
590  "-2/3 + 2*x + 3/2*y - 2*x^2 - 3*x*y - y^2 + 2*x^2*y + x*y^2 + 1/6*y^3;"
591  "-x*y^2 + 5/6*y^3;"
592  "4/3 - 2*x - 4*y + 4*x*y + 4*y^2 + 2/3*x^3 - 4*x*y^2;"
593  "-2/3*x^3;"
594  "4/3 - 2*x - 4*y + 4*x*y + 4*y^2 - 2*x*y^2 - 4/3*y^3;"
595  "-2*x*y^2 + 4/3*y^3;"
596  "-2/3 + 2*x - 2*x^2 + 2/3*x^3;"
597  "2*x^2 - 4*x*y - 2/3*x^3 + 4*x*y^2;"
598  "-2/3 + 2*x - 4*x*y + 2*y^2 + 2*x*y^2 - 4/3*y^3;"
599  "-2*y^2 + 2*x*y^2 + 4/3*y^3;"
600  "4/3 - 4*x - 2*y + 4*x^2 + 4*x*y - 4/3*x^3 - 2*x^2*y;"
601  "4/3*x^3 - 2*x^2*y;"
602  "4/3 - 4*x - 2*y + 4*x^2 + 4*x*y - 4*x^2*y + 2/3*y^3;"
603  "-2/3*y^3;"
604  "-2/3 + 2*y + 2*x^2 - 4*x*y - 4/3*x^3 + 2*x^2*y;"
605  "-2*x^2 + 4/3*x^3 + 2*x^2*y;"
606  "-2/3 + 2*y - 2*y^2 + 2/3*y^3;"
607  "-4*x*y + 2*y^2 + 4*x^2*y - 2/3*y^3;");
608 
609  bgeot::pconvex_ref cr = bgeot::parallelepiped_of_reference(2);
610  mref_convex() = cr;
611  dim() = cr->structure()->dim();
612  is_polynomialcomp() = true;
613  is_equivalent() = false;
614  is_polynomial() = false;
615  is_lagrange() = false;
616  is_standard() = false;
617  estimated_degree() = 5;
618  init_cvs_node();
619 
620  base()=std::vector<bgeot::polynomial_composite>
621  (16, bgeot::polynomial_composite(mp, false));
622  for (size_type k = 0; k < 16; ++k)
623  for (size_type ic = 0; ic < 4; ++ic)
624  base()[k].set_poly_of_subelt(ic, bgeot::read_base_poly(2, s));
625 
626  for (size_type i = 0; i < 4; ++i) {
627  base_node pt(0.0, 0.0);
628  if (i & 1) pt[0] = 1.0;
629  if (i & 2) pt[1] = 1.0;
630  add_node(lagrange_dof(2), pt);
631  add_node(derivative_dof(2, 0), pt);
632  add_node(derivative_dof(2, 1), pt);
633  }
634 
635  add_node(normal_derivative_dof(2), base_node(1.0, 0.5));
636  add_node(normal_derivative_dof(2), base_node(0.0, 0.5));
637  add_node(normal_derivative_dof(2), base_node(0.5, 1.0));
638  add_node(normal_derivative_dof(2), base_node(0.5, 0.0));
639  }
640 
641 
642  pfem quadc1p3_fem
643  (fem_param_list &params,
644  std::vector<dal::pstatic_stored_object> &dependencies) {
645  GMM_ASSERT1(params.size() == 0, "Bad number of parameters : "
646  << params.size() << " should be 0.");
647  pfem p = std::make_shared<quadc1p3__>();
648  dependencies.push_back(p->ref_convex(0));
649  dependencies.push_back(p->node_tab(0));
650  return p;
651  }
652 
653  /* ******************************************************************** */
654  /* Reduced C1 composite element on quadrilateral (piecewise P3). */
655  /* ******************************************************************** */
656 
657  struct reduced_quadc1p3__ : public fem<bgeot::polynomial_composite> {
658  const quadc1p3__ *HCT;
659  virtual void mat_trans(base_matrix &M, const base_matrix &G,
660  bgeot::pgeometric_trans pgt) const;
661  virtual size_type nb_base(size_type) const { return 16; }
662  mutable base_matrix P, Mhct;
663  reduced_quadc1p3__(void);
664  };
665 
666  void reduced_quadc1p3__::mat_trans(base_matrix &M, const base_matrix &G,
667  bgeot::pgeometric_trans pgt) const {
668  HCT->mat_trans(Mhct, G, pgt);
669 
670  P(13, 1)=HCT->true_normals[1][0]*0.5; P(15, 1)=HCT->true_normals[3][0]*0.5;
671  P(13, 2)=HCT->true_normals[1][1]*0.5; P(15, 2)=HCT->true_normals[3][1]*0.5;
672 
673  P(12, 4)=HCT->true_normals[0][0]*0.5; P(15, 4)=HCT->true_normals[3][0]*0.5;
674  P(12, 5)=HCT->true_normals[0][1]*0.5; P(15, 5)=HCT->true_normals[3][1]*0.5;
675 
676  P(13, 7)=HCT->true_normals[1][0]*0.5; P(14, 7)=HCT->true_normals[2][0]*0.5;
677  P(13, 8)=HCT->true_normals[1][1]*0.5; P(14, 8)=HCT->true_normals[2][1]*0.5;
678 
679  P(12,10)=HCT->true_normals[0][0]*0.5; P(14,10)=HCT->true_normals[2][0]*0.5;
680  P(12,11)=HCT->true_normals[0][1]*0.5; P(14,11)=HCT->true_normals[2][1]*0.5;
681 
682  gmm::mult(gmm::transposed(P), Mhct, M);
683  }
684 
685  reduced_quadc1p3__::reduced_quadc1p3__(void)
686  : P(16, 12), Mhct(16, 16) {
687  HCT = dynamic_cast<const quadc1p3__ *>
688  (&(*fem_descriptor("FEM_QUADC1_COMPOSITE")));
689 
690  bgeot::pconvex_ref cr = bgeot::parallelepiped_of_reference(2);
691  mref_convex() = cr;
692  dim() = cr->structure()->dim();
693  is_polynomialcomp() = true;
694  is_equivalent() = false;
695  is_polynomial() = false;
696  is_lagrange() = false;
697  is_standard() = false;
698  estimated_degree() = 5;
699  base() = HCT->base();
700 
701  gmm::copy(gmm::identity_matrix(), P);
702  init_cvs_node();
703 
704  for (size_type i = 0; i < 4; ++i) {
705  base_node pt(0.0, 0.0);
706  if (i & 1) pt[0] = 1.0;
707  if (i & 2) pt[1] = 1.0;
708  add_node(lagrange_dof(2), pt);
709  add_node(derivative_dof(2, 0), pt);
710  add_node(derivative_dof(2, 1), pt);
711  }
712  }
713 
714 
715  pfem reduced_quadc1p3_fem
716  (fem_param_list &params,
717  std::vector<dal::pstatic_stored_object> &dependencies) {
718  GMM_ASSERT1(params.size() == 0, "Bad number of parameters : "
719  << params.size() << " should be 0.");
720  pfem p = std::make_shared<reduced_quadc1p3__>();
721  dependencies.push_back(p->ref_convex(0));
722  dependencies.push_back(p->node_tab(0));
723  return p;
724  }
725 
726 
727 } /* end of namespace getfem. */
base_poly read_base_poly(short_type n, std::istream &f)
read a base_poly on the stream ist.
Definition: bgeot_poly.cc:210
Handle composite polynomials.
dim_type dim() const
dimension of the reference element.
Definition: getfem_fem.h:306
pfem fem_descriptor(const std::string &name)
get a fem descriptor from its string name.
Definition: getfem_fem.cc:3950
const std::vector< bgeot::polynomial_composite > & base() const
Gives the array of basic functions (components).
Definition: getfem_fem.h:543
Define the getfem::mesh_fem class.
Integration methods (exact and approximated) on convexes.
number_traits< typename linalg_traits< V >::value_type >::magnitude_type vect_norm2(const V &v)
Euclidean norm of a vector.
Definition: gmm_blas.h:557
size_t size_type
used as the common size type in the library
Definition: bgeot_poly.h:49
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...
pdof_description derivative_dof(dim_type d, dim_type r)
Description of a unique dof of derivative type.
Definition: getfem_fem.cc:466
Naming system.
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:627
const fem< bgeot::base_poly > * ppolyfem
Classical polynomial FEM.
Definition: getfem_fem.h:594
GEneric Tool for Finite Element Methods.
pdof_description lagrange_dof(dim_type d)
Description of a unique dof of lagrange type (value at the node).
Definition: getfem_fem.cc:385
std::shared_ptr< const getfem::virtual_fem > pfem
type of pointer on a fem description
Definition: getfem_fem.h:239
bool is_lagrange() const
true if the base functions are such that
Definition: getfem_fem.h:349
const fem< bgeot::polynomial_composite > * ppolycompfem
Polynomial composite FEM.
Definition: getfem_fem.h:596
gmm::uint16_type short_type
used as the common short type integer in the library
Definition: bgeot_config.h:79
pdof_description normal_derivative_dof(dim_type d)
Description of a unique dof of normal derivative type (normal derivative at the node, regarding a face).
Definition: getfem_fem.cc:486
pfem_precomp fem_precomp(pfem pf, bgeot::pstored_point_tab pspt, dal::pstatic_stored_object dep)
Handles precomputations for FEM.
Definition: getfem_fem.cc:4051
pconvex_ref parallelepiped_of_reference(dim_type nc, dim_type k)
parallelepiped of reference of dimension nc (and degree 1)
pconvex_ref simplex_of_reference(dim_type nc, short_type K)
returns a simplex of reference of dimension nc and degree k
std::shared_ptr< const bgeot::geometric_trans > pgeometric_trans
pointer type for a geometric transformation
bool is_polynomial() const
true if the base functions are polynomials
Definition: getfem_fem.h:351