33 struct bilap_brick :
public virtual_brick {
35 virtual void asm_real_tangent_terms(
const model &md,
size_type ib,
36 const model::varnamelist &vl,
37 const model::varnamelist &dl,
38 const model::mimlist &mims,
39 model::real_matlist &matl,
40 model::real_veclist &,
41 model::real_veclist &,
43 build_version version)
const {
44 GMM_ASSERT1(matl.size() == 1,
45 "Bilaplacian brick has one and only one term");
46 GMM_ASSERT1(mims.size() == 1,
47 "Bilaplacian brick need one and only one mesh_im");
48 GMM_ASSERT1(vl.size() == 1 && (dl.size() == 1 || dl.size() == 2),
49 "Wrong number of variables for bilaplacian brick");
51 bool KL = (dl.size() == 2);
53 bool recompute_matrix = !((version & model::BUILD_ON_DATA_CHANGE) != 0)
54 || md.is_var_newer_than_brick(dl[0], ib);
57 if (recompute_matrix) {
59 const mesh_fem &mf_u = md.mesh_fem_of_variable(vl[0]);
60 const mesh &m = mf_u.linked_mesh();
62 GMM_ASSERT1(Q == 1,
"Bilaplacian brick is only for a scalar field");
63 const mesh_im &mim = *mims[0];
64 mesh_region rg(region);
65 m.intersect_with_mpi_region(rg);
66 const mesh_fem *mf_data = md.pmesh_fem_of_variable(dl[0]);
67 const model_real_plain_vector *data = &(md.real_variable(dl[0]));
69 if (mf_data) sl = sl * mf_data->get_qdim() / mf_data->nb_dof();
71 GMM_ASSERT1(sl == 1,
"Bad format of bilaplacian coefficient");
73 const mesh_fem *mf_data2 = 0;
74 const model_real_plain_vector *data2 = 0;
76 mf_data2 = md.pmesh_fem_of_variable(dl[1]);
77 data2 = &(md.real_variable(dl[1]));
79 if (mf_data2) sl = sl * mf_data2->get_qdim() / mf_data2->nb_dof();
80 GMM_ASSERT1(sl2 == 1,
"Bad format of bilaplacian coefficient");
84 GMM_TRACE2(
"Stiffness matrix assembly of a bilaplacian term for a " 85 "Kirchhoff-Love plate");
88 GMM_TRACE2(
"Stiffness matrix assembly of a bilaplacian term");
94 asm_stiffness_matrix_for_bilaplacian_KL
95 (matl[0], mim, mf_u, *mf_data, *data, *data2, rg);
98 (matl[0], mim, mf_u, *mf_data, *data, rg);
101 asm_stiffness_matrix_for_homogeneous_bilaplacian_KL
102 (matl[0], mim, mf_u, *data, *data2, rg);
105 asm_stiffness_matrix_for_homogeneous_bilaplacian
106 (matl[0], mim, mf_u, *data, rg);
112 set_flags(
"Bilaplacian operator",
true ,
121 const std::string &dataname,
123 pbrick pbr = std::make_shared<bilap_brick>();
125 tl.push_back(model::term_description(varname, varname,
true));
126 model::varnamelist dl(1, dataname);
127 return md.
add_brick(pbr, model::varnamelist(1, varname), dl, tl,
128 model::mimlist(1, &mim), region);
133 const std::string &dataname1,
const std::string &dataname2,
135 pbrick pbr = std::make_shared<bilap_brick>();
137 tl.push_back(model::term_description(varname, varname,
true));
138 model::varnamelist dl(1, dataname1);
139 dl.push_back(dataname2);
140 return md.
add_brick(pbr, model::varnamelist(1, varname), dl, tl,
141 model::mimlist(1, &mim), region);
152 struct normal_derivative_source_term_brick :
public virtual_brick {
155 const model::varnamelist &vl,
156 const model::varnamelist &dl,
157 const model::mimlist &mims,
158 model::real_matlist &,
159 model::real_veclist &vecl,
160 model::real_veclist &,
162 build_version)
const {
163 GMM_ASSERT1(vecl.size() == 1,
164 "Normal derivative source term brick has one and only " 166 GMM_ASSERT1(mims.size() == 1,
167 "Normal derivative source term brick need one and only " 169 GMM_ASSERT1(vl.size() == 1 && dl.size() == 1,
170 "Wrong number of variables for normal derivative " 171 "source term brick");
183 GMM_ASSERT1(s == mf_u.get_qdim()
184 || s ==
size_type(mf_u.get_qdim()*gmm::sqr(mf_u.linked_mesh().dim())),
185 dl[0] <<
": bad format of normal derivative source term " 186 "data. Detected dimension is " << s <<
" should be " 189 GMM_TRACE2(
"Normal derivative source term assembly");
193 asm_homogeneous_normal_derivative_source_term(vecl[0], mim, mf_u, A, rg);
197 virtual void asm_complex_tangent_terms(
const model &md,
size_type,
198 const model::varnamelist &vl,
199 const model::varnamelist &dl,
200 const model::mimlist &mims,
201 model::complex_matlist &,
202 model::complex_veclist &vecl,
203 model::complex_veclist &,
205 build_version)
const {
206 GMM_ASSERT1(vecl.size() == 1,
207 "Normal derivative source term brick has one and only " 209 GMM_ASSERT1(mims.size() == 1,
210 "Normal derivative source term brick need one and only " 212 GMM_ASSERT1(vl.size() == 1 && dl.size() == 1,
213 "Wrong number of variables for normal derivative " 214 "source term brick");
226 GMM_ASSERT1(mf_u.get_qdim() == s,
227 dl[0] <<
": bad format of normal derivative source term " 228 "data. Detected dimension is " << s <<
" should be " 231 GMM_TRACE2(
"Normal derivative source term assembly");
235 asm_homogeneous_normal_derivative_source_term(vecl[0], mim, mf_u, A, rg);
239 normal_derivative_source_term_brick(
void) {
240 set_flags(
"Normal derivative source term",
true ,
251 const std::string &dataname,
size_type region) {
252 pbrick pbr = std::make_shared<normal_derivative_source_term_brick>();
254 tl.push_back(model::term_description(varname));
255 model::varnamelist vdata(1, dataname);
256 return md.
add_brick(pbr, model::varnamelist(1, varname),
257 vdata, tl, model::mimlist(1, &mim), region);
271 const model::varnamelist &vl,
272 const model::varnamelist &dl,
273 const model::mimlist &mims,
274 model::real_matlist &,
275 model::real_veclist &vecl,
276 model::real_veclist &,
278 build_version)
const {
279 GMM_ASSERT1(vecl.size() == 1,
280 "Kirchhoff Love source term brick has one and only " 282 GMM_ASSERT1(mims.size() == 1,
283 "Kirchhoff Love source term brick need one and only " 285 GMM_ASSERT1(vl.size() == 1 && dl.size() == 2,
286 "Wrong number of variables for Kirchhoff Love " 287 "source term brick");
301 GMM_ASSERT1(mf_u.get_qdim() == 1 && s == N*N,
302 dl[0] <<
": bad format of Kirchhoff Love Neumann term " 303 "data. Detected dimension is " << s <<
" should be " 306 s = gmm::vect_size(B);
309 dl[0] <<
": bad format of Kirchhoff Love Neumann term " 310 "data. Detected dimension is " << s <<
" should be " 314 GMM_TRACE2(
"Kirchhoff Love Neumann term assembly");
316 asm_neumann_KL_term(vecl[0], mim, mf_u, *mf_dataA, A, B, rg);
318 asm_neumann_KL_homogeneous_term(vecl[0], mim, mf_u, A, B, rg);
322 KL_source_term_brick(
void) {
323 set_flags(
"Kirchhoff Love Neumann term",
true ,
334 const std::string &dataname1,
const std::string &dataname2,
336 pbrick pbr = std::make_shared<KL_source_term_brick>();
338 tl.push_back(model::term_description(varname));
339 model::varnamelist vdata(1, dataname1);
340 vdata.push_back(dataname2);
341 return md.
add_brick(pbr, model::varnamelist(1, varname),
342 vdata, tl, model::mimlist(1, &mim), region);
376 struct normal_derivative_Dirichlet_condition_brick :
public virtual_brick {
378 bool R_must_be_derivated;
384 virtual void asm_real_tangent_terms(
const model &md,
size_type ib,
385 const model::varnamelist &vl,
386 const model::varnamelist &dl,
387 const model::mimlist &mims,
388 model::real_matlist &matl,
389 model::real_veclist &vecl,
390 model::real_veclist &,
392 build_version version)
const {
393 GMM_ASSERT1(vecl.size() == 1 && matl.size() == 1,
394 "Normal derivative Dirichlet condition brick has one and " 396 GMM_ASSERT1(mims.size() == 1,
397 "Normal derivative Dirichlet condition brick need one and " 399 GMM_ASSERT1(vl.size() >= 1 && vl.size() <= 2 && dl.size() <= 2,
400 "Wrong number of variables for normal derivative Dirichlet " 403 model_real_sparse_matrix& rB = rB_th;
404 model_real_plain_vector& rV = rV_th;
406 bool penalized = (vl.size() == 1);
410 const model_real_plain_vector *A = 0, *COEFF = 0;
412 bool recompute_matrix = !((version & model::BUILD_ON_DATA_CHANGE) != 0)
413 || (penalized && md.is_var_newer_than_brick(dl[0], ib));
417 GMM_ASSERT1(gmm::vect_size(*COEFF) == 1,
418 "Data for coefficient should be a scalar");
421 size_type s = 0, ind = (penalized ? 1 : 0);
422 if (dl.size() > ind) {
425 s = gmm::vect_size(*A);
428 dl[ind] <<
": bad format of normal derivative Dirichlet " 429 "data. Detected dimension is " << s <<
" should be " 437 if (recompute_matrix) {
438 GMM_TRACE2(
"Mass term assembly for normal derivative Dirichlet " 444 (rB, vecl[0], mim, mf_u, mf_mult,
445 *mf_data, *A, rg, R_must_be_derivated, ASMDIR_BUILDH);
449 (matl[0], vecl[0], mim, mf_u, mf_mult,
450 *mf_data, *A, rg, R_must_be_derivated, ASMDIR_BUILDH);
454 gmm::mult(gmm::transposed(rB), rB, matl[0]);
455 gmm::scale(matl[0], gmm::abs((*COEFF)[0]));
459 if (dl.size() > ind) {
460 GMM_TRACE2(
"Source term assembly for normal derivative Dirichlet " 462 model_real_plain_vector *R = penalized ? &rV : &(vecl[0]);
463 if (penalized) { gmm::resize(rV, mf_mult.
nb_dof()); gmm::clear(rV); }
466 if (!R_must_be_derivated) {
473 asm_real_or_complex_1_param_vec
474 (*R, mim, mf_mult, mf_data, *A, rg,
"(Grad_A.Normal)*Test_u");
480 GMM_ASSERT1(!R_must_be_derivated,
"Incoherent situation");
487 gmm::mult(gmm::transposed(rB), rV, vecl[0]);
488 gmm::scale(vecl[0], gmm::abs((*COEFF)[0]));
489 rV = model_real_plain_vector();
496 virtual void asm_complex_tangent_terms(
const model &md,
size_type ib,
497 const model::varnamelist &vl,
498 const model::varnamelist &dl,
499 const model::mimlist &mims,
500 model::complex_matlist &matl,
501 model::complex_veclist &vecl,
502 model::complex_veclist &,
504 build_version version)
const {
505 GMM_ASSERT1(vecl.size() == 1 && matl.size() == 1,
506 "Normal derivative Dirichlet condition brick has one and " 508 GMM_ASSERT1(mims.size() == 1,
509 "Normal derivative Dirichlet condition brick need one and " 511 GMM_ASSERT1(vl.size() >= 1 && vl.size() <= 2 && dl.size() <= 2,
512 "Wrong number of variables for normal derivative Dirichlet " 515 model_complex_sparse_matrix& cB = cB_th;
516 model_complex_plain_vector& cV = cV_th;
518 bool penalized = (vl.size() == 1);
522 const model_complex_plain_vector *A = 0, *COEFF = 0;
524 bool recompute_matrix = !((version & model::BUILD_ON_DATA_CHANGE) != 0)
525 || (penalized && md.is_var_newer_than_brick(dl[0], ib));
529 GMM_ASSERT1(gmm::vect_size(*COEFF) == 1,
530 "Data for coefficient should be a scalar");
533 size_type s = 0, ind = (penalized ? 1 : 0);
534 if (dl.size() > ind) {
537 s = gmm::vect_size(*A);
540 dl[ind] <<
": bad format of normal derivative Dirichlet " 541 "data. Detected dimension is " << s <<
" should be " 549 if (recompute_matrix) {
550 GMM_TRACE2(
"Mass term assembly for normal derivative Dirichlet " 556 (cB, vecl[0], mim, mf_u, mf_mult,
557 *mf_data, *A, rg, R_must_be_derivated, ASMDIR_BUILDH);
561 (matl[0], vecl[0], mim, mf_u, mf_mult,
562 *mf_data, *A, rg, R_must_be_derivated, ASMDIR_BUILDH);
566 gmm::mult(gmm::transposed(cB), cB, matl[0]);
567 gmm::scale(matl[0], gmm::abs((*COEFF)[0]));
571 if (dl.size() > ind) {
572 GMM_TRACE2(
"Source term assembly for normal derivative Dirichlet " 574 model_complex_plain_vector *R = penalized ? &cV : &(vecl[0]);
575 if (penalized) { gmm::resize(cV, mf_mult.
nb_dof()); gmm::clear(cV); }
578 if (!R_must_be_derivated) {
585 asm_real_or_complex_1_param_vec
586 (*R, mim, mf_mult, mf_data, *A, rg,
"(Grad_A.Normal)*Test_u");
592 GMM_ASSERT1(!R_must_be_derivated,
"Incoherent situation");
599 gmm::mult(gmm::transposed(cB), cV, vecl[0]);
600 gmm::scale(vecl[0], gmm::abs((*COEFF)[0]));
601 cV = model_complex_plain_vector();
606 normal_derivative_Dirichlet_condition_brick
607 (
bool penalized,
bool R_must_be_derivated_) {
608 R_must_be_derivated = R_must_be_derivated_;
609 set_flags(penalized ?
610 "Normal derivative Dirichlet with penalization brick" 611 :
"Normal derivative Dirichlet with multipliers brick",
621 const std::string &multname,
size_type region,
622 const std::string &dataname,
bool R_must_be_derivated) {
623 pbrick pbr = std::make_shared<normal_derivative_Dirichlet_condition_brick>(
false, R_must_be_derivated);
625 tl.push_back(model::term_description(multname, varname,
true));
626 model::varnamelist vl(1, varname);
627 vl.push_back(multname);
628 model::varnamelist dl;
629 if (dataname.size()) dl.push_back(dataname);
630 return md.
add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region);
636 const std::string &dataname,
bool R_must_be_derivated) {
637 std::string multname = md.
new_name(
"mult_on_" + varname);
640 (md, mim, varname, multname, region, dataname, R_must_be_derivated);
646 const std::string &dataname,
bool R_must_be_derivated) {
651 (md, mim, varname, mf_mult, region, dataname, R_must_be_derivated);
657 scalar_type penalisation_coeff,
size_type region,
658 const std::string &dataname,
bool R_must_be_derivated) {
659 std::string coeffname = md.
new_name(
"penalization_on_" + varname);
665 pbrick pbr = std::make_shared<normal_derivative_Dirichlet_condition_brick>(
true, R_must_be_derivated);
667 tl.push_back(model::term_description(varname, varname,
true));
668 model::varnamelist vl(1, varname);
669 model::varnamelist dl(1, coeffname);
670 if (dataname.size()) dl.push_back(dataname);
671 return md.
add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region);
void add_fixed_size_data(const std::string &name, size_type size, size_type niter=1)
Add a fixed size data to the model.
virtual size_type nb_dof() const
Return the total number of degrees of freedom.
structure used to hold a set of convexes and/or convex faces.
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 .
assembly procedures and bricks for fourth order pdes.
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.
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 , where is in the space of multi...
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).
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.
Describe an integration method linked to a mesh.
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...
Tools for multithreaded, OpenMP and Boost based parallelization.
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...
const mesh_fem & mesh_fem_of_variable(const std::string &name) const
Gives the access to the mesh_fem of a variable if any.
``Model'' variables store the variables, the data and the description of a model. ...
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
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.
virtual dim_type get_qdim() const
Return the Q dimension.
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...
bool is_complex() const
Boolean which says if the model deals with real or complex unknowns and data.
GEneric Tool for Finite Element Methods.
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...
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 = b.
Describe a finite element method linked to a mesh.
void clear(L &l)
clear (fill with zeros) a vector or matrix.
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.
The virtual brick has to be derived to describe real model bricks.
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_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_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 .
std::string new_name(const std::string &name)
Gives a non already existing variable name begining by name.
const mesh & linked_mesh() const
Return a reference to the underlying mesh.
const mesh & linked_mesh() const
Give a reference to the linked mesh of type mesh.
const mesh_fem * pmesh_fem_of_variable(const std::string &name) const
Gives a pointer to the mesh_fem of a variable if any.
const model_real_plain_vector & real_variable(const std::string &name, size_type niter) const
Gives the access to the vector value of a variable.
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::shared_ptr< const virtual_brick > pbrick
type of pointer on a brick
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.
const model_complex_plain_vector & complex_variable(const std::string &name, size_type niter) const
Gives the access to the vector value of a variable.