24 #include "getfem/getfem_contact_and_friction_large_sliding.h"
36 #define FRICTION_LAW 1
41 template <
typename VEC,
typename VEC2,
typename VECR>
42 void aug_friction(
const VEC &lambda, scalar_type g,
const VEC &Vs,
43 const VEC &n, scalar_type r,
const VEC2 &f, VECR &F) {
46 scalar_type lambdan_aug = gmm::neg(lambdan + r * g);
48 scalar_type tau = ((i >= 3) ? f[2] : scalar_type(0)) + f[0]*lambdan_aug;
49 if (i >= 2) tau = std::min(tau, f[1]);
51 if (tau > scalar_type(0)) {
52 gmm::add(lambda, gmm::scaled(Vs, -r), F);
56 if (norm > tau) gmm::scale(F, tau / norm);
59 gmm::add(gmm::scaled(n, -lambdan_aug/nn), F);
62 template <
typename VEC,
typename VEC2,
typename VECR,
typename MAT>
63 void aug_friction_grad(
const VEC &lambda, scalar_type g,
const VEC &Vs,
64 const VEC &n, scalar_type r,
const VEC2 &f, VECR &F,
65 MAT &dlambda, VECR &dg, MAT &dn, MAT &dVs) {
69 scalar_type lambdan_aug = gmm::neg(lambdan + r * g);
71 scalar_type tau = ((i >= 3) ? f[2] : scalar_type(0)) + f[0]*lambdan_aug;
72 if (i >= 2) tau = std::min(tau, f[1]);
75 if (tau > scalar_type(0)) {
76 gmm::add(lambda, gmm::scaled(Vs, -r), F);
81 gmm::scale(dn, -mu/nn);
82 gmm::rank_one_update(dn, gmm::scaled(n, mu/(nn*nn*nn)), n);
83 gmm::rank_one_update(dn, gmm::scaled(n, scalar_type(-1)/(nn*nn)), F);
85 gmm::rank_one_update(dVs, n, gmm::scaled(n, scalar_type(-1)/(nn*nn)));
88 gmm::rank_one_update(dVs, F,
89 gmm::scaled(F, scalar_type(-1)/(norm*norm)));
90 gmm::scale(dVs, tau / norm);
91 gmm::copy(gmm::scaled(F, scalar_type(1)/norm), dg);
92 gmm::rank_one_update(dn, gmm::scaled(F, mu/(norm*norm*nn)), F);
93 gmm::scale(dn, tau / norm);
94 gmm::scale(F, tau / norm);
102 if (norm > tau && ((i <= 1) || tau < f[1]) && ((i <= 2) || tau > f[2])) {
103 gmm::rank_one_update(dn, dg, gmm::scaled(lambda, -f[0]/nn));
104 gmm::rank_one_update(dn, dg, gmm::scaled(n, f[0]*lambdan/(nn*nn)));
105 gmm::rank_one_update(dlambda, dg, gmm::scaled(n, -f[0]/nn));
106 gmm::scale(dg, -f[0]*r);
108 if (lambdan_aug > scalar_type(0)) {
110 gmm::rank_one_update(dlambda, n, gmm::scaled(n, scalar_type(1)/(nn*nn)));
111 gmm::rank_one_update(dn, gmm::scaled(n, scalar_type(1)/(nn*nn)), lambda);
112 gmm::rank_one_update(dn,
113 gmm::scaled(n,(lambdan_aug-lambdan)/(nn*nn*nn)), n);
114 for (
size_type j = 0; j < N; ++j) dn(j,j) -= lambdan_aug/nn;
116 gmm::add(gmm::scaled(n, -lambdan_aug/nn), F);
121 #elif FRICTION_LAW == 2
123 template <
typename VEC,
typename VEC2,
typename VECR>
124 void aug_friction(
const VEC &lambda, scalar_type g,
const VEC &,
125 const VEC &n, scalar_type r,
const VEC2 &, VECR &F) {
128 scalar_type lambdan_aug = gmm::neg(lambdan + r * g);
129 gmm::copy(gmm::scaled(n, -lambdan_aug/nn), F);
132 template <
typename VEC,
typename VEC2,
typename VECR,
typename MAT>
133 void aug_friction_grad(
const VEC &lambda, scalar_type g,
const VEC &,
134 const VEC &n, scalar_type r,
const VEC2 &, VECR &F,
135 MAT &dlambda, VECR &dg, MAT &dn, MAT &dVs) {
139 scalar_type lambdan_aug = gmm::neg(lambdan + r * g);
146 if (lambdan_aug > scalar_type(0)) {
148 gmm::rank_one_update(dlambda, n, gmm::scaled(n, scalar_type(1)/(nn*nn)));
149 gmm::rank_one_update(dn, gmm::scaled(n, scalar_type(1)/(nn*nn)), lambda);
150 gmm::rank_one_update(dn,
151 gmm::scaled(n,(lambdan_aug-lambdan)/(nn*nn*nn)), n);
152 for (
size_type j = 0; j < N; ++j) dn(j,j) -= lambdan_aug/nn;
154 gmm::add(gmm::scaled(n, -lambdan_aug/nn), F);
161 #elif FRICTION_LAW == 3
163 template <
typename VEC,
typename VEC2,
typename VECR>
164 void aug_friction(
const VEC &lambda, scalar_type g,
const VEC &Vs,
165 const VEC &n, scalar_type r,
const VEC2 &f, VECR &F) {
166 gmm::copy(gmm::scaled(lambda, g*r*f[0]), F);
172 template <
typename VEC,
typename VEC2,
typename VECR,
typename MAT>
173 void aug_friction_grad(
const VEC &lambda, scalar_type g,
const VEC &Vs,
174 const VEC &n, scalar_type r,
const VEC2 &f, VECR &F,
175 MAT &dlambda, VECR &dg, MAT &dn, MAT &dVs) {
176 gmm::copy(gmm::scaled(lambda, g*r*f[0]), F);
186 #elif FRICTION_LAW == 4
188 template <
typename VEC,
typename VEC2,
typename VECR>
189 void aug_friction(
const VEC &lambda, scalar_type g,
const VEC &Vs,
190 const VEC &n, scalar_type r,
const VEC2 &f, VECR &F) {
191 gmm::copy(gmm::scaled(lambda, g*r*f[0]*n[0]*Vs[0]), F);
195 template <
typename VEC,
typename VEC2,
typename VECR,
typename MAT>
196 void aug_friction_grad(
const VEC &lambda, scalar_type g,
const VEC &Vs,
197 const VEC &n, scalar_type r,
const VEC2 &f, VECR &F,
198 MAT &dlambda, VECR &dg, MAT &dn, MAT &dVs) {
199 gmm::copy(gmm::scaled(lambda, g*r*f[0]*n[0]*Vs[0]), F);
204 gmm::copy(gmm::identity_matrix(), dlambda);
207 #elif FRICTION_LAW == 5
209 template <
typename VEC,
typename VEC2,
typename VECR>
210 void aug_friction(
const VEC &lambda, scalar_type g,
const VEC &Vs,
211 const VEC &n, scalar_type r,
const VEC2 &f, VECR &F) {
212 gmm::copy(gmm::scaled(lambda, g*r*f[0]*n[0]*Vs[0]), F);
216 template <
typename VEC,
typename VEC2,
typename VECR,
typename MAT>
217 void aug_friction_grad(
const VEC &lambda, scalar_type g,
const VEC &Vs,
218 const VEC &n, scalar_type r,
const VEC2 &f, VECR &F,
219 MAT &dlambda, VECR &dg, MAT &dn, MAT &dVs) {
220 gmm::copy(gmm::scaled(lambda, g*r*f[0]*n[0]*Vs[0]), F);
242 struct integral_large_sliding_contact_brick :
public virtual_brick {
244 multi_contact_frame &mcf;
248 virtual void asm_real_tangent_terms(
const model &md,
size_type ,
249 const model::varnamelist &vl,
250 const model::varnamelist &dl,
251 const model::mimlist &mims,
252 model::real_matlist &matl,
253 model::real_veclist &vecl,
254 model::real_veclist &,
256 build_version version)
const;
258 integral_large_sliding_contact_brick(multi_contact_frame &mcff,
260 : mcf(mcff), with_friction(with_fric) {
261 set_flags(
"Integral large sliding contact brick",
270 struct gauss_point_precomp {
272 fem_precomp_pool fppool;
273 const multi_contact_frame &mcf;
275 const multi_contact_frame::contact_pair *cp;
277 const base_node &x(
void)
const {
return cp->slave_point; }
278 const base_node &nx(
void)
const {
return cp->slave_n; }
279 const base_node &y(
void)
const {
return cp->master_point; }
280 const base_node &y_ref(
void)
const {
return cp->master_point_ref; }
281 const base_node &ny(
void)
const {
return cp->master_n; }
282 scalar_type g(
void)
const {
return cp->signed_dist; }
285 bool I_nxnx_computed;
286 const base_matrix &I_nxnx(
void) {
287 if (!I_nxnx_computed) {
288 gmm::copy(gmm::identity_matrix(), I_nxnx_);
289 gmm::rank_one_update(I_nxnx_, nx(), gmm::scaled(nx(),scalar_type(-1)));
290 I_nxnx_computed =
true;
296 bool I_nyny_computed;
297 const base_matrix &I_nyny(
void) {
298 if (!I_nyny_computed) {
299 gmm::copy(gmm::identity_matrix(), I_nyny_);
300 gmm::rank_one_update(I_nyny_, ny(), gmm::scaled(ny(),scalar_type(-1)));
301 I_nyny_computed =
true;
307 bool I_nxny_computed;
308 const base_matrix &I_nxny(
void) {
309 if (!I_nxny_computed) {
310 gmm::copy(gmm::identity_matrix(), I_nxny_);
311 gmm::rank_one_update(I_nxny_, nx(),
312 gmm::scaled(ny(),scalar_type(-1)/nxny));
313 I_nxny_computed =
true;
319 scalar_type nxdotny(
void)
const {
return nxny; }
322 bool isrigid(
void) {
return isrigid_; }
324 base_tensor base_ux, base_uy, base_lx, base_ly;
325 base_matrix vbase_ux_, vbase_uy_, vbase_lx_, vbase_ly_;
326 bool vbase_ux_init, vbase_uy_init, vbase_lx_init, vbase_ly_init;
327 base_tensor grad_base_ux, grad_base_uy, vgrad_base_ux_, vgrad_base_uy_;
328 bool vgrad_base_ux_init, vgrad_base_uy_init;
329 bool have_lx, have_ly;
331 fem_interpolation_context ctx_ux_, ctx_uy_, ctx_lx_, ctx_ly_;
332 bool ctx_ux_init, ctx_uy_init, ctx_lx_init, ctx_ly_init;
334 const mesh_fem *mf_ux_, *mf_uy_, *mf_lx_, *mf_ly_;
335 gmm::sub_interval I_ux_, I_uy_, I_lx_, I_ly_;
336 pfem pf_ux, pf_uy, pf_lx, pf_ly;
337 size_type ndof_ux_, qdim_ux, ndof_uy_, qdim_uy, ndof_lx_, qdim_lx;
338 size_type ndof_ly_, qdim_ly, cvx_, cvy_, ibx, iby;
342 pintegration_method pim;
345 scalar_type weight(
void) {
return weight_; }
347 const mesh &meshx(
void)
const {
return mf_ux_->linked_mesh(); }
348 const mesh &meshy(
void)
const {
return mf_uy_->linked_mesh(); }
349 const mesh_fem *mf_ux(
void)
const {
return mf_ux_; }
350 const mesh_fem *mf_uy(
void)
const {
return mf_uy_; }
351 const mesh_fem *mf_lx(
void)
const {
return mf_lx_; }
352 const mesh_fem *mf_ly(
void)
const {
return mf_ly_; }
353 size_type ndof_ux(
void)
const {
return ndof_ux_; }
354 size_type ndof_uy(
void)
const {
return ndof_uy_; }
355 size_type ndof_lx(
void)
const {
return ndof_lx_; }
356 size_type ndof_ly(
void)
const {
return ndof_ly_; }
357 size_type cvx(
void)
const {
return cvx_; }
358 size_type cvy(
void)
const {
return cvy_; }
359 const gmm::sub_interval I_ux(
void)
const {
return I_ux_; }
360 const gmm::sub_interval I_uy(
void)
const {
return I_uy_; }
361 const gmm::sub_interval I_lx(
void)
const {
return I_lx_; }
362 const gmm::sub_interval I_ly(
void)
const {
return I_ly_; }
365 fem_interpolation_context &ctx_ux(
void) {
367 bgeot::vectors_to_base_matrix(Gx, meshx().points_of_convex(cvx_));
369 = fppool(pf_ux, pim->approx_method()->pintegration_points());
370 ctx_ux_ = fem_interpolation_context(pgtx, pfp_ux, cp->slave_ind_pt,
377 fem_interpolation_context &ctx_lx(
void) {
378 GMM_ASSERT1(have_lx,
"No multiplier defined on the slave surface");
381 = fppool(pf_lx, pim->approx_method()->pintegration_points());
382 ctx_lx_ = fem_interpolation_context(pgtx, pfp_lx, cp->slave_ind_pt,
383 ctx_ux().G(), cvx_, fx);
389 fem_interpolation_context &ctx_uy(
void) {
390 GMM_ASSERT1(!isrigid(),
"Rigid obstacle master node: no fem defined");
392 bgeot::vectors_to_base_matrix(Gy, meshy().points_of_convex(cvy_));
393 ctx_uy_ = fem_interpolation_context(pgty, pf_uy, y_ref(), Gy, cvy_, fy);
399 fem_interpolation_context &ctx_ly(
void) {
400 GMM_ASSERT1(have_ly,
"No multiplier defined on the master surface");
402 ctx_ly_ = fem_interpolation_context(pgty, pf_ly, y_ref(),
403 ctx_uy().G(), cvy_, fy);
409 const base_matrix &vbase_ux(
void) {
410 if (!vbase_ux_init) {
411 ctx_ux().base_value(base_ux);
412 vectorize_base_tensor(base_ux, vbase_ux_, ndof_ux_, qdim_ux, N);
413 vbase_ux_init =
true;
418 const base_matrix &vbase_uy(
void) {
419 if (!vbase_uy_init) {
420 ctx_uy().base_value(base_uy);
421 vectorize_base_tensor(base_uy, vbase_uy_, ndof_uy_, qdim_uy, N);
422 vbase_uy_init =
true;
427 const base_matrix &vbase_lx(
void) {
428 if (!vbase_lx_init) {
429 ctx_lx().base_value(base_lx);
430 vectorize_base_tensor(base_lx, vbase_lx_, ndof_lx_, qdim_lx, N);
431 vbase_lx_init =
true;
436 const base_matrix &vbase_ly(
void) {
437 if (!vbase_ly_init) {
438 ctx_ly().base_value(base_ly);
439 vectorize_base_tensor(base_ly, vbase_ly_, ndof_ly_, qdim_ly, N);
440 vbase_ly_init =
true;
445 const base_tensor &vgrad_base_ux(
void) {
446 if (!vgrad_base_ux_init) {
447 ctx_ux().grad_base_value(grad_base_ux);
448 vectorize_grad_base_tensor(grad_base_ux, vgrad_base_ux_, ndof_ux_,
450 vgrad_base_ux_init =
true;
452 return vgrad_base_ux_;
455 const base_tensor &vgrad_base_uy(
void) {
456 if (!vgrad_base_uy_init) {
457 ctx_uy().grad_base_value(grad_base_uy);
458 vectorize_grad_base_tensor(grad_base_uy, vgrad_base_uy_, ndof_uy_,
460 vgrad_base_uy_init =
true;
462 return vgrad_base_uy_;
465 base_small_vector lambda_x_, lambda_y_;
466 bool lambda_x_init, lambda_y_init;
469 const base_small_vector &lx(
void) {
470 if (!lambda_x_init) {
471 pfem pf = ctx_lx().pf();
474 pf->interpolation(ctx_lx(), coeff, lambda_x_, dim_type(N));
475 lambda_x_init =
true;
480 const base_small_vector &ly(
void) {
481 if (!lambda_y_init) {
482 pfem pf = ctx_ly().pf();
485 pf->interpolation(ctx_ly(), coeff, lambda_y_, dim_type(N));
486 lambda_y_init =
true;
491 base_matrix grad_phix_, grad_phix_inv_, grad_phiy_, grad_phiy_inv_;
492 bool grad_phix_init, grad_phix_inv_init;
493 bool grad_phiy_init, grad_phiy_inv_init;
495 const base_matrix &grad_phix(
void) {
496 if (!grad_phix_init) {
497 pfem pf = ctx_ux().pf();
500 pf->interpolation_grad(ctx_ux(), coeff, grad_phix_, dim_type(N));
501 gmm::add(gmm::identity_matrix(), grad_phix_);
502 grad_phix_init =
true;
507 const base_matrix &grad_phix_inv(
void) {
508 if (!grad_phix_inv_init) {
512 grad_phix_inv_init =
true;
514 return grad_phix_inv_;
517 const base_matrix &grad_phiy(
void) {
518 if (!grad_phiy_init) {
519 pfem pf = ctx_uy().pf();
522 pf->interpolation_grad(ctx_uy(), coeff, grad_phiy_, dim_type(N));
523 gmm::add(gmm::identity_matrix(), grad_phiy_);
524 grad_phiy_init =
true;
529 const base_matrix &grad_phiy_inv(
void) {
530 if (!grad_phiy_inv_init) {
534 grad_phiy_inv_init =
true;
536 return grad_phiy_inv_;
540 base_small_vector x0_, y0_, nx0_, Vs_;
541 bool x0_init, y0_init, nx0_init, Vs_init;
542 base_matrix grad_phiy0_;
543 bool grad_phiy0_init;
545 const base_small_vector &x0(
void) {
547 const model_real_plain_vector &all_x0 = mcf.disp0_of_boundary(ibx);
549 pfem pf = ctx_ux().pf();
551 pf->interpolation(ctx_ux(), coeff, x0_, dim_type(N));
559 const base_small_vector &y0(
void) {
562 const model_real_plain_vector &all_y0 = mcf.disp0_of_boundary(iby);
564 pfem pf = ctx_uy().pf();
566 pf->interpolation(ctx_uy(), coeff, y0_, dim_type(N));
575 const base_small_vector &nx0(
void) {
577 const model_real_plain_vector &all_x0 = mcf.disp0_of_boundary(ibx);
579 pfem pf = ctx_ux().pf();
581 base_small_vector nx00_(N);
582 base_matrix grad_phix0_(N,N);
583 compute_normal(ctx_ux(), fx,
false, coeff, nx00_, nx0_, grad_phix0_);
591 const base_small_vector &Vs(
void) {
593 if (alpha != scalar_type(0)) {
594 #ifdef CONSIDER_FRAME_INDIFFERENCE
596 gmm::add(y0(), gmm::scaled(x0(), scalar_type(-1)), Vs_);
597 gmm::add(gmm::scaled(nx0(), -g()), Vs_);
601 gmm::add(x(), gmm::scaled(y(), scalar_type(-1)), Vs_);
602 gmm::add(gmm::scaled(x0(), scalar_type(-1)), Vs_);
605 gmm::scale(Vs_, alpha);
612 const base_matrix &grad_phiy0(
void) {
614 if (!grad_phiy0_init) {
615 const model_real_plain_vector &all_y0 = mcf.disp0_of_boundary(iby);
616 if (!isrigid() && all_y0.size()) {
617 pfem pf = ctx_uy().pf();
619 pf->interpolation_grad(ctx_uy(), coeff, grad_phiy0_, dim_type(N));
620 gmm::add(gmm::identity_matrix(), grad_phiy0_);
621 }
else gmm::copy(gmm::identity_matrix(), grad_phiy0_);
622 grad_phiy0_init =
true;
627 base_small_vector un;
629 void set_pair(
const multi_contact_frame::contact_pair &cp_) {
631 I_nxnx_computed = I_nyny_computed = I_nxny_computed =
false;
632 ctx_ux_init = ctx_uy_init = ctx_lx_init = ctx_ly_init =
false;
633 vbase_ux_init = vbase_uy_init = vbase_lx_init = vbase_ly_init =
false;
634 vgrad_base_ux_init = vgrad_base_uy_init =
false;
635 lambda_x_init = lambda_y_init =
false;
636 have_lx = have_ly =
false;
637 grad_phix_init = grad_phiy_init =
false;
638 grad_phix_inv_init = grad_phiy_inv_init =
false;
639 x0_init = y0_init = Vs_init = grad_phiy0_init =
false;
641 isrigid_ = (cp->irigid_obstacle !=
size_type(-1));
643 cvx_ = cp->slave_ind_element;
644 ibx = cp->slave_ind_boundary;
645 mf_ux_ = &(mcf.mfdisp_of_boundary(ibx));
646 pf_ux = mf_ux_->fem_of_element(cvx_);
647 qdim_ux = pf_ux->target_dim();
648 ndof_ux_ = pf_ux->nb_dof(cvx_) * N / qdim_ux;
649 fx = cp->slave_ind_face;
650 pgtx = meshx().trans_of_convex(cvx_);
651 mim = &(mcf.mim_of_boundary(ibx));
652 pim = mim->int_method_of_element(cvx_);
653 weight_ = pim->approx_method()->coeff(cp->slave_ind_pt) * ctx_ux().J();
654 gmm::mult(ctx_ux().B(), pgtx->normals()[fx], un);
656 const std::string &name_ux = mcf.varname_of_boundary(ibx);
657 I_ux_ = md.interval_of_variable(name_ux);
659 const std::string &name_lx = mcf.multname_of_boundary(ibx);
660 have_lx = (name_lx.size() > 0);
662 mf_lx_ = &(mcf.mfmult_of_boundary(ibx));
663 I_lx_ = md.interval_of_variable(name_lx);
664 pf_lx = mf_lx_->fem_of_element(cvx_);
665 qdim_lx = pf_lx->target_dim();
666 ndof_lx_ = pf_lx->nb_dof(cvx_) * N / qdim_lx;
670 cvy_ = cp->master_ind_element;
671 iby = cp->master_ind_boundary;
672 fy = cp->master_ind_face;
673 mf_uy_ = &(mcf.mfdisp_of_boundary(iby));
674 pf_uy = mf_uy_->fem_of_element(cvy_);
675 qdim_uy = pf_uy->target_dim();
676 ndof_uy_ = pf_uy->nb_dof(cvy_) * N / qdim_uy;
677 pgty = meshy().trans_of_convex(cvy_);
679 const std::string &name_uy = mcf.varname_of_boundary(iby);
680 I_uy_ = md.interval_of_variable(name_uy);
681 const std::string &name_ly = mcf.multname_of_boundary(iby);
682 have_ly = (name_ly.size() > 0);
684 mf_ly_ = &(mcf.mfmult_of_boundary(iby));
685 I_ly_ = md.interval_of_variable(name_ly);
686 pf_ly = mf_ly_->fem_of_element(cvy_);
687 qdim_ly = pf_ly->target_dim();
688 ndof_ly_ = pf_ly->nb_dof(cvy_) * N / qdim_ly;
693 gauss_point_precomp(
size_type N_,
const model &md_,
694 const multi_contact_frame &mcf_, scalar_type alpha_) :
695 N(N_), mcf(mcf_), md(md_),
696 I_nxnx_(N,N), I_nyny_(N,N), I_nxny_(N,N),
697 lambda_x_(N), lambda_y_(N),
698 grad_phix_(N, N), grad_phix_inv_(N, N),
699 grad_phiy_(N, N), grad_phiy_inv_(N, N),
alpha(alpha_),
700 x0_(N), y0_(N), nx0_(N), Vs_(N), grad_phiy0_(N, N), un(N) {}
778 void integral_large_sliding_contact_brick::asm_real_tangent_terms
779 (
const model &md,
size_type ,
const model::varnamelist &vl,
780 const model::varnamelist &dl,
const model::mimlist &,
781 model::real_matlist &matl, model::real_veclist &vecl,
783 build_version version)
const {
786 GMM_ASSERT1((with_friction && dl.size() >= 2 && dl.size() <= 3)
787 || (!with_friction && dl.size() >= 1 && dl.size() <= 2),
788 "Wrong number of data for integral large sliding contact brick");
790 GMM_ASSERT1(vl.size() == mcf.nb_variables() + mcf.nb_multipliers(),
791 "For the moment, it is not allowed to add boundaries to "
792 "the multi contact frame object after a model brick has "
795 const model_real_plain_vector &vr = md.real_variable(dl[0]);
796 GMM_ASSERT1(gmm::vect_size(vr) == 1,
"Large sliding contact "
797 "brick: parameter r should be a scalar");
798 scalar_type r = vr[0];
800 model_real_plain_vector f_coeff;
802 f_coeff = md.real_variable(dl[1]);
803 GMM_ASSERT1(gmm::vect_size(f_coeff) <= 3,
804 "Large sliding contact "
805 "brick: the friction law has less than 3 parameters");
807 if (gmm::vect_size(f_coeff) == 0)
808 { f_coeff.resize(1); f_coeff[0] = scalar_type(0); }
810 scalar_type
alpha(0);
812 if (dl.size() >= ind+1) {
813 GMM_ASSERT1(md.real_variable(dl[ind]).size() == 1,
814 "Large sliding contact "
815 "brick: parameter alpha should be a scalar");
816 alpha = md.real_variable(dl[ind])[0];
819 GMM_ASSERT1(matl.size() == 1,
820 "Large sliding contact brick should have only one term");
821 model_real_sparse_matrix &M = matl[0];
gmm::clear(M);
822 model_real_plain_vector &V = vecl[0];
gmm::clear(V);
824 mcf.set_raytrace(
true);
825 mcf.set_nodes_mode(0);
826 mcf.compute_contact_pairs();
830 base_matrix dlambdaF(N, N), dnF(N, N), dVsF(N, N);
831 base_small_vector F(N), dgF(N);
833 scalar_type FMULT = 1.;
836 for (
size_type i = 0; i < mcf.nb_boundaries(); ++i)
837 if (mcf.is_self_contact() || mcf.is_slave_boundary(i)) {
838 size_type region = mcf.region_of_boundary(i);
839 const std::string &name_lx = mcf.multname_of_boundary(i);
840 GMM_ASSERT1(name_lx.size() > 0,
"This brick need "
841 "multipliers defined on the multi_contact_frame object");
842 const mesh_fem &mflambda = mcf.mfmult_of_boundary(i);
843 const mesh_im &mim = mcf.mim_of_boundary(i);
844 const gmm::sub_interval &I = md.interval_of_variable(name_lx);
846 if (version & model::BUILD_MATRIX) {
847 model_real_sparse_matrix M1(mflambda.nb_dof(), mflambda.nb_dof());
849 gmm::add(gmm::scaled(M1, FMULT/r), gmm::sub_matrix(M, I, I));
852 if (version & model::BUILD_RHS) {
853 model_real_plain_vector V1(mflambda.nb_dof());
855 (V1, mim, mflambda, mflambda,
856 md.real_variable(mcf.multname_of_boundary(i)), region);
857 gmm::add(gmm::scaled(V1, -FMULT/r), gmm::sub_vector(V, I));
861 gauss_point_precomp gpp(N, md, mcf, alpha);
865 base_matrix auxNN1(N, N), auxNN2(N, N);
866 base_small_vector auxN1(N), auxN2(N);
869 for (
size_type icp = 0; icp < mcf.nb_contact_pairs(); ++icp) {
870 const multi_contact_frame::contact_pair &cp = mcf.get_contact_pair(icp);
872 const base_small_vector &nx = gpp.nx(), &ny = gpp.ny();
873 const mesh_fem *mf_ux = gpp.mf_ux(), *mf_lx = gpp.mf_lx(), *mf_uy(0);
874 size_type ndof_ux = gpp.ndof_ux(), ndof_uy(0), ndof_lx = gpp.ndof_lx();
876 const gmm::sub_interval &I_ux = gpp.I_ux(), &I_lx = gpp.I_lx();
877 gmm::sub_interval I_uy;
878 bool isrigid = gpp.isrigid();
880 ndof_uy = gpp.ndof_uy(); I_uy = gpp.I_uy();
881 mf_uy = gpp.mf_uy(); cvy = gpp.cvy();
883 scalar_type weight = gpp.weight(), g = gpp.g();
884 const base_small_vector &lambda = gpp.lx();
886 base_vector auxUX(ndof_ux), auxUY(ndof_uy);
888 if (version & model::BUILD_MATRIX) {
890 base_matrix auxUYN(ndof_uy, N);
891 base_matrix auxLXN1(ndof_lx, N), auxLXN2(ndof_lx, N);
893 aug_friction_grad(lambda, g, gpp.Vs(), nx, r, f_coeff, F, dlambdaF,
897 const base_tensor &vgrad_base_ux = gpp.vgrad_base_ux();
898 base_matrix graddeltaunx(ndof_ux, N);
902 graddeltaunx(i, j) += nx[k] * vgrad_base_ux(i, k, j);
904 #define CONSIDER_TERM1
905 #define CONSIDER_TERM2
906 #define CONSIDER_TERM3
909 #ifdef CONSIDER_TERM1
912 gmm::mult(gpp.vbase_ux(), gmm::transposed(gpp.vbase_lx()), Melem);
913 gmm::scale(Melem, -weight);
914 mat_elem_assembly(M, I_ux, I_lx, Melem, *mf_ux, cvx, *mf_lx, cvx);
917 #ifdef CONSIDER_TERM2
922 gmm::mult(gpp.vbase_uy(), gmm::transposed(gpp.vbase_lx()), Melem);
923 gmm::scale(Melem, weight);
924 mat_elem_assembly(M, I_uy, I_lx, Melem, *mf_uy, cvy, *mf_lx, cvx);
928 const base_tensor &vgrad_base_uy = gpp.vgrad_base_uy();
932 auxUYN(i, j) += lambda[k] * vgrad_base_uy(i, k, j);
933 base_matrix lgraddeltavgradphiyinv(ndof_uy, N);
934 gmm::mult(auxUYN, gpp.grad_phiy_inv(), lgraddeltavgradphiyinv);
938 gmm::mult(lgraddeltavgradphiyinv, gpp.I_nxny(), auxUYN);
939 gmm::mult(auxUYN, gmm::transposed(gpp.vbase_uy()), Melem);
941 gmm::scale(Melem, -weight);
942 mat_elem_assembly(M, I_uy, I_uy, Melem, *mf_uy, cvy, *mf_uy, cvy);
948 gmm::mult(auxUYN, gmm::transposed(gpp.vbase_ux()), Melem);
951 base_matrix auxUYUX(ndof_uy, ndof_ux);
952 gmm::mult(gpp.I_nxny(), gmm::transposed(gpp.grad_phix_inv()), auxNN1);
953 gmm::mult(lgraddeltavgradphiyinv, auxNN1, auxUYN);
954 gmm::mult(auxUYN, gmm::transposed(graddeltaunx), auxUYUX);
955 gmm::scale(auxUYUX, -g);
957 gmm::scale(Melem, weight);
958 mat_elem_assembly(M, I_uy, I_ux, Melem, *mf_uy, cvy, *mf_ux, cvx);
964 #ifdef CONSIDER_TERM3
970 gmm::copy(gmm::scaled(dlambdaF, scalar_type(-1)/r), auxNN1);
971 gmm::mult(gpp.vbase_lx(), auxNN1, auxLXN1);
972 gmm::mult(auxLXN1, gmm::transposed(gpp.vbase_lx()), Melem);
973 gmm::scale(Melem, weight*FMULT);
974 mat_elem_assembly(M, I_lx, I_lx, Melem, *mf_lx, cvx, *mf_lx, cvx);
980 gmm::mult(auxLXN1, gpp.I_nxnx(), auxLXN2);
981 gmm::mult(auxLXN2, gmm::transposed(gpp.grad_phix_inv()), auxLXN1);
982 gmm::mult(auxLXN1, gmm::transposed(graddeltaunx), Melem);
983 gmm::scale(Melem, scalar_type(1)/r);
987 base_vector deltamudgF(ndof_lx);
989 gmm::scaled(dgF, scalar_type(1)/(r*gpp.nxdotny())),
996 gmm::mult(gpp.I_nxnx(), gmm::scaled(ny, -g), auxN1);
997 gmm::mult(gpp.grad_phix_inv(), auxN1, auxN2);
999 gmm::rank_one_update(Melem, deltamudgF, auxUX);
1000 gmm::scale(Melem, weight*FMULT);
1001 mat_elem_assembly(M, I_lx, I_ux, Melem, *mf_lx, cvx, *mf_ux, cvx);
1008 gmm::rank_one_update(Melem, deltamudgF, auxUY);
1009 gmm::scale(Melem, -weight*FMULT);
1010 mat_elem_assembly(M, I_lx, I_uy, Melem, *mf_lx, cvx, *mf_uy, cvy);
1013 if (alpha != scalar_type(0)) {
1017 #ifdef CONSIDER_FRAME_INDIFFERENCE
1018 base_matrix gphiy0gphiyinv(N, N);
1019 gmm::mult(gpp.grad_phiy0(), gpp.grad_phiy_inv(), gphiy0gphiyinv);
1020 gmm::mult(gphiy0gphiyinv, gpp.I_nxny(), auxNN1);
1021 gmm::rank_one_update(auxNN1, gpp.nx0(),
1022 gmm::scaled(gpp.ny(),scalar_type(1)/gpp.nxdotny()));
1029 gmm::mult(gpp.vbase_lx(), gmm::transposed(auxNN2), auxLXN1);
1031 gmm::mult(auxLXN1, gmm::transposed(gpp.vbase_ux()), Melem);
1034 base_matrix auxLXUX(ndof_lx, ndof_ux);
1035 gmm::mult(auxNN2, gpp.I_nxnx(), auxNN1);
1036 gmm::mult(auxNN1, gmm::transposed(gpp.grad_phix_inv()), auxNN2);
1037 gmm::mult(gpp.vbase_lx(), gmm::transposed(auxNN2), auxLXN2);
1038 gmm::mult(auxLXN2, gmm::transposed(graddeltaunx), auxLXUX);
1039 gmm::scale(auxLXUX, -g);
1041 gmm::scale(Melem, -weight*alpha*FMULT/r);
1042 mat_elem_assembly(M, I_lx, I_ux, Melem, *mf_lx, cvx, *mf_ux, cvx);
1048 gmm::mult(auxLXN1, gmm::transposed(gpp.vbase_uy()), Melem);
1049 gmm::scale(Melem, weight*alpha*FMULT/r);
1050 mat_elem_assembly(M, I_lx, I_uy, Melem, *mf_lx, cvx, *mf_uy, cvy);
1052 base_matrix I_gphiy0gphiyinv(N, N);
1053 gmm::mult(gmm::scaled(gpp.grad_phiy0(), scalar_type(-1)),
1054 gpp.grad_phiy_inv(), I_gphiy0gphiyinv);
1055 gmm::add(gmm::identity_matrix(), I_gphiy0gphiyinv);
1060 gmm::mult(I_gphiy0gphiyinv, gpp.I_nxny(), auxNN1);
1061 for (
size_type j = 0; j < N; ++j) auxNN1(j,j) -= scalar_type(1);
1063 gmm::mult(gpp.vbase_lx(), gmm::transposed(auxNN2), auxLXN2);
1065 gmm::mult(auxLXN2, gmm::transposed(gpp.vbase_ux()), Melem);
1068 base_matrix auxLXUX(ndof_lx, ndof_ux);
1069 gmm::mult(dVsF, I_gphiy0gphiyinv, auxNN1);
1070 gmm::mult(auxNN1, gpp.I_nxny(), auxNN2);
1071 gmm::mult(auxNN2, gmm::transposed(gpp.grad_phix_inv()), auxNN1);
1072 gmm::mult(gpp.vbase_lx(), gmm::transposed(auxNN1), auxLXN1);
1073 gmm::mult(auxLXN1, gmm::transposed(graddeltaunx), auxLXUX);
1074 gmm::scale(auxLXUX, -g);
1076 gmm::scale(Melem, weight*alpha*FMULT/r);
1077 mat_elem_assembly(M, I_lx, I_ux, Melem, *mf_lx, cvx, *mf_ux, cvx);
1083 gmm::mult(auxLXN2, gmm::transposed(gpp.vbase_uy()), Melem);
1084 gmm::scale(Melem, -weight*alpha*FMULT/r);
1085 mat_elem_assembly(M, I_lx, I_uy, Melem, *mf_lx, cvx, *mf_uy, cvy);
1089 gmm::mult(gpp.vbase_lx(), gmm::transposed(dVsF), auxLXN1);
1090 gmm::mult(auxLXN1, gmm::transposed(gpp.vbase_ux()), Melem);
1091 gmm::scale(Melem, -weight*alpha*FMULT/r);
1092 mat_elem_assembly(M, I_lx, I_ux, Melem, *mf_lx, cvx, *mf_ux, cvx);
1098 if (version & model::BUILD_RHS) {
1100 if (!(version & model::BUILD_MATRIX))
1101 aug_friction(lambda, g, gpp.Vs(), nx, r, f_coeff, F);
1103 #ifdef CONSIDER_TERM1
1106 gmm::mult(gpp.vbase_ux(), lambda, auxUX);
1107 gmm::scale(auxUX, weight);
1108 vec_elem_assembly(V, I_ux, auxUX, *mf_ux, cvx);
1111 #ifdef CONSIDER_TERM2
1115 gmm::mult(gpp.vbase_uy(), lambda, auxUY);
1116 gmm::scale(auxUY, -weight);
1117 vec_elem_assembly(V, I_uy, auxUY, *mf_uy, cvy);
1121 #ifdef CONSIDER_TERM3
1125 base_vector auxLX(ndof_lx);
1126 gmm::mult(gpp.vbase_lx(), gmm::scaled(F, weight*FMULT/r), auxLX);
1127 vec_elem_assembly(V, I_lx, auxLX, *mf_lx, cvx);
1136 (
model &md, multi_contact_frame &mcf,
1137 const std::string &dataname_r,
const std::string &dataname_friction_coeff,
1138 const std::string &dataname_alpha) {
1140 bool with_friction = (dataname_friction_coeff.size() > 0);
1142 = std::make_shared<integral_large_sliding_contact_brick>(mcf,
1146 tl.push_back(model::term_description(
true,
false));
1148 model::varnamelist dl(1, dataname_r);
1149 if (with_friction) dl.push_back(dataname_friction_coeff);
1150 if (dataname_alpha.size()) dl.push_back(dataname_alpha);
1152 model::varnamelist vl;
1154 bool selfcontact = mcf.is_self_contact();
1156 dal::bit_vector uvar, mvar;
1157 for (
size_type i = 0; i < mcf.nb_boundaries(); ++i) {
1158 size_type ind_u = mcf.ind_varname_of_boundary(i);
1159 if (!(uvar.is_in(ind_u))) {
1160 vl.push_back(mcf.varname(ind_u));
1163 size_type ind_lambda = mcf.ind_multname_of_boundary(i);
1165 if (selfcontact || mcf.is_slave_boundary(i))
1166 GMM_ASSERT1(ind_lambda !=
size_type(-1),
"Large sliding contact "
1167 "brick: a multiplier should be associated to each slave "
1168 "boundary in the multi_contact_frame object.");
1169 if (ind_lambda !=
size_type(-1) && !(mvar.is_in(ind_lambda))) {
1170 vl.push_back(mcf.multname(ind_lambda));
1189 #if GETFEM_HAVE_MUPARSER_MUPARSER_H
1190 #include <muParser/muParser.h>
1191 #elif GETFEM_HAVE_MUPARSER_H
1192 #include <muParser.h>
1200 struct contact_frame {
1203 scalar_type friction_coef;
1204 std::vector<const model_real_plain_vector *> Us;
1205 std::vector<model_real_plain_vector> ext_Us;
1206 std::vector<const model_real_plain_vector *> lambdas;
1207 std::vector<model_real_plain_vector> ext_lambdas;
1208 struct contact_boundary {
1215 std::vector<contact_boundary> contact_boundaries;
1217 gmm::dense_matrix< model_real_sparse_matrix * > UU;
1218 gmm::dense_matrix< model_real_sparse_matrix * > UL;
1219 gmm::dense_matrix< model_real_sparse_matrix * > LU;
1220 gmm::dense_matrix< model_real_sparse_matrix * > LL;
1222 std::vector< model_real_plain_vector *> Urhs;
1223 std::vector< model_real_plain_vector *> Lrhs;
1227 std::vector<std::string> coordinates;
1229 #if GETFEM_HAVE_MUPARSER_MUPARSER_H || GETFEM_HAVE_MUPARSER_H
1230 std::vector<mu::Parser> obstacles_parsers;
1232 std::vector<std::string> obstacles;
1233 std::vector<std::string> obstacles_velocities;
1236 const model_real_plain_vector &U) {
1238 for (; i < Us.size(); ++i)
if (Us[i] == &U)
return i;
1241 mfu.extend_vector(U, ext_U);
1242 ext_Us.push_back(ext_U);
1247 const model_real_plain_vector &l) {
1249 for (; i < lambdas.size(); ++i)
if (lambdas[i] == &l)
return i;
1250 lambdas.push_back(&l);
1252 mfl.extend_vector(l, ext_l);
1253 ext_lambdas.push_back(ext_l);
1257 void extend_vectors(
void) {
1258 for (
size_type i = 0; i < contact_boundaries.size(); ++i) {
1259 size_type ind_U = contact_boundaries[i].ind_U;
1260 contact_boundaries[i].mfu->extend_vector(*(Us[ind_U]), ext_Us[ind_U]);
1261 size_type ind_lambda = contact_boundaries[i].ind_lambda;
1262 contact_boundaries[i].mflambda->extend_vector(*(lambdas[ind_lambda]),
1263 ext_lambdas[ind_lambda]);
1269 {
return *(contact_boundaries[n].mfu); }
1271 {
return *(contact_boundaries[n].mflambda); }
1272 const model_real_plain_vector &disp_of_boundary(
size_type n)
const
1273 {
return ext_Us[contact_boundaries[n].ind_U]; }
1274 const model_real_plain_vector &lambda_of_boundary(
size_type n)
const
1275 {
return ext_lambdas[contact_boundaries[n].ind_lambda]; }
1277 {
return contact_boundaries[n].region; }
1279 {
return *(UU(contact_boundaries[n].ind_U, contact_boundaries[m].ind_U)); }
1281 return *(LU(contact_boundaries[n].ind_lambda,
1282 contact_boundaries[m].ind_U));
1285 return *(UL(contact_boundaries[n].ind_U,
1286 contact_boundaries[m].ind_lambda));
1289 return *(LL(contact_boundaries[n].ind_lambda,
1290 contact_boundaries[m].ind_lambda));
1292 model_real_plain_vector &U_vector(
size_type n)
const
1293 {
return *(Urhs[contact_boundaries[n].ind_U]); }
1294 model_real_plain_vector &L_vector(
size_type n)
const
1295 {
return *(Lrhs[contact_boundaries[n].ind_lambda]); }
1297 contact_frame(
size_type NN) : N(NN), coordinates(N), pt_eval(N) {
1298 if (N > 0) coordinates[0] =
"x";
1299 if (N > 1) coordinates[1] =
"y";
1300 if (N > 2) coordinates[2] =
"z";
1301 if (N > 3) coordinates[3] =
"w";
1302 GMM_ASSERT1(N <= 4,
"Complete the definition for contact in "
1303 "dimension greater than 4");
1306 size_type add_obstacle(
const std::string &obs) {
1308 obstacles.push_back(obs);
1309 obstacles_velocities.push_back(
"");
1310 #if GETFEM_HAVE_MUPARSER_MUPARSER_H || GETFEM_HAVE_MUPARSER_H
1313 obstacles_parsers.push_back(mu);
1314 obstacles_parsers[ind].SetExpr(obstacles[ind]);
1316 obstacles_parsers[ind].DefineVar(coordinates[k], &pt_eval[k]);
1318 GMM_ASSERT1(
false,
"You have to link muparser with getfem to deal "
1319 "with rigid body obstacles");
1325 const model_real_plain_vector &U,
1327 const model_real_plain_vector &l,
1329 contact_boundary cb;
1333 cb.ind_U = add_U(mfu, U);
1334 cb.ind_lambda = add_lambda(mfl, l);
1335 size_type ind = contact_boundaries.size();
1336 contact_boundaries.push_back(cb);
1353 struct contact_elements {
1360 std::vector<size_type> boundary_of_elements;
1361 std::vector<size_type> ind_of_elements;
1362 std::vector<size_type> face_of_elements;
1363 std::vector<base_node> unit_normal_of_elements;
1365 contact_elements(contact_frame &ccf) : cf(ccf) {}
1367 bool add_point_contribution(
size_type boundary_num,
1370 scalar_type weight, scalar_type f_coeff,
1371 scalar_type r, model::build_version version);
1375 void contact_elements::init(
void) {
1376 fem_precomp_pool fppool;
1379 element_boxes.clear();
1380 unit_normal_of_elements.resize(0);
1381 boundary_of_elements.resize(0);
1382 ind_of_elements.resize(0);
1383 face_of_elements.resize(0);
1387 model_real_plain_vector coeff;
1388 cf.extend_vectors();
1389 for (
size_type i = 0; i < cf.contact_boundaries.size(); ++i) {
1390 size_type bnum = cf.region_of_boundary(i);
1391 const mesh_fem &mfu = cf.mfu_of_boundary(i);
1392 const model_real_plain_vector &U = cf.disp_of_boundary(i);
1393 const mesh &m = mfu.linked_mesh();
1394 if (i == 0) N = m.dim();
1395 GMM_ASSERT1(m.dim() == N,
1396 "Meshes are of mixed dimensions, cannot deal with that");
1397 base_node val(N), bmin(N), bmax(N), n0(N), n(N), n_mean(N);
1398 base_matrix grad(N,N);
1399 mesh_region region = m.region(bnum);
1400 GMM_ASSERT1(mfu.get_qdim() == N,
1401 "Wrong mesh_fem qdim to compute contact pairs");
1403 dal::bit_vector points_already_interpolated;
1404 std::vector<base_node> transformed_points(m.nb_max_points());
1408 pfem pf_s = mfu.fem_of_element(cv);
1411 bgeot::vectors_to_base_matrix
1412 (G, mfu.linked_mesh().points_of_convex(cv));
1414 pfem_precomp pfp = fppool(pf_s, &(pgt->geometric_nodes()));
1415 fem_interpolation_context ctx(pgt, pfp,
size_type(-1), G, cv);
1420 size_type ind = m.ind_points_of_convex(cv)[ip];
1423 if (!(points_already_interpolated.is_in(ind))) {
1425 pf_s->interpolation(ctx, coeff, val, dim_type(N));
1427 transformed_points[ind] = val;
1428 points_already_interpolated.add(ind);
1430 val = transformed_points[ind];
1433 bool is_on_face =
false;
1435 for (
size_type k = 0; k < cvs->nb_points_of_face(v.f()); ++k)
1436 if (cvs->ind_points_of_face(v.f())[k] == ip) is_on_face =
true;
1440 pf_s->interpolation_grad(ctx, coeff, grad, dim_type(N));
1441 gmm::add(gmm::identity_matrix(), grad);
1442 scalar_type J = bgeot::lu_inverse(&(*(grad.begin())), N);
1443 if (J <= scalar_type(0)) GMM_WARNING1(
"Inverted element ! " << J);
1444 gmm::mult(gmm::transposed(grad), n0, n);
1454 bmin[k] = std::min(bmin[k], val[k]);
1455 bmax[k] = std::max(bmax[k], val[k]);
1460 GMM_ASSERT1(nb_pt_on_face,
1461 "This element has not vertex on considered face !");
1465 scalar_type h = bmax[0] - bmin[0];
1467 h = std::max(h, bmax[k] - bmin[k]);
1469 { bmin[k] -= h; bmax[k] += h; }
1472 element_boxes.add_box(bmin, bmax, unit_normal_of_elements.size());
1474 unit_normal_of_elements.push_back(n_mean);
1475 boundary_of_elements.push_back(i);
1476 ind_of_elements.push_back(cv);
1477 face_of_elements.push_back(v.f());
1480 element_boxes.build_tree();
1485 bool contact_elements::add_point_contribution
1488 scalar_type , scalar_type r, model::build_version version) {
1489 const mesh_fem &mfu = cf.mfu_of_boundary(boundary_num);
1490 const mesh_fem &mfl = cf.mflambda_of_boundary(boundary_num);
1491 const model_real_plain_vector &U = cf.disp_of_boundary(boundary_num);
1492 const model_real_plain_vector &L = cf.lambda_of_boundary(boundary_num);
1494 base_node x0 = ctxu.
xreal();
1505 base_small_vector n(N), val(N), h(N);
1506 base_matrix gradinv(N,N), grad(N,N), gradtot(N,N), G;
1507 size_type cvnbdofu = mfu.nb_basic_dof_of_element(cv);
1508 size_type cvnbdofl = mfl.nb_basic_dof_of_element(cv);
1509 base_vector coeff(cvnbdofu);
1511 ctxu.
pf()->interpolation(ctxu, coeff, val, dim_type(N));
1512 base_node x = x0 + val;
1514 ctxu.
pf()->interpolation_grad(ctxu, coeff, gradinv, dim_type(N));
1515 gmm::add(gmm::identity_matrix(), gradinv);
1516 scalar_type J = bgeot::lu_inverse(&(*(grad_inv.begin())), N);
1517 if (J <= scalar_type(0)) {
1518 GMM_WARNING1(
"Inverted element !");
1520 GMM_ASSERT1(!(version & model::BUILD_MATRIX),
"Impossible to build "
1521 "tangent matrix for large sliding contact");
1522 if (version & model::BUILD_RHS) {
1523 base_vector Velem(cvnbdofl);
1524 for (
size_type i = 0; i < cvnbdofl; ++i) Velem[i] = 1E200;
1525 vec_elem_assembly(cf.L_vector(boundary_num), Velem, mfl, cv);
1530 gmm::mult(gmm::transposed(gradinv), n0, n);
1537 bgeot::rtree::pbox_set bset;
1538 element_boxes.find_boxes_at_point(x, bset);
1540 if (noisy) cout <<
"Number of boxes found : " << bset.size() << endl;
1547 bgeot::rtree::pbox_set::iterator it = bset.begin(), itnext;
1548 for (; it != bset.end(); it = itnext) {
1549 itnext = it; ++itnext;
1550 if (gmm::vect_sp(unit_normal_of_elements[(*it)->id], n)
1551 >= -scalar_type(1)/scalar_type(20)) bset.erase(it);
1555 cout <<
"Number of boxes satisfying the unit normal criterion : "
1556 << bset.size() << endl;
1566 std::vector<base_node> y0s;
1567 std::vector<base_small_vector> n0_y0s;
1568 std::vector<scalar_type> d0s;
1569 std::vector<scalar_type> d1s;
1570 std::vector<size_type> elt_nums;
1571 std::vector<fem_interpolation_context> ctx_y0s;
1572 for (; it != bset.end(); ++it) {
1573 size_type boundary_num_y0 = boundary_of_elements[(*it)->id];
1574 size_type cv_y0 = ind_of_elements[(*it)->id];
1576 const mesh_fem &mfu_y0 = cf.mfu_of_boundary(boundary_num_y0);
1577 pfem pf_s_y0 = mfu_y0.fem_of_element(cv_y0);
1578 const model_real_plain_vector &U_y0
1579 = cf.disp_of_boundary(boundary_num_y0);
1580 const mesh &m_y0 = mfu_y0.linked_mesh();
1587 for (; ind_dep_point < cvs_y0->nb_points(); ++ind_dep_point) {
1588 bool is_on_face =
false;
1590 k < cvs_y0->nb_points_of_face(face_y0); ++k)
1591 if (cvs_y0->ind_points_of_face(face_y0)[k]
1592 == ind_dep_point) is_on_face =
true;
1593 if (!is_on_face)
break;
1595 GMM_ASSERT1(ind_dep_point < cvs_y0->nb_points(),
1596 "No interior point found !");
1598 base_node y0_ref = pgt_y0->convex_ref()->points()[ind_dep_point];
1602 bgeot::vectors_to_base_matrix(G, m_y0.points_of_convex(cv_y0));
1604 fem_interpolation_context ctx_y0(pgt_y0, pf_s_y0, y0_ref, G, cv_y0);
1609 pf_s_y0->interpolation(ctx_y0, coeff, val, dim_type(N));
1610 val += ctx_y0.xreal() - x;
1613 if (init_res < 1E-12)
break;
1614 if (newton_iter > 100) {
1615 GMM_WARNING1(
"Newton has failed to invert transformation");
1616 GMM_ASSERT1(!(version & model::BUILD_MATRIX),
"Impossible to build "
1617 "tangent matrix for large sliding contact");
1618 if (version & model::BUILD_RHS) {
1619 base_vector Velem(cvnbdofl);
1620 for (
size_type i = 0; i < cvnbdofl; ++i) Velem[i] = 1E200;
1621 vec_elem_assembly(cf.L_vector(boundary_num), Velem, mfl, cv);
1626 pf_s_y0->interpolation_grad(ctx_y0, coeff, grad, dim_type(N));
1627 gmm::add(gmm::identity_matrix(), grad);
1630 std::vector<long> ipvt(N);
1632 GMM_ASSERT1(!info,
"Singular system, pivot = " << info);
1638 for (alpha = 1;
alpha >= 1E-5;
alpha/=scalar_type(2)) {
1640 ctx_y0.set_xref(y0_ref - alpha*h);
1641 pf_s_y0->interpolation(ctx_y0, coeff, val, dim_type(N));
1642 val += ctx_y0.xreal() - x;
1644 if (gmm::vect_norm2(val) < init_res) { ok =
true;
break; }
1647 GMM_WARNING1(
"Line search has failed to invert transformation");
1649 ctx_y0.set_xref(y0_ref);
1653 base_node y0 = ctx_y0.xreal();
1655 scalar_type d0_ref = pgt_y0->convex_ref()->is_in_face(face_y0, y0_ref);
1659 scalar_type d1 = d0_ref;
1662 for (
short_type k = 0; k < pgt_y0->structure()->nb_faces(); ++k) {
1663 scalar_type dd = pgt_y0->convex_ref()->is_in_face(k, y0_ref);
1664 if (dd > scalar_type(0) && dd > gmm::abs(d1)) { d1 = dd; ifd = k; }
1669 if (gmm::abs(d1) < gmm::abs(d0)) d1 = d0;
1676 if (noisy) cout <<
"gmm::vect_norm2(n0_y0) = " <<
gmm::vect_norm2(n0_y0) << endl;
1678 if (noisy) cout <<
"autocontact status : x0 = " << x0 <<
" y0 = " << y0 <<
" " <<
gmm::vect_dist2(y0, x0) <<
" : " << d0*0.75 <<
" : " << d1*0.75 << endl;
1679 if (noisy) cout <<
"n = " << n <<
" unit_normal_of_elements[(*it)->id] = " << unit_normal_of_elements[(*it)->id] << endl;
1681 if (d0 < scalar_type(0)
1683 && (gmm::vect_dist2(y0, x0) < gmm::abs(d1)*scalar_type(3)/scalar_type(4)))
1684 || gmm::abs(d1) > 0.05)) {
1685 if (noisy) cout <<
"Eliminated x0 = " << x0 <<
" y0 = " << y0
1686 <<
" d0 = " << d0 << endl;
1698 y0s.push_back(ctx_y0.xreal());
1699 elt_nums.push_back((*it)->id);
1702 ctx_y0s.push_back(ctx_y0);
1704 n0_y0s.push_back(n0_y0);
1706 if (noisy) cout <<
"dist0 = " << d0 <<
" dist0 * area = "
1707 << pgt_y0->convex_ref()->is_in(y0_ref) << endl;
1716 scalar_type d0 = 1E100, d1 = 1E100;
1717 base_small_vector grad_obs(N);
1720 for (
size_type k = 0; k < y0s.size(); ++k)
1721 if (d1s[k] < d1) { d0 = d0s[k]; d1 = d1s[k]; ibound = k; state = 1; }
1725 #if GETFEM_HAVE_MUPARSER_MUPARSER_H || GETFEM_HAVE_MUPARSER_H
1727 for (
size_type i = 0; i < cf.obstacles.size(); ++i) {
1728 scalar_type d0_o = scalar_type(cf.obstacles_parsers[i].Eval());
1729 if (d0_o < d0) { d0 = d0_o; irigid_obstacle = i; state = 2; }
1732 scalar_type EPS = face_factor * 1E-9;
1734 cf.pt_eval[k] += EPS;
1736 (scalar_type(cf.obstacles_parsers[irigid_obstacle].Eval())-d0)/EPS;
1737 cf.pt_eval[k] -= EPS;
1742 if (cf.obstacles.size() > 0)
1743 GMM_WARNING1(
"Rigid obstacles are ignored. Recompile with "
1744 "muParser to account for rigid obstacles");
1753 if (noisy && state == 1) {
1754 cout <<
"Point : " << x0 <<
" of boundary " << boundary_num
1755 <<
" and element " << cv <<
" state = " << int(state);
1756 if (version & model::BUILD_RHS) cout <<
" RHS";
1757 if (version & model::BUILD_MATRIX) cout <<
" MATRIX";
1760 size_type boundary_num_y0 = boundary_of_elements[elt_nums[ibound]];
1761 const mesh_fem &mfu_y0 = cf.mfu_of_boundary(boundary_num_y0);
1762 const mesh &m_y0 = mfu_y0.linked_mesh();
1763 size_type cv_y0 = ind_of_elements[elt_nums[ibound]];
1765 if (noisy) cout <<
" y0 = " << y0s[ibound] <<
" of element "
1766 << cv_y0 <<
" of boundary " << boundary_num_y0 << endl;
1767 for (
size_type k = 0; k < m_y0.nb_points_of_convex(cv_y0); ++k)
1768 if (noisy) cout <<
"point " << k <<
" : "
1769 << m_y0.points()[m_y0.ind_points_of_convex(cv_y0)[k]] << endl;
1770 if (boundary_num_y0 == 0 && boundary_num == 0 && d0 < 0.0 && (version & model::BUILD_MATRIX)) GMM_ASSERT1(
false,
"oups");
1772 if (noisy) cout <<
" d0 = " << d0 << endl;
1778 GMM_ASSERT1(ctxu.
pf()->target_dim() == 1 && ctxl.
pf()->target_dim() == 1,
1779 "Large sliding contact assembly procedure has to be adapted "
1780 "to intrinsic vectorial elements. To be done.");
1792 base_small_vector lambda(N);
1794 ctxl.
pf()->interpolation(ctxl, coeff, lambda, dim_type(N));
1795 GMM_ASSERT1(!(isnan(lambda[0])),
"internal error");
1800 scalar_type aux1, aux2;
1805 base_small_vector zeta(N);
1806 gmm::add(lambda, gmm::scaled(n, r*d0), zeta);
1813 size_type boundary_num_y0 = 0, cv_y0 = 0, cvnbdofu_y0 = 0;
1815 ctx_y0s[ibound].base_value(tu_y0);
1816 boundary_num_y0 = boundary_of_elements[elt_nums[ibound]];
1817 cv_y0 = ind_of_elements[elt_nums[ibound]];
1818 cvnbdofu_y0 = cf.mfu_of_boundary(boundary_num_y0).nb_basic_dof_of_element(cv_y0);
1820 const mesh_fem &mfu_y0 = (state == 1) ?
1821 cf.mfu_of_boundary(boundary_num_y0) : mfu;
1823 if (version & model::BUILD_RHS) {
1828 base_small_vector vecaux(N);
1830 De_Saxce_projection(vecaux, n, scalar_type(0));
1831 gmm::scale(vecaux, -scalar_type(1));
1833 for (
size_type i = 0; i < cvnbdofl; ++i)
1834 Velem[i] = tl[i/N] * vecaux[i%N] * weight/r;
1835 vec_elem_assembly(cf.L_vector(boundary_num), Velem, mfl, cv);
1839 for (
size_type i = 0; i < cvnbdofu; ++i)
1840 Velem[i] = tu[i/N] * lambda[i%N] * weight;
1841 vec_elem_assembly(cf.U_vector(boundary_num), Velem, mfu, cv);
1845 for (
size_type i = 0; i < cvnbdofu_y0; ++i)
1846 Velem[i] = -tu_y0[i/N] * lambda[i%N] * weight;
1847 vec_elem_assembly(cf.U_vector(boundary_num_y0), Velem, mfu_y0, cv_y0);
1851 if (version & model::BUILD_MATRIX) {
1853 base_small_vector gradinv_n(N);
1857 base_matrix pgrad(N,N), pgradn(N,N);
1858 De_Saxce_projection_grad(zeta, n, scalar_type(0), pgrad);
1859 De_Saxce_projection_gradn(zeta, n, scalar_type(0), pgradn);
1861 base_small_vector pgrad_n(N), pgradn_n(N);
1864 base_matrix gradinv_pgrad(N,N), gradinv_pgradn(N,N);
1865 gmm::mult(gradinv, gmm::transposed(pgrad), gradinv_pgrad);
1866 gmm::mult(gradinv, gmm::transposed(pgradn), gradinv_pgradn);
1871 for (
size_type i = 0; i < cvnbdofl; i += N) {
1872 aux1 = -tl[i/N] * weight/r;
1873 for (
size_type j = 0; j < cvnbdofl; j += N) {
1874 aux2 = aux1 * tl[j/N];
1875 for (
size_type k = 0; k < N; k++) Melem(i+k,j+k) = aux2;
1879 for (
size_type i = 0, ii = 0; i < cvnbdofl; ++i, ii = i%N)
1880 for (
size_type j = 0, jj = 0; j < cvnbdofl; ++j, jj = j%N)
1881 Melem(i,j) += tl[i/N] * tl[j/N] * pgrad(ii,jj) * weight/r;
1882 mat_elem_assembly(cf.LL_matrix(boundary_num, boundary_num),
1883 Melem, mfl, cv, mfl, cv);
1888 for (
size_type i = 0; i < cvnbdofu; i += N) {
1889 aux1 = -tu[i/N] * weight;
1890 for (
size_type j = 0; j < cvnbdofl; j += N) {
1891 aux2 = aux1 * tl[j/N];
1892 for (
size_type k = 0; k < N; k++) Melem(i+k,j+k) = aux2;
1895 mat_elem_assembly(cf.UL_matrix(boundary_num, boundary_num),
1896 Melem, mfu, cv, mfl, cv);
1902 for (
size_type i = 0, ii = 0; i < cvnbdofl; ++i, ii = i%N)
1903 for (
size_type j = 0, jj = 0; j < cvnbdofu; ++j, jj = j%N) {
1904 aux1 = aux2 = scalar_type(0);
1906 aux1 += tgradu[j/N+N*k] * gradinv_n[k];
1907 aux2 += tgradu[j/N+N*k] * gradinv_pgrad(k,ii);
1909 Melem(i,j) = d0 * tl[i/N] * (pgrad_n[ii] * aux1 - aux2) * n[jj] * weight;
1915 for (
size_type i = 0, ii = 0; i < cvnbdofl; ++i, ii = i%N)
1916 for (
size_type j = 0, jj = 0; j < cvnbdofu; ++j, jj = j%N) {
1917 aux1 = aux2 = scalar_type(0);
1919 aux1 += tgradu[j/N+N*k] * gradinv_n[k];
1920 aux2 += tgradu[j/N+N*k] * gradinv_pgradn(k,ii);
1922 Melem(i,j) += tl[i/N] * (pgradn_n[ii] * aux1 - aux2) * n[jj] * weight / r;
1924 mat_elem_assembly(cf.LU_matrix(boundary_num, boundary_num),
1925 Melem, mfl, cv, mfu, cv);
1930 base_tensor tgradu_y0;
1931 ctx_y0s[ibound].grad_base_value(tgradu_y0);
1933 base_matrix gradinv_y0(N,N);
1934 base_small_vector ntilde_y0(N);
1936 base_matrix grad_y0(N,N);
1937 base_vector coeff_y0(cvnbdofu_y0);
1938 const model_real_plain_vector &U_y0
1939 = cf.disp_of_boundary(boundary_num_y0);
1941 ctx_y0s[ibound].pf()->interpolation_grad(ctx_y0s[ibound], coeff_y0,
1942 grad_y0, dim_type(N));
1943 gmm::add(gmm::identity_matrix(), grad_y0);
1947 gmm::mult(gmm::transposed(gradinv_y0), n0_y0s[ibound], ntilde_y0);
1952 for (
size_type i = 0; i < cvnbdofu_y0; i += N) {
1953 aux1 = tu_y0[i/N] * weight;
1954 for (
size_type j = 0; j < cvnbdofl; j += N) {
1955 aux2 = aux1 * tl[j/N];
1956 for (
size_type k = 0; k < N; k++) Melem(i+k,j+k) = aux2;
1959 mat_elem_assembly(cf.UL_matrix(boundary_num_y0, boundary_num),
1960 Melem, mfu_y0, cv_y0, mfl, cv);
1968 for (
size_type i = 0, ii = 0; i < cvnbdofu_y0; ++i, ii = i%N)
1969 for (
size_type j = 0, jj = 0; j < cvnbdofu; ++j, jj = j%N) {
1970 aux1 = scalar_type(0);
1972 aux1 += tgradu_y0[i/N+N*k]* gradinv_y0(k,jj);
1973 Melem(i,j) = lambda[ii] * aux1 * tu[j/N] * weight;
1975 mat_elem_assembly(cf.UU_matrix(boundary_num_y0, boundary_num),
1976 Melem, mfu_y0, cv_y0, mfu, cv);
1981 for (
size_type i = 0, ii = 0; i < cvnbdofu_y0; ++i, ii = i%N)
1982 for (
size_type j = 0, jj = 0; j < cvnbdofu_y0; ++j, jj = j%N) {
1983 aux1 = scalar_type(0);
1985 aux1 += tgradu_y0[i/N+N*k] * gradinv_y0(k,jj);
1986 Melem(i,j) = - lambda[ii] * aux1 * tu_y0[j/N] * weight;
1988 mat_elem_assembly(cf.UU_matrix(boundary_num_y0, boundary_num_y0),
1989 Melem, mfu_y0, cv_y0, mfu_y0, cv_y0);
1994 for (
size_type i = 0; i < cvnbdofl; ++i) {
1995 aux1 = tl[i/N] * pgrad_n[i%N] * weight;
1996 for (
size_type j = 0; j < cvnbdofu_y0; ++j)
1997 Melem(i,j) = - aux1 * tu_y0[j/N] * ntilde_y0[j%N];
1999 mat_elem_assembly(cf.LU_matrix(boundary_num, boundary_num_y0),
2000 Melem, mfl, cv, mfu_y0, cv_y0);
2005 for (
size_type i = 0; i < cvnbdofl; ++i) {
2006 aux1 = tl[i/N] * pgrad_n[i%N] * weight;
2007 for (
size_type j = 0; j < cvnbdofu; ++j)
2008 Melem(i,j) = aux1 * tu[j/N] * ntilde_y0[j%N];
2015 for (
size_type i = 0; i < cvnbdofl; ++i) {
2016 aux1 = tl[i/N] * pgrad_n[i%N] * weight;
2017 for (
size_type j = 0; j < cvnbdofu; ++j)
2018 Melem(i,j) = aux1 * tu[j/N] * grad_obs[j%N];
2021 mat_elem_assembly(cf.LU_matrix(boundary_num, boundary_num),
2022 Melem, mfl, cv, mfu, cv);
2029 if (version & model::BUILD_RHS) {
2031 for (
size_type i = 0; i < cvnbdofl; ++i)
2032 Velem[i] = tl[i/N] * lambda[i%N] * weight/r;
2033 vec_elem_assembly(cf.L_vector(boundary_num), Velem, mfl, cv);
2037 if (version & model::BUILD_MATRIX) {
2039 for (
size_type i = 0; i < cvnbdofl; i += N) {
2040 aux1 = -tl[i/N] * weight/r;
2041 for (
size_type j = 0; j < cvnbdofl; j += N) {
2042 aux2 = aux1 * tl[j/N];
2043 for (
size_type k = 0; k < N; k++) Melem(i+k,j+k) = aux2;
2046 mat_elem_assembly(cf.LL_matrix(boundary_num, boundary_num),
2047 Melem, mfl, cv, mfl, cv);
2058 struct integral_large_sliding_contact_brick_field_extension :
public virtual_brick {
2061 struct contact_boundary {
2063 std::string varname;
2064 std::string multname;
2068 std::vector<contact_boundary> boundaries;
2069 std::vector<std::string> obstacles;
2071 void add_boundary(
const std::string &varn,
const std::string &multn,
2073 contact_boundary cb;
2074 cb.region = region; cb.varname = varn; cb.multname = multn; cb.mim=&mim;
2075 boundaries.push_back(cb);
2078 void add_obstacle(
const std::string &obs)
2079 { obstacles.push_back(obs); }
2081 void build_contact_frame(
const model &md, contact_frame &cf)
const {
2082 for (
size_type i = 0; i < boundaries.size(); ++i) {
2083 const contact_boundary &cb = boundaries[i];
2084 cf.add_boundary(md.mesh_fem_of_variable(cb.varname),
2085 md.real_variable(cb.varname),
2086 md.mesh_fem_of_variable(cb.multname),
2087 md.real_variable(cb.multname), cb.region);
2089 for (
size_type i = 0; i < obstacles.size(); ++i)
2090 cf.add_obstacle(obstacles[i]);
2094 virtual void asm_real_tangent_terms(
const model &md,
size_type ,
2095 const model::varnamelist &vl,
2096 const model::varnamelist &dl,
2097 const model::mimlist &mims,
2098 model::real_matlist &matl,
2099 model::real_veclist &vecl,
2100 model::real_veclist &,
2102 build_version version)
const;
2104 integral_large_sliding_contact_brick_field_extension() {
2105 set_flags(
"Integral large sliding contact brick",
2116 void integral_large_sliding_contact_brick_field_extension::asm_real_tangent_terms
2117 (
const model &md,
size_type ,
const model::varnamelist &vl,
2118 const model::varnamelist &dl,
const model::mimlist &,
2119 model::real_matlist &matl, model::real_veclist &vecl,
2121 build_version version)
const {
2123 fem_precomp_pool fppool;
2125 size_type N = md.mesh_fem_of_variable(vl[0]).linked_mesh().dim();
2126 contact_frame cf(N);
2127 build_contact_frame(md, cf);
2129 size_type Nvar = vl.size(), Nu = cf.Urhs.size(), Nl = cf.Lrhs.size();
2130 GMM_ASSERT1(Nvar == Nu+Nl,
"Wrong size of variable list for integral "
2131 "large sliding contact brick");
2132 GMM_ASSERT1(matl.size() == Nvar*Nvar,
"Wrong size of terms for "
2133 "integral large sliding contact brick");
2135 if (version & model::BUILD_MATRIX) {
2139 if (i < Nu && j < Nu) cf.UU(i,j) = &(matl[i*Nvar+j]);
2140 if (i >= Nu && j < Nu) cf.LU(i-Nu,j) = &(matl[i*Nvar+j]);
2141 if (i < Nu && j >= Nu) cf.UL(i,j-Nu) = &(matl[i*Nvar+j]);
2142 if (i >= Nu && j >= Nu) cf.LL(i-Nu,j-Nu) = &(matl[i*Nvar+j]);
2145 if (version & model::BUILD_RHS) {
2146 for (
size_type i = 0; i < vl.size(); ++i) {
2147 if (i < Nu) cf.Urhs[i] = &(vecl[i*Nvar]);
2148 else cf.Lrhs[i-Nu] = &(vecl[i*Nvar]);
2153 GMM_ASSERT1(dl.size() == 2,
"Wrong number of data for integral large "
2154 "sliding contact brick");
2156 const model_real_plain_vector &vr = md.real_variable(dl[0]);
2157 GMM_ASSERT1(gmm::vect_size(vr) == 1,
"Parameter r should be a scalar");
2159 const model_real_plain_vector &f_coeff = md.real_variable(dl[1]);
2160 GMM_ASSERT1(gmm::vect_size(f_coeff) == 1,
2161 "Friction coefficient should be a scalar");
2163 contact_elements ce(cf);
2166 for (
size_type bnum = 0; bnum < boundaries.size(); ++bnum) {
2167 mesh_region rg(boundaries[bnum].region);
2168 const mesh_fem &mfu=md.mesh_fem_of_variable(boundaries[bnum].varname);
2169 const mesh_fem &mfl=md.mesh_fem_of_variable(boundaries[bnum].multname);
2170 const mesh_im &mim = *(boundaries[bnum].mim);
2171 const mesh &m = mfu.linked_mesh();
2172 mfu.linked_mesh().intersect_with_mpi_region(rg);
2178 pfem pf_s = mfu.fem_of_element(cv);
2179 pfem pf_sl = mfl.fem_of_element(cv);
2180 pintegration_method pim = mim.int_method_of_element(cv);
2181 bgeot::vectors_to_base_matrix(G, m.points_of_convex(cv));
2184 = fppool(pf_s, pim->approx_method()->pintegration_points());
2186 = fppool(pf_sl, pim->approx_method()->pintegration_points());
2187 fem_interpolation_context ctxu(pgt, pfpu,
size_type(-1), G, cv, v.f());
2188 fem_interpolation_context ctxl(pgt, pfpl,
size_type(-1), G, cv, v.f());
2191 k < pim->approx_method()->nb_points_on_face(v.f()); ++k) {
2193 = pim->approx_method()->ind_first_point_on_face(v.f()) + k;
2196 if (!(ce.add_point_contribution
2197 (bnum, ctxu, ctxl,pim->approx_method()->coeff(ind),
2198 f_coeff[0], vr[0], version)))
return;
2208 size_type add_integral_large_sliding_contact_brick_field_extension
2209 (model &md,
const mesh_im &mim,
const std::string &varname_u,
2210 const std::string &multname,
const std::string &dataname_r,
2211 const std::string &dataname_friction_coeff,
size_type region) {
2214 =std::make_shared<integral_large_sliding_contact_brick_field_extension>();
2216 pbr->add_boundary(varname_u, multname, mim, region);
2219 tl.push_back(model::term_description(varname_u, varname_u,
false));
2220 tl.push_back(model::term_description(varname_u, multname,
false));
2221 tl.push_back(model::term_description(multname, varname_u,
false));
2222 tl.push_back(model::term_description(multname, multname,
false));
2224 model::varnamelist dl(1, dataname_r);
2225 dl.push_back(dataname_friction_coeff);
2227 model::varnamelist vl(1, varname_u);
2228 vl.push_back(multname);
2230 return md.add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region);
2234 void add_boundary_to_large_sliding_contact_brick
2235 (model &md,
size_type indbrick,
const mesh_im &mim,
2236 const std::string &varname_u,
const std::string &multname,
2238 dim_type N = md.mesh_fem_of_variable(varname_u).linked_mesh().dim();
2239 pbrick pbr = md.brick_pointer(indbrick);
2240 md.touch_brick(indbrick);
2241 integral_large_sliding_contact_brick_field_extension *p
2242 =
dynamic_cast<integral_large_sliding_contact_brick_field_extension *
>
2243 (
const_cast<virtual_brick *
>(pbr.get()));
2244 GMM_ASSERT1(p,
"Wrong type of brick");
2245 p->add_boundary(varname_u, multname, mim, region);
2246 md.add_mim_to_brick(indbrick, mim);
2248 contact_frame cf(N);
2249 p->build_contact_frame(md, cf);
2251 model::varnamelist vl;
2253 for (
size_type i = 0; i < cf.contact_boundaries.size(); ++i)
2254 if (cf.contact_boundaries[i].ind_U >= nvaru)
2255 { vl.push_back(p->boundaries[i].varname); ++nvaru; }
2258 for (
size_type i = 0; i < cf.contact_boundaries.size(); ++i)
2259 if (cf.contact_boundaries[i].ind_lambda >= nvarl)
2260 { vl.push_back(p->boundaries[i].multname); ++nvarl; }
2261 md.change_variables_of_brick(indbrick, vl);
2264 for (
size_type i = 0; i < vl.size(); ++i)
2265 for (
size_type j = 0; j < vl.size(); ++j)
2266 tl.push_back(model::term_description(vl[i], vl[j],
false));
2268 md.change_terms_of_brick(indbrick, tl);
2272 (model &md,
size_type indbrick,
const std::string &obs) {
2273 pbrick pbr = md.brick_pointer(indbrick);
2274 md.touch_brick(indbrick);
2275 integral_large_sliding_contact_brick_field_extension *p
2276 =
dynamic_cast<integral_large_sliding_contact_brick_field_extension *
>
2277 (
const_cast<virtual_brick *
>(pbr.get()));
2278 GMM_ASSERT1(p,
"Wrong type of brick");
2279 p->add_obstacle(obs);
2291 struct intergral_large_sliding_contact_brick_raytracing
2292 :
public virtual_brick {
2294 struct contact_boundary {
2296 std::string varname_u;
2297 std::string varname_lambda;
2298 std::string varname_w;
2306 std::vector<contact_boundary> boundaries;
2307 std::string transformation_name;
2308 std::string u_group;
2309 std::string w_group;
2310 std::string friction_coeff;
2312 std::string augmentation_param;
2313 model::varnamelist vl, dl;
2316 bool sym_version, frame_indifferent;
2318 void add_contact_boundary(model &md,
const mesh_im &mim,
size_type region,
2319 bool is_master,
bool is_slave,
2320 const std::string &u,
2321 const std::string &lambda,
2322 const std::string &w =
"") {
2323 std::string test_u =
"Test_" + sup_previous_and_dot_to_varname(u);
2324 std::string test_u_group =
"Test_" + sup_previous_and_dot_to_varname(u_group);
2325 std::string test_lambda =
"Test_" + sup_previous_and_dot_to_varname(lambda);
2326 GMM_ASSERT1(is_slave || is_master,
"The contact boundary should be "
2327 "either master, slave or both");
2328 const mesh_fem *mf = md.pmesh_fem_of_variable(u);
2329 GMM_ASSERT1(mf,
"The displacement variable should be a f.e.m. one");
2330 GMM_ASSERT1(&(mf->linked_mesh()) == &(mim.linked_mesh()),
2331 "The displacement variable and the integration method "
2332 "should share the same mesh");
2334 const mesh_fem *mf_l = md.pmesh_fem_of_variable(lambda);
2335 const im_data *mimd_l = md.pim_data_of_variable(lambda);
2336 GMM_ASSERT1(mf_l || mimd_l,
2337 "The multiplier variable should be defined on a "
2338 "mesh_fem or an im_data");
2339 GMM_ASSERT1(&(mf_l ? mf_l->linked_mesh() : mimd_l->linked_mesh())
2340 == &(mim.linked_mesh()),
2341 "The displacement and the multiplier fields "
2342 "should be defined on the same mesh");
2346 const mesh_fem *mf2 = md.pmesh_fem_of_variable(w);
2347 GMM_ASSERT1(!mf2 || &(mf2->linked_mesh()) == &(mf->linked_mesh()),
2348 "The data for the sliding velocity should be defined on "
2349 " the same mesh as the displacement variable");
2352 for (
size_type i = 0; i < boundaries.size(); ++i) {
2353 const contact_boundary &cb = boundaries[i];
2354 if (&(md.mesh_fem_of_variable(cb.varname_u).linked_mesh())
2355 == &(mf->linked_mesh()) && cb.region == region)
2356 GMM_ASSERT1(
false,
"This contact boundary has already been added");
2360 (md, transformation_name, mf->linked_mesh(), u_group, region);
2363 (md, transformation_name, mf->linked_mesh(), u_group, region);
2365 boundaries.push_back(contact_boundary());
2366 contact_boundary &cb = boundaries.back();
2369 if (is_slave) cb.varname_lambda = lambda;
2371 cb.is_master = is_master;
2372 cb.is_slave = is_slave;
2375 std::string n, n0, Vs, g, Y;
2376 n =
"Transformed_unit_vector(Grad_"+u+
", Normal)";
2377 n0 =
"Transformed_unit_vector(Grad_"+w+
", Normal)";
2384 Y =
"Interpolate(X,"+transformation_name+
")";
2385 g =
"("+Y+
"+Interpolate("+u_group+
","+transformation_name+
")-X-"+u+
")."+n;
2386 Vs =
"("+u+
"-Interpolate("+u_group+
","+transformation_name+
")";
2388 Vs +=
"-"+w+
"+Interpolate("+w_group+
","+transformation_name+
")";
2389 if (frame_indifferent)
2390 Vs +=
"+("+g+
")*("+n+
"-"+n0+
")";
2394 std::string coupled_projection_def =
2395 "Coulomb_friction_coupled_projection("
2396 + lambda+
","+n+
","+Vs+
","+g+
","+friction_coeff+
","
2397 + augmentation_param+
")";
2403 g =
"(Interpolate(X,"+transformation_name+
")-X-"+u+
")."+n;
2404 if (frame_indifferent && w.size())
2405 Vs =
"("+u+
"-"+w+
"+"+g+
"*("+n+
"-"+n0+
"))*"+
alpha;
2407 Vs =
"("+u+(w.size() ? (
"-"+w):
"")+
")*"+
alpha;
2409 std::string coupled_projection_rig =
2410 "Coulomb_friction_coupled_projection("
2411 + lambda+
","+n+
","+Vs+
","+g+
","+ friction_coeff+
","
2412 + augmentation_param+
")";
2416 (sym_version ?
"" : (
"-"+lambda+
"."+test_u))
2419 + (sym_version ? (
"+ Interpolate_filter("+transformation_name+
",-"
2420 +coupled_projection_def+
"."+test_u+
",1)") :
"")
2421 + (sym_version ? (
"+ Interpolate_filter("+transformation_name+
",-"
2422 +coupled_projection_rig+
"."+test_u+
",2)") :
"")
2428 +
"+ Interpolate_filter("+transformation_name+
","
2429 + (sym_version ? coupled_projection_def : lambda)
2430 +
".Interpolate("+test_u_group+
"," + transformation_name+
"), 1)"
2432 +
"-(1/"+augmentation_param+
")*"+lambda+
"."+test_lambda
2435 +
"+ Interpolate_filter("+transformation_name+
","
2436 +
"(1/"+augmentation_param+
")*"+ coupled_projection_rig
2437 +
"."+test_lambda+
", 2)"
2440 +
"+ Interpolate_filter("+transformation_name+
","
2441 +
"(1/"+augmentation_param+
")*" + coupled_projection_def +
"."
2442 + test_lambda+
", 1)";
2446 virtual void asm_real_tangent_terms(
const model &md,
size_type ,
2447 const model::varnamelist &,
2448 const model::varnamelist &,
2449 const model::mimlist &,
2450 model::real_matlist &,
2451 model::real_veclist &,
2452 model::real_veclist &,
2454 build_version)
const {
2459 for (
const contact_boundary &cb : boundaries) {
2461 md.add_generic_expression(cb.expr, *(cb.mim), cb.region);
2466 intergral_large_sliding_contact_brick_raytracing
2467 (
const std::string &r,
2468 const std::string &f_coeff,
const std::string &ug,
2469 const std::string &wg,
const std::string &tr,
2470 const std::string &alpha_ =
"1",
bool sym_v =
false,
2471 bool frame_indiff =
false) {
2472 transformation_name = tr;
2473 u_group = ug; w_group = wg;
2474 friction_coeff = f_coeff;
2476 augmentation_param = r;
2477 sym_version = sym_v;
2478 frame_indifferent = frame_indiff;
2480 set_flags(
"Integral large sliding contact bick raytracing",
2491 pbrick pbr = md.brick_pointer(indbrick);
2492 intergral_large_sliding_contact_brick_raytracing *p
2493 =
dynamic_cast<intergral_large_sliding_contact_brick_raytracing *
>
2495 GMM_ASSERT1(p,
"Wrong type of brick");
2496 return p->transformation_name;
2501 pbrick pbr = md.brick_pointer(indbrick);
2502 intergral_large_sliding_contact_brick_raytracing *p
2503 =
dynamic_cast<intergral_large_sliding_contact_brick_raytracing *
>
2505 GMM_ASSERT1(p,
"Wrong type of brick");
2511 pbrick pbr = md.brick_pointer(indbrick);
2512 intergral_large_sliding_contact_brick_raytracing *p
2513 =
dynamic_cast<intergral_large_sliding_contact_brick_raytracing *
>
2515 GMM_ASSERT1(p,
"Wrong type of brick");
2521 pbrick pbr = md.brick_pointer(indbrick);
2522 intergral_large_sliding_contact_brick_raytracing *p
2523 =
dynamic_cast<intergral_large_sliding_contact_brick_raytracing *
>
2525 GMM_ASSERT1(p,
"Wrong type of brick");
2527 (md, p->transformation_name, expr, N);
2532 bool is_master,
bool is_slave,
const std::string &u,
2533 const std::string &lambda,
const std::string &w) {
2535 pbrick pbr = md.brick_pointer(indbrick);
2536 intergral_large_sliding_contact_brick_raytracing *p
2537 =
dynamic_cast<intergral_large_sliding_contact_brick_raytracing *
>
2539 GMM_ASSERT1(p,
"Wrong type of brick");
2541 bool found_u =
false, found_lambda =
false;
2542 for (
const auto & v : p->vl) {
2543 if (v.compare(u) == 0) found_u =
true;
2544 if (v.compare(lambda) == 0) found_lambda =
true;
2546 if (!found_u) p->vl.push_back(u);
2547 GMM_ASSERT1(!is_slave || lambda.size(),
2548 "You should define a multiplier on each slave boundary");
2549 if (is_slave && !found_lambda) p->vl.push_back(lambda);
2550 if (!found_u || (is_slave && !found_lambda))
2553 std::vector<std::string> ug = md.variable_group(p->u_group);
2555 for (
const auto &uu : ug)
2556 if (uu.compare(u) == 0) { found_u =
true;
break; }
2559 md.define_variable_group(p->u_group, ug);
2563 bool found_w =
false;
2564 for (
const auto &ww : p->dl)
2565 if (ww.compare(w) == 0) { found_w =
true;
break; }
2570 std::vector<std::string> wg = md.variable_group(p->w_group);
2572 for (
const auto &ww : wg)
2573 if (ww.compare(w) == 0) { found_w =
true;
break; }
2576 md.define_variable_group(p->w_group, wg);
2580 bool found_mim =
false;
2581 for (
const auto &pmim : p->ml)
2582 if (pmim == &mim) { found_mim =
true;
break; }
2584 p->ml.push_back(&mim);
2588 p->add_contact_boundary(md, mim, region, is_master, is_slave,
2593 (
model &md,
const std::string &augm_param,
2594 scalar_type release_distance,
const std::string &f_coeff,
2595 const std::string &alpha,
bool sym_v,
bool frame_indifferent) {
2597 char ugroupname[50], wgroupname[50], transname[50];
2598 for (
int i = 0; i < 10000; ++i) {
2599 snprintf(ugroupname, 49,
"disp__group_raytracing_%d", i);
2600 if (!(md.variable_group_exists(ugroupname))
2604 md.define_variable_group(ugroupname, std::vector<std::string>());
2606 for (
int i = 0; i < 10000; ++i) {
2607 snprintf(wgroupname, 49,
"w__group_raytracing_%d", i);
2608 if (!(md.variable_group_exists(wgroupname))
2612 md.define_variable_group(wgroupname, std::vector<std::string>());
2614 for (
int i = 0; i < 10000; ++i) {
2615 snprintf(transname, 49,
"trans__raytracing_%d", i);
2621 model::varnamelist vl, dl;
2626 auto p = std::make_shared<intergral_large_sliding_contact_brick_raytracing>
2627 (augm_param, f_coeff, ugroupname, wgroupname, transname, alpha,
2628 sym_v, frame_indifferent);
2632 return md.
add_brick(pbr, p->vl, p->dl, model::termlist(), model::mimlist(),
2638 struct Nitsche_large_sliding_contact_brick_raytracing
2639 :
public virtual_brick {
2641 struct contact_boundary {
2643 std::string varname_u;
2644 std::string sigma_u;
2645 std::string varname_w;
2654 std::vector<contact_boundary> boundaries;
2655 std::string transformation_name;
2656 std::string u_group;
2657 std::string w_group;
2658 std::string friction_coeff;
2660 std::string Nitsche_param;
2661 model::varnamelist vl, dl;
2664 bool sym_version, frame_indifferent, unbiased;
2666 void add_contact_boundary(model &md,
const mesh_im &mim,
size_type region,
2667 bool is_master,
bool is_slave,
bool is_unbiased,
2668 const std::string &u,
2669 const std::string &sigma_u,
2670 const std::string &w =
"") {
2671 std::string test_u =
"Test_" + sup_previous_and_dot_to_varname(u);
2672 std::string test_u_group =
"Test_" + sup_previous_and_dot_to_varname(u_group);
2673 GMM_ASSERT1(is_slave || is_master,
"The contact boundary should be "
2674 "either master, slave or both");
2676 GMM_ASSERT1((is_slave && is_master),
"The contact boundary should be "
2677 "both master and slave for the unbiased version");
2678 is_slave=
true; is_master=
true;
2680 const mesh_fem *mf = md.pmesh_fem_of_variable(u);
2681 GMM_ASSERT1(mf,
"The displacement variable should be a f.e.m. one");
2682 GMM_ASSERT1(&(mf->linked_mesh()) == &(mim.linked_mesh()),
2683 "The displacement variable and the integration method "
2684 "should share the same mesh");
2687 const mesh_fem *mf2 = md.pmesh_fem_of_variable(w);
2688 GMM_ASSERT1(!mf2 || &(mf2->linked_mesh()) == &(mf->linked_mesh()),
2689 "The data for the sliding velocity should be defined on "
2690 " the same mesh as the displacement variable");
2693 for (
size_type i = 0; i < boundaries.size(); ++i) {
2694 const contact_boundary &cb = boundaries[i];
2695 if (&(md.mesh_fem_of_variable(cb.varname_u).linked_mesh())
2696 == &(mf->linked_mesh()) && cb.region == region)
2697 GMM_ASSERT1(
false,
"This contact boundary has already been added");
2701 (md, transformation_name, mf->linked_mesh(), u_group, region);
2704 (md, transformation_name, mf->linked_mesh(), u_group, region);
2706 boundaries.push_back(contact_boundary());
2707 contact_boundary &cb = boundaries.back();
2710 if (is_slave) cb.sigma_u = sigma_u;
2712 cb.is_master = is_master;
2713 cb.is_slave = is_slave;
2714 cb.is_unbiased= is_unbiased;
2717 std::string n, n0, Vs, g, Y, gamma;
2719 gamma =
"("+Nitsche_param+
"/element_size)";
2720 n =
"Transformed_unit_vector(Grad_"+u+
", Normal)";
2721 n0 =
"Transformed_unit_vector(Grad_"+w+
", Normal)";
2729 Y =
"Interpolate(X,"+transformation_name+
")";
2730 g =
"("+Y+
"+Interpolate("+u_group+
","+transformation_name+
")-X-"+u+
")."+n;
2731 Vs =
"("+u+
"-Interpolate("+u_group+
","+transformation_name+
")";
2733 Vs +=
"-"+w+
"+Interpolate("+w_group+
","+transformation_name+
")";
2734 if (frame_indifferent)
2735 Vs +=
"+("+g+
")*("+n+
"-"+n0+
")";
2739 std::string coupled_projection_def =
2740 "Coulomb_friction_coupled_projection("
2741 + sigma_u +
","+n+
","+Vs+
","+g+
","+friction_coeff+
","
2749 g =
"(Interpolate(X,"+transformation_name+
")-X-"+u+
")."+n;
2750 if (frame_indifferent && w.size())
2751 Vs =
"("+u+
"-"+w+
"+"+g+
"*("+n+
"-"+n0+
"))*"+
alpha;
2753 Vs =
"("+u+(w.size() ? (
"-"+w):
"")+
")*"+
alpha;
2755 std::string coupled_projection_rig =
2756 "Coulomb_friction_coupled_projection("
2757 + sigma_u +
","+n+
","+Vs+
","+g+
","+ friction_coeff+
","
2762 (is_unbiased ?
"-0.5*" :
"-")
2764 + (
"Interpolate_filter("+transformation_name+
","
2765 +coupled_projection_def+
"."+test_u+
",1) ")
2766 +(is_unbiased ?
"":
"-Interpolate_filter("+transformation_name+
","
2767 +coupled_projection_rig+
"."+test_u+
",2) ")
2773 + (is_unbiased ?
"+ 0.5*" :
"+ ")
2774 +
"Interpolate_filter("+transformation_name+
","
2775 +coupled_projection_def +
".Interpolate("+test_u_group+
"," + transformation_name+
"), 1)"
2776 +(is_unbiased ?
"":
"+ Interpolate_filter("+transformation_name+
","
2777 +coupled_projection_rig +
".Interpolate("+test_u_group+
"," + transformation_name+
"), 2)");
2781 virtual void asm_real_tangent_terms(
const model &md,
size_type ,
2782 const model::varnamelist &,
2783 const model::varnamelist &,
2784 const model::mimlist &,
2785 model::real_matlist &,
2786 model::real_veclist &,
2787 model::real_veclist &,
2789 build_version)
const {
2794 for (
const contact_boundary &cb : boundaries) {
2796 md.add_generic_expression(cb.expr, *(cb.mim), cb.region);
2801 Nitsche_large_sliding_contact_brick_raytracing
2803 const std::string &Nitsche_parameter,
2804 const std::string &f_coeff,
const std::string &ug,
2805 const std::string &wg,
const std::string &tr,
2806 const std::string &alpha_ =
"1",
bool sym_v =
false,
2807 bool frame_indiff =
false) {
2808 transformation_name = tr;
2809 u_group = ug; w_group = wg;
2810 friction_coeff = f_coeff;
2812 Nitsche_param = Nitsche_parameter;
2813 sym_version = sym_v;
2814 frame_indifferent = frame_indiff;
2817 set_flags(
"Integral large sliding contact bick raytracing",
2828 pbrick pbr = md.brick_pointer(indbrick);
2829 Nitsche_large_sliding_contact_brick_raytracing *p
2830 =
dynamic_cast<Nitsche_large_sliding_contact_brick_raytracing *
>
2832 GMM_ASSERT1(p,
"Wrong type of brick");
2833 return p->transformation_name;
2838 pbrick pbr = md.brick_pointer(indbrick);
2839 Nitsche_large_sliding_contact_brick_raytracing *p
2840 =
dynamic_cast<Nitsche_large_sliding_contact_brick_raytracing *
>
2842 GMM_ASSERT1(p,
"Wrong type of brick");
2848 pbrick pbr = md.brick_pointer(indbrick);
2849 Nitsche_large_sliding_contact_brick_raytracing *p
2850 =
dynamic_cast<Nitsche_large_sliding_contact_brick_raytracing *
>
2852 GMM_ASSERT1(p,
"Wrong type of brick");
2858 pbrick pbr = md.brick_pointer(indbrick);
2859 Nitsche_large_sliding_contact_brick_raytracing *p
2860 =
dynamic_cast<Nitsche_large_sliding_contact_brick_raytracing *
>
2862 GMM_ASSERT1(p,
"Wrong type of brick");
2864 (md, p->transformation_name, expr, N);
2869 bool is_master,
bool is_slave,
bool is_unbiased,
const std::string &u,
2870 const std::string &sigma_u,
const std::string &w) {
2872 pbrick pbr = md.brick_pointer(indbrick);
2873 Nitsche_large_sliding_contact_brick_raytracing *p
2874 =
dynamic_cast<Nitsche_large_sliding_contact_brick_raytracing *
>
2876 GMM_ASSERT1(p,
"Wrong type of brick");
2878 bool found_u =
false, found_sigma =
false;
2879 for (
const auto & v : p->vl) {
2880 if (v.compare(u) == 0) found_u =
true;
2881 if (v.compare(sigma_u) == 0) found_sigma =
true;
2883 if (!found_u) p->vl.push_back(u);
2884 GMM_ASSERT1(!is_slave || sigma_u.size(),
2885 "You should define an expression of sigma(u) on each slave boundary");
2890 std::vector<std::string> ug = md.variable_group(p->u_group);
2892 for (
const auto &uu : ug)
2893 if (uu.compare(u) == 0) { found_u =
true;
break; }
2896 md.define_variable_group(p->u_group, ug);
2900 bool found_w =
false;
2901 for (
const auto &ww : p->dl)
2902 if (ww.compare(w) == 0) { found_w =
true;
break; }
2907 std::vector<std::string> wg = md.variable_group(p->w_group);
2909 for (
const auto &ww : wg)
2910 if (ww.compare(w) == 0) { found_w =
true;
break; }
2913 md.define_variable_group(p->w_group, wg);
2917 bool found_mim =
false;
2918 for (
const auto &pmim : p->ml)
2919 if (pmim == &mim) { found_mim =
true;
break; }
2921 p->ml.push_back(&mim);
2925 p->add_contact_boundary(md, mim, region, is_master, is_slave,is_unbiased,
2930 (
model &md,
bool is_unbiased,
const std::string &Nitsche_param,
2931 scalar_type release_distance,
const std::string &f_coeff,
2932 const std::string &alpha,
bool sym_v,
bool frame_indifferent) {
2934 char ugroupname[50], wgroupname[50], transname[50];
2935 for (
int i = 0; i < 10000; ++i) {
2936 snprintf(ugroupname, 49,
"disp__group_raytracing_%d", i);
2937 if (!(md.variable_group_exists(ugroupname))
2941 md.define_variable_group(ugroupname, std::vector<std::string>());
2943 for (
int i = 0; i < 10000; ++i) {
2944 snprintf(wgroupname, 49,
"w__group_raytracing_%d", i);
2945 if (!(md.variable_group_exists(wgroupname))
2949 md.define_variable_group(wgroupname, std::vector<std::string>());
2951 for (
int i = 0; i < 10000; ++i) {
2952 snprintf(transname, 49,
"trans__raytracing_%d", i);
2958 model::varnamelist vl, dl;
2963 auto p = std::make_shared<Nitsche_large_sliding_contact_brick_raytracing>
2964 (is_unbiased, Nitsche_param , f_coeff, ugroupname, wgroupname, transname, alpha,
2965 sym_v, frame_indifferent);
2969 return md.
add_brick(pbr, p->vl, p->dl, model::termlist(), model::mimlist(),
region-tree for window/point search on a set of rectangles.
const base_node & xreal() const
coordinates of the current point, in the real convex.
void set_ii(size_type ii__)
change the current point (assuming a geotrans_precomp_ is used)
Balanced tree of n-dimensional rectangles.
structure passed as the argument of fem interpolation functions.
Describe a finite element method linked to a mesh.
virtual size_type nb_basic_dof() const
Return the total number of basic degrees of freedom (before the optional reduction).
Describe an integration method linked to a mesh.
"iterator" class for regions.
`‘Model’' variables store the variables, the data and the description of a model.
bool interpolate_transformation_exists(const std::string &name) const
Tests if name corresponds to an interpolate transformation.
void change_mims_of_brick(size_type ib, const mimlist &ml)
Change the mim list of a brick.
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.
void change_data_of_brick(size_type ib, const varnamelist &vl)
Change the data list of a brick.
void change_variables_of_brick(size_type ib, const varnamelist &vl)
Change the variable list of a brick.
bool variable_exists(const std::string &name) const
States if a name corresponds to a declared variable.
The virtual brick has to be derived to describe real model bricks.
Miscelleanous assembly routines for common terms. Use the low-level generic assembly....
void mult_add(const L1 &l1, const L2 &l2, L3 &l3)
*/
void copy(const L1 &l1, L2 &l2)
*/
number_traits< typename linalg_traits< V >::value_type >::magnitude_type vect_norm2(const V &v)
Euclidean norm of a vector.
void clear(L &l)
clear (fill with zeros) a vector or matrix.
number_traits< typename linalg_traits< V1 >::value_type >::magnitude_type vect_dist2(const V1 &v1, const V2 &v2)
Euclidean distance between two vectors.
void resize(V &v, size_type n)
*/
void mult(const L1 &l1, const L2 &l2, L3 &l3)
*/
strongest_value_type< V1, V2 >::value_type vect_sp(const V1 &v1, const V2 &v2)
*/
void add(const L1 &l1, L2 &l2)
*/
computation of the condition number of dense matrices.
void lu_inverse(const DenseMatrixLU &LU, const Pvector &pvector, const DenseMatrix &AInv_)
Given an LU factored matrix, build the inverse of the matrix.
size_type lu_factor(DenseMatrix &A, Pvector &ipvt)
LU Factorization of a general (dense) matrix (real or complex).
void lu_solve(const DenseMatrix &LU, const Pvector &pvector, VectorX &x, const VectorB &b)
LU Solve : Solve equation Ax=b, given an LU factored matrix.
void asm_mass_matrix(const MAT &M, const mesh_im &mim, const mesh_fem &mf1, const mesh_region &rg=mesh_region::all_convexes())
generic mass matrix assembly (on the whole mesh or on the specified convex set or boundary)
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 convex_num() const
get the current convex number
std::shared_ptr< const getfem::virtual_fem > pfem
type of pointer on a fem description
void grad_base_value(base_tensor &t, bool withM=true) const
fill the tensor with the gradient of the base functions (taken at point this->xref())
void base_value(base_tensor &t, bool withM=true) const
fill the tensor with the values of the base functions (taken at point this->xref())
short_type face_num() const
get the current face number
const pfem pf() const
get the current FEM descriptor
gmm::uint16_type short_type
used as the common short type integer in the library
std::shared_ptr< const convex_structure > pconvex_structure
Pointer on a convex structure description.
base_small_vector compute_normal(const geotrans_interpolation_context &c, size_type face)
norm of returned vector is the ratio between the face surface on the real element and the face surfac...
size_t size_type
used as the common size type in the library
std::shared_ptr< const bgeot::geometric_trans > pgeometric_trans
pointer type for a geometric transformation
size_type alpha(short_type n, short_type d)
Return the value of which is the number of monomials of a polynomial of variables and degree .
GEneric Tool for Finite Element Methods.
void add_rigid_obstacle_to_raytracing_transformation(model &md, const std::string &transname, const std::string &expr, size_type N)
Add a rigid obstacle whose geometry corresponds to the zero level-set of the high-level generic assem...
const std::string & transformation_name_of_large_sliding_contact_brick(model &md, size_type indbrick)
Gives the name of the raytracing interpolate transformation for an existing large sliding contact bri...
const std::string & sliding_data_group_name_of_Nitsche_large_sliding_contact_brick(model &md, size_type indbrick)
Gives the name of the group of variables corresponding to the sliding data for an existing large slid...
size_type add_integral_large_sliding_contact_brick_raytracing(model &md, const std::string &augm_param, scalar_type release_distance, const std::string &f_coeff="0", const std::string &alpha="1", bool sym_v=false, bool frame_indifferent=false)
Adds a large sliding contact with friction brick to the model.
size_type add_integral_large_sliding_contact_brick_raytrace(model &md, multi_contact_frame &mcf, const std::string &dataname_r, const std::string &dataname_friction_coeff=std::string(), const std::string &dataname_alpha=std::string())
Adds a large sliding contact with friction brick to the model.
void add_raytracing_transformation(model &md, const std::string &transname, scalar_type release_distance)
Add a raytracing interpolate transformation called 'transname' to a model to be used by the generic a...
size_type add_Nitsche_large_sliding_contact_brick_raytracing(model &md, bool is_unbiased, const std::string &Nitsche_param, scalar_type release_distance, const std::string &f_coeff="0", const std::string &alpha="1", bool sym_v=false, bool frame_indifferent=false)
Adds a large sliding contact with friction brick to the model based on Nitsche's method.
void add_rigid_obstacle_to_Nitsche_large_sliding_contact_brick(model &md, size_type indbrick, const std::string &expr, size_type N)
Adds a rigid obstacle to an existing large sliding contact with friction brick.
const std::string & sliding_data_group_name_of_large_sliding_contact_brick(model &md, size_type indbrick)
Gives the name of the group of variables corresponding to the sliding data for an existing large slid...
void add_contact_boundary_to_Nitsche_large_sliding_contact_brick(model &md, size_type indbrick, const mesh_im &mim, size_type region, bool is_master, bool is_slave, bool is_unbiased, const std::string &u, const std::string &lambda="", const std::string &w="")
Adds a contact boundary to an existing large sliding contact with friction brick.
void add_rigid_obstacle_to_large_sliding_contact_brick(model &md, size_type indbrick, const std::string &expr, size_type N)
Adds a rigid obstacle to an existing large sliding contact with friction brick.
void add_master_contact_boundary_to_raytracing_transformation(model &md, const std::string &transname, const mesh &m, const std::string &dispname, size_type region)
Add a master boundary with corresponding displacement variable 'dispname' on a specific boundary 'reg...
void slice_vector_on_basic_dof_of_element(const mesh_fem &mf, const VEC1 &vec, size_type cv, VEC2 &coeff, size_type qmult1=size_type(-1), size_type qmult2=size_type(-1))
Given a mesh_fem.
std::shared_ptr< const virtual_brick > pbrick
type of pointer on a brick
const std::string & transformation_name_of_Nitsche_large_sliding_contact_brick(model &md, size_type indbrick)
Gives the name of the raytracing interpolate transformation for an existing large sliding contact bri...
const std::string & displacement_group_name_of_large_sliding_contact_brick(model &md, size_type indbrick)
Gives the name of the group of variables corresponding to the displacement for an existing large slid...
const std::string & displacement_group_name_of_Nitsche_large_sliding_contact_brick(model &md, size_type indbrick)
Gives the name of the group of variables corresponding to the displacement for an existing large slid...
void add_slave_contact_boundary_to_raytracing_transformation(model &md, const std::string &transname, const mesh &m, const std::string &dispname, size_type region)
Add a slave boundary with corresponding displacement variable 'dispname' on a specific boundary 'regi...
void add_contact_boundary_to_large_sliding_contact_brick(model &md, size_type indbrick, const mesh_im &mim, size_type region, bool is_master, bool is_slave, const std::string &u, const std::string &lambda="", const std::string &w="")
Adds a contact boundary to an existing large sliding contact with friction brick.