GetFEM++  5.3
getfem_linearized_plates.cc
1 /*===========================================================================
2 
3  Copyright (C) 2004-2017 Yves Renard, Jeremie Lasry, Mathieu Fabre
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 
24 
25 
26 namespace getfem {
27 
29  const mesh_im & mim,
30  const mesh_im & mim_red,
31  const std::string &U,
32  const std::string &Theta,
33  const std::string &param_E,
34  const std::string &param_nu,
35  const std::string &param_epsilon,
36  const std::string &param_kappa,
37  size_type variant,
38  size_type region) {
39 
40 
41  std::string test_U = "Test_" + sup_previous_and_dot_to_varname(U);
42  std::string test_Theta = "Test_" + sup_previous_and_dot_to_varname(Theta);
43  std::string proj_Theta = (variant == 2) ?
44  ("Elementary_transformation("+Theta+",_2D_rotated_RT0_projection__434)")
45  : Theta;
46  std::string proj_test_Theta = (variant == 2) ?
47  ("Elementary_transformation("+test_Theta
48  +",_2D_rotated_RT0_projection__434)") : test_Theta;
49 
50  std::string D = "(("+param_E+")*pow("+param_epsilon+
51  ",3))/(12*(1-sqr("+param_nu+")))";
52  std::string G = "(("+param_E+")*("+param_epsilon+"))*("+param_kappa+
53  ")/(2*(1+("+param_nu+")))";
54  std::string E_theta = "(Grad_" + Theta + "+(Grad_" + Theta + ")')/2";
55  std::string E_test_Theta="(Grad_"+test_Theta+"+(Grad_"+test_Theta+")')/2";
56 
57  std::string expr_left =
58  D+"*(( 1-("+param_nu+"))*("+E_theta+"):("+E_test_Theta+")+("+param_nu+
59  ")*Trace("+E_theta+")*Trace("+E_test_Theta+"))";
60 
61  std::string expr_right =
62  "("+G+")*(Grad_"+U+"-"+proj_Theta+").Grad_"+test_U+
63  "-("+G+")*(Grad_"+U+"-"+proj_Theta+")."+proj_test_Theta;
64 
65  switch(variant) {
66  case 0: // Without reduction
67  return add_linear_generic_assembly_brick
68  (md, mim, expr_left+"+"+expr_right, region, false, false,
69  "Reissner-Mindlin plate model brick");
70  case 1: // With reduced integration
71  add_linear_generic_assembly_brick
72  (md, mim, expr_left, region, false, false,
73  "Reissner-Mindlin plate model brick, rotation term");
74  return add_linear_generic_assembly_brick
75  (md, mim_red, expr_right, region, false, false,
76  "Reissner-Mindlin plate model brick, transverse shear term");
77  case 2: // Variant with projection on rotated RT0
78  add_2D_rotated_RT0_projection(md, "_2D_rotated_RT0_projection__434");
79  return add_linear_generic_assembly_brick
80  (md, mim, expr_left+"+"+expr_right, region, false, false,
81  "Reissner-Mindlin plate model brick");
82  break;
83  default: GMM_ASSERT1(false, "Invalid variant for Reissner-Mindlin brick.");
84  }
85  return size_type(-1);
86  }
87 
88 
89 
90 
91 
92 
93 
94 
95 
96 
97 
98  // For the moment, only projection onto rotated RT0 element in dimension 2
99 
100  class _2D_Rotated_RT0_projection_transformation
101  : public virtual_elementary_transformation {
102 
103  public:
104 
105  virtual void give_transformation(const mesh_fem &mf, size_type cv,
106  base_matrix &M) const{
107 
108  DEFINE_STATIC_THREAD_LOCAL(base_matrix, M_old);
109  DEFINE_STATIC_THREAD_LOCAL_INITIALIZED(pfem, pf_old, 0);
110 
111  // Obtaining the fem descriptors
112  pfem pf1 = mf.fem_of_element(cv);
113  size_type N = 2;
114  GMM_ASSERT1(pf1->dim() == 2, "This projection is only defined "
115  "for two-dimensional elements");
116  size_type qmult = N / pf1->target_dim();
117 
118  bool simplex = false;
119  if (pf1->ref_convex(cv) == bgeot::simplex_of_reference(dim_type(N))) {
120  simplex = true;
121  } else if (pf1->ref_convex(cv)
122  == bgeot::parallelepiped_of_reference(dim_type(N))) {
123  simplex = false;
124  } else {
125  GMM_ASSERT1(false, "Cannot adapt the method for such an element.");
126  }
127 
128  if (pf1 == pf_old && pf1->is_equivalent() && M.size() == M_old.size()) {
129  gmm::copy(M_old, M);
130  return;
131  }
132 
133  std::stringstream fem_desc;
134  fem_desc << "FEM_RT0" << (simplex ? "":"Q") << "(" << N << ")";
135  pfem pf2 = fem_descriptor(fem_desc.str());
136 
137  // Obtaining a convenient integration method
138  size_type degree = pf1->estimated_degree() + pf2->estimated_degree();
139  bgeot::pgeometric_trans pgt = mf.linked_mesh().trans_of_convex(cv);
140  papprox_integration pim
141  = classical_approx_im(pgt, dim_type(degree))->approx_method();
142 
143  // Computation of mass matrices
144  size_type ndof1 = pf1->nb_dof(cv) * qmult;
145  size_type ndof2 = pf2->nb_dof(0);
146  base_matrix M1(ndof1, ndof1), M2(ndof2, ndof2), B(ndof1, ndof2);
147  base_matrix aux0(ndof1, ndof1), aux1(ndof1, ndof2), aux2(ndof1, ndof2);
148  base_matrix aux3(ndof2, ndof2);
149 
150 
151  base_matrix G;
152  bgeot::vectors_to_base_matrix(G, mf.linked_mesh().points_of_convex(cv));
153  fem_interpolation_context ctx1(pgt, pf1, base_node(N), G, cv);
154  fem_interpolation_context ctx2(pgt, pf2, base_node(N), G, cv);
155 
156  base_tensor t1, t2;
157  base_matrix tv1, tv2;
158 
159  for (size_type i = 0; i < pim->nb_points_on_convex(); ++i) {
160 
161  scalar_type coeff = pim->coeff(i); // Mult by ctx.J() not useful here
162  ctx1.set_xref(pim->point(i));
163  ctx2.set_xref(pim->point(i));
164  pf1->real_base_value(ctx1, t1);
165  vectorize_base_tensor(t1, tv1, ndof1, pf1->target_dim(), N);
166  pf2->real_base_value(ctx2, t2);
167  vectorize_base_tensor(t2, tv2, ndof2, pf2->target_dim(), N);
168  for (size_type j = 0; j < ndof2; ++j) std::swap(tv2(j,0), tv2(j,1));
169 
170  gmm::mult(tv1, gmm::transposed(tv1), aux0);
171  gmm::add(gmm::scaled(aux0, coeff), M1);
172  gmm::mult(tv2, gmm::transposed(tv2), aux3);
173  gmm::add(gmm::scaled(aux3, coeff), M2);
174  gmm::mult(tv1, gmm::transposed(tv2), aux1);
175  gmm::add(gmm::scaled(aux1, coeff), B);
176  }
177 
178 
179  // Computation of M
180  gmm::lu_inverse(M1);
181  gmm::lu_inverse(M2);
182  gmm::mult(M1, B, aux1);
183  gmm::mult(aux1, M2, aux2);
184  GMM_ASSERT1(gmm::mat_nrows(M) == ndof1,
185  "Element not convenient for projection");
186  gmm::mult(aux2, gmm::transposed(B), M);
187  gmm::clean(M, 1E-15);
188  M_old = M; pf_old = pf1;
189  }
190  };
191 
192 
193 
194  void add_2D_rotated_RT0_projection(model &md, std::string name) {
195  pelementary_transformation
196  p = std::make_shared<_2D_Rotated_RT0_projection_transformation>();
197  md.add_elementary_transformation(name, p);
198  }
199 
200 
201 
202 
203 
204  // RT0 projection in any dimension. Unused for the moment.
205 
206 
207 // class RT0_projection_transformation
208 // : public virtual_elementary_transformation {
209 
210 // public:
211 
212 // virtual void give_transformation(const mesh_fem &mf, size_type cv,
213 // base_matrix &M) const{
214 
215 
216 
217 // // Obtaining the fem descriptors
218 // pfem pf1 = mf.fem_of_element(cv);
219 // size_type N = pf1->dim();
220 // size_type qmult = N / pf1->target_dim();
221 
222 // bool simplex = false;
223 // if (pf1->ref_convex(cv) == bgeot::simplex_of_reference(dim_type(N))) {
224 // simplex = true;
225 // } else if (pf1->ref_convex(cv)
226 // == bgeot::parallelepiped_of_reference(dim_type(N))) {
227 // simplex = false;
228 // } else {
229 // GMM_ASSERT1(false, "Cannot adapt the method for such an element.");
230 // }
231 
232 // GMM_ASSERT1(pf1->is_equivalent(), "For tau-equivalent fem only."); // Indeed no, for the moment ...
233 
234 // std::stringstream fem_desc;
235 // fem_desc << "FEM_RT0" << (simplex ? "":"Q") << "(" << N << ")";
236 // pfem pf2 = fem_descriptor(fem_desc.str());
237 
238 // // Obtaining a convenient integration method
239 // size_type degree = pf1->estimated_degree() + pf2->estimated_degree();
240 // bgeot::pgeometric_trans pgt = mf.linked_mesh().trans_of_convex(cv);
241 // papprox_integration pim
242 // = classical_approx_im(pgt, dim_type(degree))->approx_method();
243 
244 // // Computation of mass matrices
245 // size_type ndof1 = pf1->nb_dof(cv) * qmult;
246 // size_type ndof2 = pf2->nb_dof(0);
247 // base_matrix M1(ndof1, ndof1), M2(ndof2, ndof2), B(ndof1, ndof2);
248 // base_matrix aux0(ndof1, ndof1), aux1(ndof1, ndof2), aux2(ndof1, ndof2);
249 // base_matrix aux3(ndof2, ndof2);
250 
251 
252 // base_matrix G;
253 // bgeot::vectors_to_base_matrix(G, mf.linked_mesh().points_of_convex(cv));
254 // fem_interpolation_context ctx1(pgt, pf1, base_node(N), G, cv);
255 // fem_interpolation_context ctx2(pgt, pf2, base_node(N), G, cv);
256 
257 // base_tensor t1, t2;
258 // base_matrix tv1, tv2;
259 
260 // for (size_type i = 0; i < pim->nb_points_on_convex(); ++i) {
261 
262 // scalar_type coeff = pim->coeff(i); // Mult by ctx.J() not useful here
263 // ctx1.set_xref(pim->point(i));
264 // ctx2.set_xref(pim->point(i));
265 // pf1->real_base_value(ctx1, t1);
266 // vectorize_base_tensor(t1, tv1, ndof1, pf1->target_dim(), N);
267 // pf2->real_base_value(ctx2, t2);
268 // vectorize_base_tensor(t2, tv2, ndof2, pf2->target_dim(), N);
269 
270 
271 // // for (size_type j = 0; j < 4; ++j)
272 // // std::swap(tv2(j,0), tv2(j,1));
273 
274 
275 // gmm::mult(tv1, gmm::transposed(tv1), aux0);
276 // gmm::add(gmm::scaled(aux0, coeff), M1);
277 // gmm::mult(tv2, gmm::transposed(tv2), aux3);
278 // gmm::add(gmm::scaled(aux3, coeff), M2);
279 // gmm::mult(tv1, gmm::transposed(tv2), aux1);
280 // gmm::add(gmm::scaled(aux1, coeff), B);
281 // }
282 
283 
284 // // Computation of M
285 // gmm::lu_inverse(M1);
286 // gmm::lu_inverse(M2);
287 // gmm::mult(M1, B, aux1);
288 // gmm::mult(aux1, M2, aux2);
289 // GMM_ASSERT1(gmm::mat_nrows(M) == ndof1,
290 // "Element not convenient for projection");
291 // gmm::mult(aux2, gmm::transposed(B), M);
292 // gmm::clean(M, 1E-15);
293 // // cout << "M = " << M << endl;
294 // }
295 // };
296 
297 
298 
299 
300 
301 
302 
303 
304 } /* end of namespace getfem. */
305 
pfem fem_descriptor(const std::string &name)
get a fem descriptor from its string name.
Definition: getfem_fem.cc:3950
virtual pfem fem_of_element(size_type cv) const
Return the basic fem associated with an element (if no fem is associated, the function will crash! us...
Describe an integration method linked to a mesh.
``Model&#39;&#39; variables store the variables, the data and the description of a model. ...
size_t size_type
used as the common size type in the library
Definition: bgeot_poly.h:49
Reissner-Mindlin plate model brick.
structure passed as the argument of fem interpolation functions.
Definition: getfem_fem.h:741
GEneric Tool for Finite Element Methods.
std::shared_ptr< const getfem::virtual_fem > pfem
type of pointer on a fem description
Definition: getfem_fem.h:239
Describe a finite element method linked to a mesh.
size_type add_Mindlin_Reissner_plate_brick(model &md, const mesh_im &mim, const mesh_im &mim_reduced, const std::string &u3, const std::string &Theta, const std::string &param_E, const std::string &param_nu, const std::string &param_epsilon, const std::string &param_kappa, size_type variant=size_type(2), size_type region=size_type(-1))
Add a term corresponding to the classical Reissner-Mindlin plate model for which u3 is the transverse...
void add_2D_rotated_RT0_projection(model &md, std::string name)
Add the elementary transformation corresponding to the projection on rotated RT0 element for two-dime...
pconvex_ref parallelepiped_of_reference(dim_type nc, dim_type k)
parallelepiped of reference of dimension nc (and degree 1)
pintegration_method classical_approx_im(bgeot::pgeometric_trans pgt, dim_type degree)
try to find an approximate integration method for the geometric transformation pgt which is able to i...
void add_elementary_transformation(const std::string &name, pelementary_transformation ptrans)
Add an elementary transformation to the model to be used with the generic assembly.
void set_xref(const base_node &P)
change the current point (coordinates given in the reference convex)
const mesh & linked_mesh() const
Return a reference to the underlying mesh.
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