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 {
154 virtual void asm_real_tangent_terms(
const model &md,
size_type,
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");
173 const mesh_fem &mf_u = md.mesh_fem_of_variable(vl[0]);
174 const mesh_im &mim = *mims[0];
175 const model_real_plain_vector &A = md.real_variable(dl[0]);
176 const mesh_fem *mf_data = md.pmesh_fem_of_variable(dl[0]);
177 mesh_region rg(region);
178 mim.linked_mesh().intersect_with_mpi_region(rg);
181 if (mf_data) s = s * mf_data->get_qdim() / mf_data->nb_dof();
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");
216 const mesh_fem &mf_u = md.mesh_fem_of_variable(vl[0]);
217 const mesh_im &mim = *mims[0];
218 const model_complex_plain_vector &A = md.complex_variable(dl[0]);
219 const mesh_fem *mf_data = md.pmesh_fem_of_variable(dl[0]);
220 mesh_region rg(region);
221 mim.linked_mesh().intersect_with_mpi_region(rg);
224 if (mf_data) s = s * mf_data->get_qdim() / mf_data->nb_dof();
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);
268 struct KL_source_term_brick :
public virtual_brick {
270 virtual void asm_real_tangent_terms(
const model &md,
size_type,
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");
289 const mesh_fem &mf_u = md.mesh_fem_of_variable(vl[0]);
290 const mesh_im &mim = *mims[0];
291 const model_real_plain_vector &A = md.real_variable(dl[0]);
292 const mesh_fem *mf_dataA = md.pmesh_fem_of_variable(dl[0]);
293 const model_real_plain_vector &B = md.real_variable(dl[1]);
294 const mesh_fem *mf_dataB = md.pmesh_fem_of_variable(dl[1]);
296 mesh_region rg(region);
297 mim.linked_mesh().intersect_with_mpi_region(rg);
300 if (mf_dataA) s = s * mf_dataA->get_qdim() / mf_dataA->nb_dof();
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);
307 if (mf_dataB) s = s * mf_dataB->get_qdim() / mf_dataB->nb_dof();
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);
407 const mesh_fem &mf_u = md.mesh_fem_of_variable(vl[0]);
408 const mesh_fem &mf_mult = md.mesh_fem_of_variable(vl[vl.size()-1]);
409 const mesh_im &mim = *mims[0];
410 const model_real_plain_vector *A = 0, *COEFF = 0;
411 const mesh_fem *mf_data = 0;
412 bool recompute_matrix = !((version & model::BUILD_ON_DATA_CHANGE) != 0)
413 || (penalized && md.is_var_newer_than_brick(dl[0], ib));
416 COEFF = &(md.real_variable(dl[0]));
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) {
423 A = &(md.real_variable(dl[ind]));
424 mf_data = md.pmesh_fem_of_variable(dl[ind]);
425 s = gmm::vect_size(*A);
426 if (mf_data) s = s * mf_data->get_qdim() / mf_data->nb_dof();
427 GMM_ASSERT1(s == mf_u.get_qdim() || s == mf_u.linked_mesh().dim(),
428 dl[ind] <<
": bad format of normal derivative Dirichlet "
429 "data. Detected dimension is " << s <<
" should be "
431 << mf_u.linked_mesh().dim());
434 mesh_region rg(region);
435 mim.linked_mesh().intersect_with_mpi_region(rg);
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]);
466 if (!R_must_be_derivated) {
467 if (s == mf_u.linked_mesh().dim())
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");
481 if (s == mf_u.linked_mesh().dim())
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);
519 const mesh_fem &mf_u = md.mesh_fem_of_variable(vl[0]);
520 const mesh_fem &mf_mult = md.mesh_fem_of_variable(vl[vl.size()-1]);
521 const mesh_im &mim = *mims[0];
522 const model_complex_plain_vector *A = 0, *COEFF = 0;
523 const mesh_fem *mf_data = 0;
524 bool recompute_matrix = !((version & model::BUILD_ON_DATA_CHANGE) != 0)
525 || (penalized && md.is_var_newer_than_brick(dl[0], ib));
528 COEFF = &(md.complex_variable(dl[0]));
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) {
535 A = &(md.complex_variable(dl[ind]));
536 mf_data = md.pmesh_fem_of_variable(dl[ind]);
537 s = gmm::vect_size(*A);
538 if (mf_data) s = s * mf_data->get_qdim() / mf_data->nb_dof();
539 GMM_ASSERT1(s == mf_u.get_qdim() || s == mf_u.linked_mesh().dim(),
540 dl[ind] <<
": bad format of normal derivative Dirichlet "
541 "data. Detected dimension is " << s <<
" should be "
543 << mf_u.linked_mesh().dim());
546 mesh_region rg(region);
547 mim.linked_mesh().intersect_with_mpi_region(rg);
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]);
578 if (!R_must_be_derivated) {
579 if (s == mf_u.linked_mesh().dim())
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");
593 if (s == mf_u.linked_mesh().dim())
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);