GetFEM  5.5
getfem_fourth_order.cc
1 /*===========================================================================
2 
3  Copyright (C) 2009-2026 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, see https://www.gnu.org/licenses/.
18 
19 ===========================================================================*/
20 
21 
23 #include "getfem/getfem_omp.h"
24 
25 
26 namespace getfem {
27 
28  // ----------------------------------------------------------------------
29  // Bilaplacian brick
30  // ----------------------------------------------------------------------
31 
32  struct bilap_brick : public virtual_brick {
33 
34  virtual void asm_real_tangent_terms(const model &md, size_type ib,
35  const model::varnamelist &vl,
36  const model::varnamelist &dl,
37  const model::mimlist &mims,
38  model::real_matlist &matl,
39  model::real_veclist &,
40  model::real_veclist &,
41  size_type region,
42  build_version version) const {
43  GMM_ASSERT1(matl.size() == 1,
44  "Bilaplacian brick has one and only one term");
45  GMM_ASSERT1(mims.size() == 1,
46  "Bilaplacian brick need one and only one mesh_im");
47  GMM_ASSERT1(vl.size() == 1 && (dl.size() == 1 || dl.size() == 2),
48  "Wrong number of variables for bilaplacian brick");
49 
50  bool KL = (dl.size() == 2);
51 
52  bool recompute_matrix = !((version & model::BUILD_ON_DATA_CHANGE) != 0)
53  || md.is_var_newer_than_brick(dl[0], ib);
54 
55 
56  if (recompute_matrix) {
57 
58  const mesh_fem &mf_u = md.mesh_fem_of_variable(vl[0]);
59  const mesh &m = mf_u.linked_mesh();
60  size_type Q = mf_u.get_qdim();
61  GMM_ASSERT1(Q == 1, "Bilaplacian brick is only for a scalar field");
62  const mesh_im &mim = *mims[0];
63  mesh_region rg(region);
64  m.intersect_with_mpi_region(rg);
65  const mesh_fem *mf_data = md.pmesh_fem_of_variable(dl[0]);
66  const model_real_plain_vector *data = &(md.real_variable(dl[0]));
67  size_type sl = gmm::vect_size(*data);
68  if (mf_data) sl = sl * mf_data->get_qdim() / mf_data->nb_dof();
69 
70  GMM_ASSERT1(sl == 1, "Bad format of bilaplacian coefficient");
71 
72  const mesh_fem *mf_data2 = 0;
73  const model_real_plain_vector *data2 = 0;
74  if (KL) {
75  mf_data2 = md.pmesh_fem_of_variable(dl[1]);
76  data2 = &(md.real_variable(dl[1]));
77  size_type sl2 = gmm::vect_size(*data2);
78  if (mf_data2) sl = sl * mf_data2->get_qdim() / mf_data2->nb_dof();
79  GMM_ASSERT1(sl2 == 1, "Bad format of bilaplacian coefficient");
80  }
81 
82  if (KL) {
83  GMM_TRACE2("Stiffness matrix assembly of a bilaplacian term for a "
84  "Kirchhoff-Love plate");
85  }
86  else {
87  GMM_TRACE2("Stiffness matrix assembly of a bilaplacian term");
88  }
89 
90  gmm::clear(matl[0]);
91  if (mf_data) {
92  if (KL)
93  asm_stiffness_matrix_for_bilaplacian_KL
94  (matl[0], mim, mf_u, *mf_data, *data, *data2, rg);
95  else
97  (matl[0], mim, mf_u, *mf_data, *data, rg);
98  } else {
99  if (KL) {
100  asm_stiffness_matrix_for_homogeneous_bilaplacian_KL
101  (matl[0], mim, mf_u, *data, *data2, rg);
102  }
103  else
104  asm_stiffness_matrix_for_homogeneous_bilaplacian
105  (matl[0], mim, mf_u, *data, rg);
106  }
107  }
108  }
109 
110  bilap_brick(void) {
111  set_flags("Bilaplacian operator", true /* is linear*/,
112  true /* is symmetric */, true /* is coercive */,
113  true /* is real */, false /* is complex */);
114  }
115 
116  };
117 
119  (model &md, const mesh_im &mim, const std::string &varname,
120  const std::string &dataname,
121  size_type region) {
122  pbrick pbr = std::make_shared<bilap_brick>();
123  model::termlist tl;
124  tl.push_back(model::term_description(varname, varname, true));
125  model::varnamelist dl(1, dataname);
126  return md.add_brick(pbr, model::varnamelist(1, varname), dl, tl,
127  model::mimlist(1, &mim), region);
128  }
129 
131  (model &md, const mesh_im &mim, const std::string &varname,
132  const std::string &dataname1, const std::string &dataname2,
133  size_type region) {
134  pbrick pbr = std::make_shared<bilap_brick>();
135  model::termlist tl;
136  tl.push_back(model::term_description(varname, varname, true));
137  model::varnamelist dl(1, dataname1);
138  dl.push_back(dataname2);
139  return md.add_brick(pbr, model::varnamelist(1, varname), dl, tl,
140  model::mimlist(1, &mim), region);
141  }
142 
143 
144 
145  // ----------------------------------------------------------------------
146  //
147  // Normal derivative source term brick
148  //
149  // ----------------------------------------------------------------------
150 
151  struct normal_derivative_source_term_brick : public virtual_brick {
152 
153  virtual void asm_real_tangent_terms(const model &md, size_type,
154  const model::varnamelist &vl,
155  const model::varnamelist &dl,
156  const model::mimlist &mims,
157  model::real_matlist &,
158  model::real_veclist &vecl,
159  model::real_veclist &,
160  size_type region,
161  build_version) const {
162  GMM_ASSERT1(vecl.size() == 1,
163  "Normal derivative source term brick has one and only "
164  "one term");
165  GMM_ASSERT1(mims.size() == 1,
166  "Normal derivative source term brick need one and only "
167  "one mesh_im");
168  GMM_ASSERT1(vl.size() == 1 && dl.size() == 1,
169  "Wrong number of variables for normal derivative "
170  "source term brick");
171 
172  const mesh_fem &mf_u = md.mesh_fem_of_variable(vl[0]);
173  const mesh_im &mim = *mims[0];
174  const model_real_plain_vector &A = md.real_variable(dl[0]);
175  const mesh_fem *mf_data = md.pmesh_fem_of_variable(dl[0]);
176  mesh_region rg(region);
177  mim.linked_mesh().intersect_with_mpi_region(rg);
178 
179  size_type s = gmm::vect_size(A);
180  if (mf_data) s = s * mf_data->get_qdim() / mf_data->nb_dof();
181 
182  GMM_ASSERT1(s == mf_u.get_qdim()
183  || s == size_type(mf_u.get_qdim()*gmm::sqr(mf_u.linked_mesh().dim())),
184  dl[0] << ": bad format of normal derivative source term "
185  "data. Detected dimension is " << s << " should be "
186  << size_type(mf_u.get_qdim()));
187 
188  GMM_TRACE2("Normal derivative source term assembly");
189  if (mf_data)
190  asm_normal_derivative_source_term(vecl[0], mim, mf_u, *mf_data, A, rg);
191  else
192  asm_homogeneous_normal_derivative_source_term(vecl[0], mim, mf_u, A, rg);
193 
194  }
195 
196  virtual void asm_complex_tangent_terms(const model &md, size_type,
197  const model::varnamelist &vl,
198  const model::varnamelist &dl,
199  const model::mimlist &mims,
200  model::complex_matlist &,
201  model::complex_veclist &vecl,
202  model::complex_veclist &,
203  size_type region,
204  build_version) const {
205  GMM_ASSERT1(vecl.size() == 1,
206  "Normal derivative source term brick has one and only "
207  "one term");
208  GMM_ASSERT1(mims.size() == 1,
209  "Normal derivative source term brick need one and only "
210  "one mesh_im");
211  GMM_ASSERT1(vl.size() == 1 && dl.size() == 1,
212  "Wrong number of variables for normal derivative "
213  "source term brick");
214 
215  const mesh_fem &mf_u = md.mesh_fem_of_variable(vl[0]);
216  const mesh_im &mim = *mims[0];
217  const model_complex_plain_vector &A = md.complex_variable(dl[0]);
218  const mesh_fem *mf_data = md.pmesh_fem_of_variable(dl[0]);
219  mesh_region rg(region);
220  mim.linked_mesh().intersect_with_mpi_region(rg);
221 
222  size_type s = gmm::vect_size(A);
223  if (mf_data) s = s * mf_data->get_qdim() / mf_data->nb_dof();
224 
225  GMM_ASSERT1(mf_u.get_qdim() == s,
226  dl[0] << ": bad format of normal derivative source term "
227  "data. Detected dimension is " << s << " should be "
228  << size_type(mf_u.get_qdim()));
229 
230  GMM_TRACE2("Normal derivative source term assembly");
231  if (mf_data)
232  asm_normal_derivative_source_term(vecl[0], mim, mf_u, *mf_data, A, rg);
233  else
234  asm_homogeneous_normal_derivative_source_term(vecl[0], mim, mf_u, A, rg);
235 
236  }
237 
238  normal_derivative_source_term_brick(void) {
239  set_flags("Normal derivative source term", true /* is linear*/,
240  true /* is symmetric */, true /* is coercive */,
241  true /* is real */, true /* is complex */,
242  false /* compute each time */);
243  }
244 
245 
246  };
247 
249  (model &md, const mesh_im &mim, const std::string &varname,
250  const std::string &dataname, size_type region) {
251  pbrick pbr = std::make_shared<normal_derivative_source_term_brick>();
252  model::termlist tl;
253  tl.push_back(model::term_description(varname));
254  model::varnamelist vdata(1, dataname);
255  return md.add_brick(pbr, model::varnamelist(1, varname),
256  vdata, tl, model::mimlist(1, &mim), region);
257  }
258 
259 
260 
261  // ----------------------------------------------------------------------
262  //
263  // K.L. source term brick
264  //
265  // ----------------------------------------------------------------------
266 
267  struct KL_source_term_brick : public virtual_brick {
268 
269  virtual void asm_real_tangent_terms(const model &md, size_type,
270  const model::varnamelist &vl,
271  const model::varnamelist &dl,
272  const model::mimlist &mims,
273  model::real_matlist &,
274  model::real_veclist &vecl,
275  model::real_veclist &,
276  size_type region,
277  build_version) const {
278  GMM_ASSERT1(vecl.size() == 1,
279  "Kirchhoff Love source term brick has one and only "
280  "one term");
281  GMM_ASSERT1(mims.size() == 1,
282  "Kirchhoff Love source term brick need one and only "
283  "one mesh_im");
284  GMM_ASSERT1(vl.size() == 1 && dl.size() == 2,
285  "Wrong number of variables for Kirchhoff Love "
286  "source term brick");
287 
288  const mesh_fem &mf_u = md.mesh_fem_of_variable(vl[0]);
289  const mesh_im &mim = *mims[0];
290  const model_real_plain_vector &A = md.real_variable(dl[0]);
291  const mesh_fem *mf_dataA = md.pmesh_fem_of_variable(dl[0]);
292  const model_real_plain_vector &B = md.real_variable(dl[1]);
293  const mesh_fem *mf_dataB = md.pmesh_fem_of_variable(dl[1]);
294  size_type N = mf_u.linked_mesh().dim();
295  mesh_region rg(region);
296  mim.linked_mesh().intersect_with_mpi_region(rg);
297 
298  size_type s = gmm::vect_size(A);
299  if (mf_dataA) s = s * mf_dataA->get_qdim() / mf_dataA->nb_dof();
300  GMM_ASSERT1(mf_u.get_qdim() == 1 && s == N*N,
301  dl[0] << ": bad format of Kirchhoff Love Neumann term "
302  "data. Detected dimension is " << s << " should be "
303  << N*N);
304 
305  s = gmm::vect_size(B);
306  if (mf_dataB) s = s * mf_dataB->get_qdim() / mf_dataB->nb_dof();
307  GMM_ASSERT1(s == N,
308  dl[0] << ": bad format of Kirchhoff Love Neumann term "
309  "data. Detected dimension is " << s << " should be "
310  << N);
311 
312 
313  GMM_TRACE2("Kirchhoff Love Neumann term assembly");
314  if (mf_dataA)
315  asm_neumann_KL_term(vecl[0], mim, mf_u, *mf_dataA, A, B, rg);
316  else
317  asm_neumann_KL_homogeneous_term(vecl[0], mim, mf_u, A, B, rg);
318 
319  }
320 
321  KL_source_term_brick(void) {
322  set_flags("Kirchhoff Love Neumann term", true /* is linear*/,
323  true /* is symmetric */, true /* is coercive */,
324  true /* is real */, false /* is complex */,
325  false /* compute each time */);
326  }
327 
328 
329  };
330 
332  (model &md, const mesh_im &mim, const std::string &varname,
333  const std::string &dataname1, const std::string &dataname2,
334  size_type region) {
335  pbrick pbr = std::make_shared<KL_source_term_brick>();
336  model::termlist tl;
337  tl.push_back(model::term_description(varname));
338  model::varnamelist vdata(1, dataname1);
339  vdata.push_back(dataname2);
340  return md.add_brick(pbr, model::varnamelist(1, varname),
341  vdata, tl, model::mimlist(1, &mim), region);
342  }
343 
344 
345 
346 
347 
348 
349 
350 
351 
352 
353 
354 
355 
356 
357 
358 
359 
360 
361 
362 
363 
364 
365 
366 
367  // ----------------------------------------------------------------------
368  //
369  // Normal derivative Dirichlet condition brick
370  //
371  // ----------------------------------------------------------------------
372  // Two variables : with multipliers
373  // One variable : penalization
374 
375  struct normal_derivative_Dirichlet_condition_brick : public virtual_brick {
376 
377  bool R_must_be_derivated;
382 
383  virtual void asm_real_tangent_terms(const model &md, size_type ib,
384  const model::varnamelist &vl,
385  const model::varnamelist &dl,
386  const model::mimlist &mims,
387  model::real_matlist &matl,
388  model::real_veclist &vecl,
389  model::real_veclist &,
390  size_type region,
391  build_version version) const {
392  GMM_ASSERT1(vecl.size() == 1 && matl.size() == 1,
393  "Normal derivative Dirichlet condition brick has one and "
394  "only one term");
395  GMM_ASSERT1(mims.size() == 1,
396  "Normal derivative Dirichlet condition brick need one and "
397  "only one mesh_im");
398  GMM_ASSERT1(vl.size() >= 1 && vl.size() <= 2 && dl.size() <= 2,
399  "Wrong number of variables for normal derivative Dirichlet "
400  "condition brick");
401 
402  model_real_sparse_matrix& rB = rB_th;
403  model_real_plain_vector& rV = rV_th;
404 
405  bool penalized = (vl.size() == 1);
406  const mesh_fem &mf_u = md.mesh_fem_of_variable(vl[0]);
407  const mesh_fem &mf_mult = md.mesh_fem_of_variable(vl[vl.size()-1]);
408  const mesh_im &mim = *mims[0];
409  const model_real_plain_vector *A = 0, *COEFF = 0;
410  const mesh_fem *mf_data = 0;
411  bool recompute_matrix = !((version & model::BUILD_ON_DATA_CHANGE) != 0)
412  || (penalized && md.is_var_newer_than_brick(dl[0], ib));
413 
414  if (penalized) {
415  COEFF = &(md.real_variable(dl[0]));
416  GMM_ASSERT1(gmm::vect_size(*COEFF) == 1,
417  "Data for coefficient should be a scalar");
418  }
419 
420  size_type s = 0, ind = (penalized ? 1 : 0);
421  if (dl.size() > ind) {
422  A = &(md.real_variable(dl[ind]));
423  mf_data = md.pmesh_fem_of_variable(dl[ind]);
424  s = gmm::vect_size(*A);
425  if (mf_data) s = s * mf_data->get_qdim() / mf_data->nb_dof();
426  GMM_ASSERT1(s == mf_u.get_qdim() || s == mf_u.linked_mesh().dim(),
427  dl[ind] << ": bad format of normal derivative Dirichlet "
428  "data. Detected dimension is " << s << " should be "
429  << size_type(mf_u.get_qdim()) << " or "
430  << mf_u.linked_mesh().dim());
431  }
432 
433  mesh_region rg(region);
434  mim.linked_mesh().intersect_with_mpi_region(rg);
435 
436  if (recompute_matrix) {
437  GMM_TRACE2("Mass term assembly for normal derivative Dirichlet "
438  "condition");
439  if (penalized) {
440  gmm::resize(rB, mf_mult.nb_dof(), mf_u.nb_dof());
441  gmm::clear(rB);
443  (rB, vecl[0], mim, mf_u, mf_mult,
444  *mf_data, *A, rg, R_must_be_derivated, ASMDIR_BUILDH);
445  } else {
446  gmm::clear(matl[0]);
448  (matl[0], vecl[0], mim, mf_u, mf_mult,
449  *mf_data, *A, rg, R_must_be_derivated, ASMDIR_BUILDH);
450  }
451 
452  if (penalized) {
453  gmm::mult(gmm::transposed(rB), rB, matl[0]);
454  gmm::scale(matl[0], gmm::abs((*COEFF)[0]));
455  }
456  }
457 
458  if (dl.size() > ind) {
459  GMM_TRACE2("Source term assembly for normal derivative Dirichlet "
460  "condition");
461  model_real_plain_vector *R = penalized ? &rV : &(vecl[0]);
462  if (penalized) { gmm::resize(rV, mf_mult.nb_dof()); gmm::clear(rV); }
463 
464  if (mf_data) {
465  if (!R_must_be_derivated) {
466  if (s == mf_u.linked_mesh().dim())
467  asm_normal_source_term(*R, mim, mf_mult, *mf_data, *A, rg);
468  else
469  asm_source_term(*R, mim, mf_mult, *mf_data, *A, rg);
470  }
471  else {
472  asm_real_or_complex_1_param_vec
473  (*R, mim, mf_mult, mf_data, *A, rg, "(Grad_A.Normal)*Test_u");
474  // asm_real_or_complex_1_param
475  // (*R, mim, mf_mult, *mf_data, *A, rg,
476  // "R=data(#2); V(#1)+=comp(Base(#1).Grad(#2).Normal())(:,i,j,j).R(i)");
477  }
478  } else {
479  GMM_ASSERT1(!R_must_be_derivated, "Incoherent situation");
480  if (s == mf_u.linked_mesh().dim())
481  asm_homogeneous_normal_source_term(*R, mim, mf_mult, *A, rg);
482  else
483  asm_homogeneous_source_term(*R, mim, mf_mult, *A, rg);
484  }
485  if (penalized) {
486  gmm::mult(gmm::transposed(rB), rV, vecl[0]);
487  gmm::scale(vecl[0], gmm::abs((*COEFF)[0]));
488  rV = model_real_plain_vector();
489  }
490  }
491 
492 
493  }
494 
495  virtual void asm_complex_tangent_terms(const model &md, size_type ib,
496  const model::varnamelist &vl,
497  const model::varnamelist &dl,
498  const model::mimlist &mims,
499  model::complex_matlist &matl,
500  model::complex_veclist &vecl,
501  model::complex_veclist &,
502  size_type region,
503  build_version version) const {
504  GMM_ASSERT1(vecl.size() == 1 && matl.size() == 1,
505  "Normal derivative Dirichlet condition brick has one and "
506  "only one term");
507  GMM_ASSERT1(mims.size() == 1,
508  "Normal derivative Dirichlet condition brick need one and "
509  "only one mesh_im");
510  GMM_ASSERT1(vl.size() >= 1 && vl.size() <= 2 && dl.size() <= 2,
511  "Wrong number of variables for normal derivative Dirichlet "
512  "condition brick");
513 
514  model_complex_sparse_matrix& cB = cB_th;
515  model_complex_plain_vector& cV = cV_th;
516 
517  bool penalized = (vl.size() == 1);
518  const mesh_fem &mf_u = md.mesh_fem_of_variable(vl[0]);
519  const mesh_fem &mf_mult = md.mesh_fem_of_variable(vl[vl.size()-1]);
520  const mesh_im &mim = *mims[0];
521  const model_complex_plain_vector *A = 0, *COEFF = 0;
522  const mesh_fem *mf_data = 0;
523  bool recompute_matrix = !((version & model::BUILD_ON_DATA_CHANGE) != 0)
524  || (penalized && md.is_var_newer_than_brick(dl[0], ib));
525 
526  if (penalized) {
527  COEFF = &(md.complex_variable(dl[0]));
528  GMM_ASSERT1(gmm::vect_size(*COEFF) == 1,
529  "Data for coefficient should be a scalar");
530  }
531 
532  size_type s = 0, ind = (penalized ? 1 : 0);
533  if (dl.size() > ind) {
534  A = &(md.complex_variable(dl[ind]));
535  mf_data = md.pmesh_fem_of_variable(dl[ind]);
536  s = gmm::vect_size(*A);
537  if (mf_data) s = s * mf_data->get_qdim() / mf_data->nb_dof();
538  GMM_ASSERT1(s == mf_u.get_qdim() || s == mf_u.linked_mesh().dim(),
539  dl[ind] << ": bad format of normal derivative Dirichlet "
540  "data. Detected dimension is " << s << " should be "
541  << size_type(mf_u.get_qdim()) << " or "
542  << mf_u.linked_mesh().dim());
543  }
544 
545  mesh_region rg(region);
546  mim.linked_mesh().intersect_with_mpi_region(rg);
547 
548  if (recompute_matrix) {
549  GMM_TRACE2("Mass term assembly for normal derivative Dirichlet "
550  "condition");
551  if (penalized) {
552  gmm::resize(cB, mf_mult.nb_dof(), mf_u.nb_dof());
553  gmm::clear(cB);
555  (cB, vecl[0], mim, mf_u, mf_mult,
556  *mf_data, *A, rg, R_must_be_derivated, ASMDIR_BUILDH);
557  } else {
558  gmm::clear(matl[0]);
560  (matl[0], vecl[0], mim, mf_u, mf_mult,
561  *mf_data, *A, rg, R_must_be_derivated, ASMDIR_BUILDH);
562  }
563 
564  if (penalized) {
565  gmm::mult(gmm::transposed(cB), cB, matl[0]);
566  gmm::scale(matl[0], gmm::abs((*COEFF)[0]));
567  }
568  }
569 
570  if (dl.size() > ind) {
571  GMM_TRACE2("Source term assembly for normal derivative Dirichlet "
572  "condition");
573  model_complex_plain_vector *R = penalized ? &cV : &(vecl[0]);
574  if (penalized) { gmm::resize(cV, mf_mult.nb_dof()); gmm::clear(cV); }
575 
576  if (mf_data) {
577  if (!R_must_be_derivated) {
578  if (s == mf_u.linked_mesh().dim())
579  asm_normal_source_term(*R, mim, mf_mult, *mf_data, *A, rg);
580  else
581  asm_source_term(*R, mim, mf_mult, *mf_data, *A, rg);
582  }
583  else {
584  asm_real_or_complex_1_param_vec
585  (*R, mim, mf_mult, mf_data, *A, rg, "(Grad_A.Normal)*Test_u");
586  // asm_real_or_complex_1_param
587  // (*R, mim, mf_mult, *mf_data, *A, rg,
588  // "R=data(#2); V(#1)+=comp(Base(#1).Grad(#2).Normal())(:,i,j,j).R(i)");
589  }
590  } else {
591  GMM_ASSERT1(!R_must_be_derivated, "Incoherent situation");
592  if (s == mf_u.linked_mesh().dim())
593  asm_homogeneous_normal_source_term(*R, mim, mf_mult, *A, rg);
594  else
595  asm_homogeneous_source_term(*R, mim, mf_mult, *A, rg);
596  }
597  if (penalized) {
598  gmm::mult(gmm::transposed(cB), cV, vecl[0]);
599  gmm::scale(vecl[0], gmm::abs((*COEFF)[0]));
600  cV = model_complex_plain_vector();
601  }
602  }
603  }
604 
605  normal_derivative_Dirichlet_condition_brick
606  (bool penalized, bool R_must_be_derivated_) {
607  R_must_be_derivated = R_must_be_derivated_;
608  set_flags(penalized ?
609  "Normal derivative Dirichlet with penalization brick"
610  : "Normal derivative Dirichlet with multipliers brick",
611  true /* is linear*/,
612  true /* is symmetric */, penalized /* is coercive */,
613  true /* is real */, true /* is complex */,
614  false /* compute each time */);
615  }
616  };
617 
619  (model &md, const mesh_im &mim, const std::string &varname,
620  const std::string &multname, size_type region,
621  const std::string &dataname, bool R_must_be_derivated) {
622  pbrick pbr = std::make_shared<normal_derivative_Dirichlet_condition_brick>(false, R_must_be_derivated);
623  model::termlist tl;
624  tl.push_back(model::term_description(multname, varname, true));
625  model::varnamelist vl(1, varname);
626  vl.push_back(multname);
627  model::varnamelist dl;
628  if (dataname.size()) dl.push_back(dataname);
629  return md.add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region);
630  }
631 
633  (model &md, const mesh_im &mim, const std::string &varname,
634  const mesh_fem &mf_mult, size_type region,
635  const std::string &dataname, bool R_must_be_derivated) {
636  std::string multname = md.new_name("mult_on_" + varname);
637  md.add_multiplier(multname, mf_mult, varname);
639  (md, mim, varname, multname, region, dataname, R_must_be_derivated);
640  }
641 
643  (model &md, const mesh_im &mim, const std::string &varname,
644  dim_type degree, size_type region,
645  const std::string &dataname, bool R_must_be_derivated) {
646  const mesh_fem &mf_u = md.mesh_fem_of_variable(varname);
647  const mesh_fem &mf_mult = classical_mesh_fem(mf_u.linked_mesh(),
648  degree, mf_u.get_qdim());
650  (md, mim, varname, mf_mult, region, dataname, R_must_be_derivated);
651  }
652 
653 
655  (model &md, const mesh_im &mim, const std::string &varname,
656  scalar_type penalisation_coeff, size_type region,
657  const std::string &dataname, bool R_must_be_derivated) {
658  std::string coeffname = md.new_name("penalization_on_" + varname);
659  md.add_fixed_size_data(coeffname, 1);
660  if (md.is_complex())
661  md.set_complex_variable(coeffname)[0] = penalisation_coeff;
662  else
663  md.set_real_variable(coeffname)[0] = penalisation_coeff;
664  pbrick pbr = std::make_shared<normal_derivative_Dirichlet_condition_brick>(true, R_must_be_derivated);
665  model::termlist tl;
666  tl.push_back(model::term_description(varname, varname, true));
667  model::varnamelist vl(1, varname);
668  model::varnamelist dl(1, coeffname);
669  if (dataname.size()) dl.push_back(dataname);
670  return md.add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region);
671  }
672 
673  // + changement du coeff de penalisation avec la fonction de Dirichelt standard.
674 
675 
676 
677 } /* end of namespace getfem. */
678 
Describe a finite element method linked to a mesh.
virtual dim_type get_qdim() const
Return the Q dimension.
const mesh & linked_mesh() const
Return a reference to the underlying mesh.
Describe an integration method linked to a mesh.
`‘Model’' variables store the variables, the data and the description of a model.
void add_fixed_size_data(const std::string &name, size_type size, size_type niter=1)
Add a fixed size data to the model.
size_type add_brick(pbrick pbr, const varnamelist &varnames, const varnamelist &datanames, const termlist &terms, const mimlist &mims, size_type region)
Add a brick to the model.
const mesh_fem & mesh_fem_of_variable(const std::string &name) const
Gives the access to the mesh_fem of a variable if any.
void add_multiplier(const std::string &name, const mesh_fem &mf, const std::string &primal_name, size_type niter=1)
Add a particular variable linked to a fem being a multiplier with respect to a primal variable.
model_real_plain_vector & set_real_variable(const std::string &name, size_type niter) const
Gives the write access to the vector value of a variable.
bool is_complex() const
Boolean which says if the model deals with real or complex unknowns and data.
model_complex_plain_vector & set_complex_variable(const std::string &name, size_type niter) const
Gives the write access to the vector value of a variable.
std::string new_name(const std::string &name)
Gives a non already existing variable name begining by name.
assembly procedures and bricks for fourth order pdes.
Tools for multithreaded, OpenMP and Boost based parallelization.
void clear(L &l)
clear (fill with zeros) a vector or matrix.
Definition: gmm_blas.h:58
void resize(V &v, size_type n)
*‍/
Definition: gmm_blas.h:209
void mult(const L1 &l1, const L2 &l2, L3 &l3)
*‍/
Definition: gmm_blas.h:1663
void asm_stiffness_matrix_for_bilaplacian(const MAT &M, const mesh_im &mim, const mesh_fem &mf, const mesh_fem &mf_data, const VECT &A, const mesh_region &rg=mesh_region::all_convexes())
assembly of .
void asm_source_term(const VECT1 &B, const mesh_im &mim, const mesh_fem &mf, const mesh_fem &mf_data, const VECT2 &F, const mesh_region &rg=mesh_region::all_convexes())
source term (for both volumic sources and boundary (Neumann) sources).
void asm_homogeneous_normal_source_term(VECT1 &B, const mesh_im &mim, const mesh_fem &mf, const VECT2 &F, const mesh_region &rg)
Homogeneous normal source term (for boundary (Neumann) condition).
void asm_normal_derivative_dirichlet_constraints(MAT &H, VECT1 &R, const mesh_im &mim, const mesh_fem &mf_u, const mesh_fem &mf_mult, const mesh_fem &mf_r, const VECT2 &r_data, const mesh_region &rg, bool R_must_be_derivated, int version)
Assembly of normal derivative Dirichlet constraints in a weak form.
void asm_normal_derivative_source_term(VECT1 &B, const mesh_im &mim, const mesh_fem &mf, const mesh_fem &mf_data, const VECT2 &F, const mesh_region &rg)
assembly of .
void asm_normal_source_term(VECT1 &B, const mesh_im &mim, const mesh_fem &mf, const mesh_fem &mf_data, const VECT2 &F, const mesh_region &rg)
Normal source term (for boundary (Neumann) condition).
void asm_homogeneous_source_term(const VECT1 &B, const mesh_im &mim, const mesh_fem &mf, const VECT2 &F, const mesh_region &rg=mesh_region::all_convexes())
source term (for both volumic sources and boundary (Neumann) sources).
size_t size_type
used as the common size type in the library
Definition: bgeot_poly.h:48
GEneric Tool for Finite Element Methods.
size_type add_bilaplacian_brick(model &md, const mesh_im &mim, const std::string &varname, const std::string &dataname, size_type region=size_type(-1))
Adds a bilaplacian brick on the variable varname and on the mesh region region.
size_type add_bilaplacian_brick_KL(model &md, const mesh_im &mim, const std::string &varname, const std::string &dataname1, const std::string &dataname2, size_type region=size_type(-1))
Adds a bilaplacian brick on the variable varname and on the mesh region region.
size_type add_normal_derivative_Dirichlet_condition_with_multipliers(model &md, const mesh_im &mim, const std::string &varname, const std::string &multname, size_type region, const std::string &dataname=std::string(), bool R_must_be_derivated=false)
Adds a Dirichlet condition on the normal derivative of the variable varname and on the mesh region re...
std::shared_ptr< const virtual_brick > pbrick
type of pointer on a brick
Definition: getfem_models.h:48
const mesh_fem & classical_mesh_fem(const mesh &mesh, dim_type degree, dim_type qdim=1, bool complete=false)
Gives the descriptor of a classical finite element method of degree K on mesh.
size_type add_normal_derivative_source_term_brick(model &md, const mesh_im &mim, const std::string &varname, const std::string &dataname, size_type region)
Adds a normal derivative source term brick :math:F = \int b.
size_type add_Kirchhoff_Love_Neumann_term_brick(model &md, const mesh_im &mim, const std::string &varname, const std::string &dataname1, const std::string &dataname2, size_type region)
Adds a Neumann term brick for Kirchhoff-Love model on the variable varname and the mesh region region...
size_type add_normal_derivative_Dirichlet_condition_with_penalization(model &md, const mesh_im &mim, const std::string &varname, scalar_type penalisation_coeff, size_type region, const std::string &dataname=std::string(), bool R_must_be_derivated=false)
Adds a Dirichlet condition on the normal derivative of the variable varname and on the mesh region re...