25 #include "getfem/getfem_contact_and_friction_large_sliding.h"
37 #define FRICTION_LAW 1
40 #if FRICTION_LAW == 1 // Complete law with friction
42 template <
typename VEC,
typename VEC2,
typename VECR>
43 void aug_friction(
const VEC &lambda, scalar_type g,
const VEC &Vs,
44 const VEC &n, scalar_type r,
const VEC2 &f, VECR &F) {
46 scalar_type lambdan = gmm::vect_sp(lambda, n)/nn;
47 scalar_type lambdan_aug = gmm::neg(lambdan + r * g);
49 scalar_type tau = ((i >= 3) ? f[2] : scalar_type(0)) + f[0]*lambdan_aug;
50 if (i >= 2) tau = std::min(tau, f[1]);
52 if (tau > scalar_type(0)) {
53 gmm::add(lambda, gmm::scaled(Vs, -r), F);
54 scalar_type mu = gmm::vect_sp(F, n)/nn;
55 gmm::add(gmm::scaled(n, -mu/nn), F);
57 if (norm > tau) gmm::scale(F, tau / norm);
60 gmm::add(gmm::scaled(n, -lambdan_aug/nn), F);
63 template <
typename VEC,
typename VEC2,
typename VECR,
typename MAT>
64 void aug_friction_grad(
const VEC &lambda, scalar_type g,
const VEC &Vs,
65 const VEC &n, scalar_type r,
const VEC2 &f, VECR &F,
66 MAT &dlambda, VECR &dg, MAT &dn, MAT &dVs) {
69 scalar_type lambdan = gmm::vect_sp(lambda, n)/nn;
70 scalar_type lambdan_aug = gmm::neg(lambdan + r * g);
72 scalar_type tau = ((i >= 3) ? f[2] : scalar_type(0)) + f[0]*lambdan_aug;
73 if (i >= 2) tau = std::min(tau, f[1]);
76 if (tau > scalar_type(0)) {
77 gmm::add(lambda, gmm::scaled(Vs, -r), F);
78 scalar_type mu = gmm::vect_sp(F, n)/nn;
79 gmm::add(gmm::scaled(n, -mu/nn), F);
81 gmm::copy(gmm::identity_matrix(), dn);
82 gmm::scale(dn, -mu/nn);
83 gmm::rank_one_update(dn, gmm::scaled(n, mu/(nn*nn*nn)), n);
84 gmm::rank_one_update(dn, gmm::scaled(n, scalar_type(-1)/(nn*nn)), F);
85 gmm::copy(gmm::identity_matrix(), dVs);
86 gmm::rank_one_update(dVs, n, gmm::scaled(n, scalar_type(-1)/(nn*nn)));
89 gmm::rank_one_update(dVs, F,
90 gmm::scaled(F, scalar_type(-1)/(norm*norm)));
91 gmm::scale(dVs, tau / norm);
92 gmm::copy(gmm::scaled(F, scalar_type(1)/norm), dg);
93 gmm::rank_one_update(dn, gmm::scaled(F, mu/(norm*norm*nn)), F);
94 gmm::scale(dn, tau / norm);
95 gmm::scale(F, tau / norm);
102 gmm::copy(dVs, dlambda);
103 if (norm > tau && ((i <= 1) || tau < f[1]) && ((i <= 2) || tau > f[2])) {
104 gmm::rank_one_update(dn, dg, gmm::scaled(lambda, -f[0]/nn));
105 gmm::rank_one_update(dn, dg, gmm::scaled(n, f[0]*lambdan/(nn*nn)));
106 gmm::rank_one_update(dlambda, dg, gmm::scaled(n, -f[0]/nn));
107 gmm::scale(dg, -f[0]*r);
109 if (lambdan_aug > scalar_type(0)) {
110 gmm::add(gmm::scaled(n, r/nn), dg);
111 gmm::rank_one_update(dlambda, n, gmm::scaled(n, scalar_type(1)/(nn*nn)));
112 gmm::rank_one_update(dn, gmm::scaled(n, scalar_type(1)/(nn*nn)), lambda);
113 gmm::rank_one_update(dn,
114 gmm::scaled(n,(lambdan_aug-lambdan)/(nn*nn*nn)), n);
115 for (
size_type j = 0; j < N; ++j) dn(j,j) -= lambdan_aug/nn;
117 gmm::add(gmm::scaled(n, -lambdan_aug/nn), F);
122 #elif FRICTION_LAW == 2 // Contact only
124 template <
typename VEC,
typename VEC2,
typename VECR>
125 void aug_friction(
const VEC &lambda, scalar_type g,
const VEC &,
126 const VEC &n, scalar_type r,
const VEC2 &, VECR &F) {
128 scalar_type lambdan = gmm::vect_sp(lambda, n)/nn;
129 scalar_type lambdan_aug = gmm::neg(lambdan + r * g);
130 gmm::copy(gmm::scaled(n, -lambdan_aug/nn), F);
133 template <
typename VEC,
typename VEC2,
typename VECR,
typename MAT>
134 void aug_friction_grad(
const VEC &lambda, scalar_type g,
const VEC &,
135 const VEC &n, scalar_type r,
const VEC2 &, VECR &F,
136 MAT &dlambda, VECR &dg, MAT &dn, MAT &dVs) {
139 scalar_type lambdan = gmm::vect_sp(lambda, n)/nn;
140 scalar_type lambdan_aug = gmm::neg(lambdan + r * g);
147 if (lambdan_aug > scalar_type(0)) {
148 gmm::add(gmm::scaled(n, r/nn), dg);
149 gmm::rank_one_update(dlambda, n, gmm::scaled(n, scalar_type(1)/(nn*nn)));
150 gmm::rank_one_update(dn, gmm::scaled(n, scalar_type(1)/(nn*nn)), lambda);
151 gmm::rank_one_update(dn,
152 gmm::scaled(n,(lambdan_aug-lambdan)/(nn*nn*nn)), n);
153 for (
size_type j = 0; j < N; ++j) dn(j,j) -= lambdan_aug/nn;
155 gmm::add(gmm::scaled(n, -lambdan_aug/nn), F);
162 #elif FRICTION_LAW == 3 // Dummy law for test
164 template <
typename VEC,
typename VEC2,
typename VECR>
165 void aug_friction(
const VEC &lambda, scalar_type g,
const VEC &Vs,
166 const VEC &n, scalar_type r,
const VEC2 &f, VECR &F) {
167 gmm::copy(gmm::scaled(lambda, g*r*f[0]), F);
168 gmm::copy(gmm::scaled(Vs, g*r*f[0]), F);
173 template <
typename VEC,
typename VEC2,
typename VECR,
typename MAT>
174 void aug_friction_grad(
const VEC &lambda, scalar_type g,
const VEC &Vs,
175 const VEC &n, scalar_type r,
const VEC2 &f, VECR &F,
176 MAT &dlambda, VECR &dg, MAT &dn, MAT &dVs) {
177 gmm::copy(gmm::scaled(lambda, g*r*f[0]), F);
178 gmm::copy(gmm::scaled(Vs, g*r*f[0]), F);
184 gmm::copy(gmm::identity_matrix(), dn);
187 #elif FRICTION_LAW == 4 // Dummy law for test
189 template <
typename VEC,
typename VEC2,
typename VECR>
190 void aug_friction(
const VEC &lambda, scalar_type g,
const VEC &Vs,
191 const VEC &n, scalar_type r,
const VEC2 &f, VECR &F) {
192 gmm::copy(gmm::scaled(lambda, g*r*f[0]*n[0]*Vs[0]), F);
193 gmm::copy(lambda, F);
196 template <
typename VEC,
typename VEC2,
typename VECR,
typename MAT>
197 void aug_friction_grad(
const VEC &lambda, scalar_type g,
const VEC &Vs,
198 const VEC &n, scalar_type r,
const VEC2 &f, VECR &F,
199 MAT &dlambda, VECR &dg, MAT &dn, MAT &dVs) {
200 gmm::copy(gmm::scaled(lambda, g*r*f[0]*n[0]*Vs[0]), F);
204 gmm::copy(lambda, F);
205 gmm::copy(gmm::identity_matrix(), dlambda);
208 #elif FRICTION_LAW == 5 // Dummy law for test
210 template <
typename VEC,
typename VEC2,
typename VECR>
211 void aug_friction(
const VEC &lambda, scalar_type g,
const VEC &Vs,
212 const VEC &n, scalar_type r,
const VEC2 &f, VECR &F) {
213 gmm::copy(gmm::scaled(lambda, g*r*f[0]*n[0]*Vs[0]), F);
217 template <
typename VEC,
typename VEC2,
typename VECR,
typename MAT>
218 void aug_friction_grad(
const VEC &lambda, scalar_type g,
const VEC &Vs,
219 const VEC &n, scalar_type r,
const VEC2 &f, VECR &F,
220 MAT &dlambda, VECR &dg, MAT &dn, MAT &dVs) {
221 gmm::copy(gmm::scaled(lambda, g*r*f[0]*n[0]*Vs[0]), F);
243 struct integral_large_sliding_contact_brick :
public virtual_brick {
245 multi_contact_frame &mcf;
249 virtual void asm_real_tangent_terms(
const model &md,
size_type ,
250 const model::varnamelist &vl,
251 const model::varnamelist &dl,
252 const model::mimlist &mims,
253 model::real_matlist &matl,
254 model::real_veclist &vecl,
255 model::real_veclist &,
257 build_version version)
const;
259 integral_large_sliding_contact_brick(multi_contact_frame &mcff,
261 : mcf(mcff), with_friction(with_fric) {
262 set_flags(
"Integral large sliding contact brick",
271 struct gauss_point_precomp {
273 fem_precomp_pool fppool;
274 const multi_contact_frame &mcf;
276 const multi_contact_frame::contact_pair *cp;
278 const base_node &x(
void)
const {
return cp->slave_point; }
279 const base_node &nx(
void)
const {
return cp->slave_n; }
280 const base_node &y(
void)
const {
return cp->master_point; }
281 const base_node &y_ref(
void)
const {
return cp->master_point_ref; }
282 const base_node &ny(
void)
const {
return cp->master_n; }
283 scalar_type g(
void)
const {
return cp->signed_dist; }
286 bool I_nxnx_computed;
287 const base_matrix &I_nxnx(
void) {
288 if (!I_nxnx_computed) {
289 gmm::copy(gmm::identity_matrix(), I_nxnx_);
290 gmm::rank_one_update(I_nxnx_, nx(), gmm::scaled(nx(),scalar_type(-1)));
291 I_nxnx_computed =
true;
297 bool I_nyny_computed;
298 const base_matrix &I_nyny(
void) {
299 if (!I_nyny_computed) {
300 gmm::copy(gmm::identity_matrix(), I_nyny_);
301 gmm::rank_one_update(I_nyny_, ny(), gmm::scaled(ny(),scalar_type(-1)));
302 I_nyny_computed =
true;
308 bool I_nxny_computed;
309 const base_matrix &I_nxny(
void) {
310 if (!I_nxny_computed) {
311 gmm::copy(gmm::identity_matrix(), I_nxny_);
312 gmm::rank_one_update(I_nxny_, nx(),
313 gmm::scaled(ny(),scalar_type(-1)/nxny));
314 I_nxny_computed =
true;
320 scalar_type nxdotny(
void)
const {
return nxny; }
323 bool isrigid(
void) {
return isrigid_; }
325 base_tensor base_ux, base_uy, base_lx, base_ly;
326 base_matrix vbase_ux_, vbase_uy_, vbase_lx_, vbase_ly_;
327 bool vbase_ux_init, vbase_uy_init, vbase_lx_init, vbase_ly_init;
328 base_tensor grad_base_ux, grad_base_uy, vgrad_base_ux_, vgrad_base_uy_;
329 bool vgrad_base_ux_init, vgrad_base_uy_init;
330 bool have_lx, have_ly;
332 fem_interpolation_context ctx_ux_, ctx_uy_, ctx_lx_, ctx_ly_;
333 bool ctx_ux_init, ctx_uy_init, ctx_lx_init, ctx_ly_init;
335 const mesh_fem *mf_ux_, *mf_uy_, *mf_lx_, *mf_ly_;
336 gmm::sub_interval I_ux_, I_uy_, I_lx_, I_ly_;
337 pfem pf_ux, pf_uy, pf_lx, pf_ly;
338 size_type ndof_ux_, qdim_ux, ndof_uy_, qdim_uy, ndof_lx_, qdim_lx;
339 size_type ndof_ly_, qdim_ly, cvx_, cvy_, ibx, iby;
343 pintegration_method pim;
346 scalar_type weight(
void) {
return weight_; }
348 const mesh &meshx(
void)
const {
return mf_ux_->linked_mesh(); }
349 const mesh &meshy(
void)
const {
return mf_uy_->linked_mesh(); }
350 const mesh_fem *mf_ux(
void)
const {
return mf_ux_; }
351 const mesh_fem *mf_uy(
void)
const {
return mf_uy_; }
352 const mesh_fem *mf_lx(
void)
const {
return mf_lx_; }
353 const mesh_fem *mf_ly(
void)
const {
return mf_ly_; }
354 size_type ndof_ux(
void)
const {
return ndof_ux_; }
355 size_type ndof_uy(
void)
const {
return ndof_uy_; }
356 size_type ndof_lx(
void)
const {
return ndof_lx_; }
357 size_type ndof_ly(
void)
const {
return ndof_ly_; }
358 size_type cvx(
void)
const {
return cvx_; }
359 size_type cvy(
void)
const {
return cvy_; }
360 const gmm::sub_interval I_ux(
void)
const {
return I_ux_; }
361 const gmm::sub_interval I_uy(
void)
const {
return I_uy_; }
362 const gmm::sub_interval I_lx(
void)
const {
return I_lx_; }
363 const gmm::sub_interval I_ly(
void)
const {
return I_ly_; }
366 fem_interpolation_context &ctx_ux(
void) {
368 bgeot::vectors_to_base_matrix(Gx, meshx().points_of_convex(cvx_));
370 = fppool(pf_ux, pim->approx_method()->pintegration_points());
371 ctx_ux_ = fem_interpolation_context(pgtx, pfp_ux, cp->slave_ind_pt,
378 fem_interpolation_context &ctx_lx(
void) {
379 GMM_ASSERT1(have_lx,
"No multiplier defined on the slave surface");
382 = fppool(pf_lx, pim->approx_method()->pintegration_points());
383 ctx_lx_ = fem_interpolation_context(pgtx, pfp_lx, cp->slave_ind_pt,
384 ctx_ux().G(), cvx_, fx);
390 fem_interpolation_context &ctx_uy(
void) {
391 GMM_ASSERT1(!isrigid(),
"Rigid obstacle master node: no fem defined");
393 bgeot::vectors_to_base_matrix(Gy, meshy().points_of_convex(cvy_));
394 ctx_uy_ = fem_interpolation_context(pgty, pf_uy, y_ref(), Gy, cvy_, fy);
400 fem_interpolation_context &ctx_ly(
void) {
401 GMM_ASSERT1(have_ly,
"No multiplier defined on the master surface");
403 ctx_ly_ = fem_interpolation_context(pgty, pf_ly, y_ref(),
404 ctx_uy().G(), cvy_, fy);
410 const base_matrix &vbase_ux(
void) {
411 if (!vbase_ux_init) {
412 ctx_ux().base_value(base_ux);
413 vectorize_base_tensor(base_ux, vbase_ux_, ndof_ux_, qdim_ux, N);
414 vbase_ux_init =
true;
419 const base_matrix &vbase_uy(
void) {
420 if (!vbase_uy_init) {
421 ctx_uy().base_value(base_uy);
422 vectorize_base_tensor(base_uy, vbase_uy_, ndof_uy_, qdim_uy, N);
423 vbase_uy_init =
true;
428 const base_matrix &vbase_lx(
void) {
429 if (!vbase_lx_init) {
430 ctx_lx().base_value(base_lx);
431 vectorize_base_tensor(base_lx, vbase_lx_, ndof_lx_, qdim_lx, N);
432 vbase_lx_init =
true;
437 const base_matrix &vbase_ly(
void) {
438 if (!vbase_ly_init) {
439 ctx_ly().base_value(base_ly);
440 vectorize_base_tensor(base_ly, vbase_ly_, ndof_ly_, qdim_ly, N);
441 vbase_ly_init =
true;
446 const base_tensor &vgrad_base_ux(
void) {
447 if (!vgrad_base_ux_init) {
448 ctx_ux().grad_base_value(grad_base_ux);
449 vectorize_grad_base_tensor(grad_base_ux, vgrad_base_ux_, ndof_ux_,
451 vgrad_base_ux_init =
true;
453 return vgrad_base_ux_;
456 const base_tensor &vgrad_base_uy(
void) {
457 if (!vgrad_base_uy_init) {
458 ctx_uy().grad_base_value(grad_base_uy);
459 vectorize_grad_base_tensor(grad_base_uy, vgrad_base_uy_, ndof_uy_,
461 vgrad_base_uy_init =
true;
463 return vgrad_base_uy_;
466 base_small_vector lambda_x_, lambda_y_;
467 bool lambda_x_init, lambda_y_init;
470 const base_small_vector &lx(
void) {
471 if (!lambda_x_init) {
472 pfem pf = ctx_lx().pf();
475 pf->interpolation(ctx_lx(), coeff, lambda_x_, dim_type(N));
476 lambda_x_init =
true;
481 const base_small_vector &ly(
void) {
482 if (!lambda_y_init) {
483 pfem pf = ctx_ly().pf();
486 pf->interpolation(ctx_ly(), coeff, lambda_y_, dim_type(N));
487 lambda_y_init =
true;
492 base_matrix grad_phix_, grad_phix_inv_, grad_phiy_, grad_phiy_inv_;
493 bool grad_phix_init, grad_phix_inv_init;
494 bool grad_phiy_init, grad_phiy_inv_init;
496 const base_matrix &grad_phix(
void) {
497 if (!grad_phix_init) {
498 pfem pf = ctx_ux().pf();
501 pf->interpolation_grad(ctx_ux(), coeff, grad_phix_, dim_type(N));
502 gmm::add(gmm::identity_matrix(), grad_phix_);
503 grad_phix_init =
true;
508 const base_matrix &grad_phix_inv(
void) {
509 if (!grad_phix_inv_init) {
510 gmm::copy(grad_phix(), grad_phix_inv_);
511 gmm::lu_inverse(grad_phix_inv_);
513 grad_phix_inv_init =
true;
515 return grad_phix_inv_;
518 const base_matrix &grad_phiy(
void) {
519 if (!grad_phiy_init) {
520 pfem pf = ctx_uy().pf();
523 pf->interpolation_grad(ctx_uy(), coeff, grad_phiy_, dim_type(N));
524 gmm::add(gmm::identity_matrix(), grad_phiy_);
525 grad_phiy_init =
true;
530 const base_matrix &grad_phiy_inv(
void) {
531 if (!grad_phiy_inv_init) {
532 gmm::copy(grad_phiy(), grad_phiy_inv_);
533 gmm::lu_inverse(grad_phiy_inv_);
535 grad_phiy_inv_init =
true;
537 return grad_phiy_inv_;
541 base_small_vector x0_, y0_, nx0_, Vs_;
542 bool x0_init, y0_init, nx0_init, Vs_init;
543 base_matrix grad_phiy0_;
544 bool grad_phiy0_init;
546 const base_small_vector &x0(
void) {
548 const model_real_plain_vector &all_x0 = mcf.disp0_of_boundary(ibx);
550 pfem pf = ctx_ux().pf();
552 pf->interpolation(ctx_ux(), coeff, x0_, dim_type(N));
554 gmm::add(ctx_ux().xreal(), x0_);
560 const base_small_vector &y0(
void) {
563 const model_real_plain_vector &all_y0 = mcf.disp0_of_boundary(iby);
565 pfem pf = ctx_uy().pf();
567 pf->interpolation(ctx_uy(), coeff, y0_, dim_type(N));
569 gmm::add(ctx_uy().xreal(), y0_);
570 }
else gmm::copy(y(), y0_);
576 const base_small_vector &nx0(
void) {
578 const model_real_plain_vector &all_x0 = mcf.disp0_of_boundary(ibx);
580 pfem pf = ctx_ux().pf();
582 base_small_vector nx00_(N);
583 base_matrix grad_phix0_(N,N);
584 compute_normal(ctx_ux(), fx,
false, coeff, nx00_, nx0_, grad_phix0_);
592 const base_small_vector &Vs(
void) {
594 if (alpha != scalar_type(0)) {
595 #ifdef CONSIDER_FRAME_INDIFFERENCE
597 gmm::add(y0(), gmm::scaled(x0(), scalar_type(-1)), Vs_);
598 gmm::add(gmm::scaled(nx0(), -g()), Vs_);
602 gmm::add(x(), gmm::scaled(y(), scalar_type(-1)), Vs_);
603 gmm::add(gmm::scaled(x0(), scalar_type(-1)), Vs_);
606 gmm::scale(Vs_, alpha);
613 const base_matrix &grad_phiy0(
void) {
615 if (!grad_phiy0_init) {
616 const model_real_plain_vector &all_y0 = mcf.disp0_of_boundary(iby);
617 if (!isrigid() && all_y0.size()) {
618 pfem pf = ctx_uy().pf();
620 pf->interpolation_grad(ctx_uy(), coeff, grad_phiy0_, dim_type(N));
621 gmm::add(gmm::identity_matrix(), grad_phiy0_);
622 }
else gmm::copy(gmm::identity_matrix(), grad_phiy0_);
623 grad_phiy0_init =
true;
628 base_small_vector un;
630 void set_pair(
const multi_contact_frame::contact_pair &cp_) {
632 I_nxnx_computed = I_nyny_computed = I_nxny_computed =
false;
633 ctx_ux_init = ctx_uy_init = ctx_lx_init = ctx_ly_init =
false;
634 vbase_ux_init = vbase_uy_init = vbase_lx_init = vbase_ly_init =
false;
635 vgrad_base_ux_init = vgrad_base_uy_init =
false;
636 lambda_x_init = lambda_y_init =
false;
637 have_lx = have_ly =
false;
638 grad_phix_init = grad_phiy_init =
false;
639 grad_phix_inv_init = grad_phiy_inv_init =
false;
640 x0_init = y0_init = Vs_init = grad_phiy0_init =
false;
641 nxny = gmm::vect_sp(nx(), ny());
642 isrigid_ = (cp->irigid_obstacle !=
size_type(-1));
644 cvx_ = cp->slave_ind_element;
645 ibx = cp->slave_ind_boundary;
646 mf_ux_ = &(mcf.mfdisp_of_boundary(ibx));
647 pf_ux = mf_ux_->fem_of_element(cvx_);
648 qdim_ux = pf_ux->target_dim();
649 ndof_ux_ = pf_ux->nb_dof(cvx_) * N / qdim_ux;
650 fx = cp->slave_ind_face;
651 pgtx = meshx().trans_of_convex(cvx_);
652 mim = &(mcf.mim_of_boundary(ibx));
653 pim = mim->int_method_of_element(cvx_);
654 weight_ = pim->approx_method()->coeff(cp->slave_ind_pt) * ctx_ux().J();
655 gmm::mult(ctx_ux().B(), pgtx->normals()[fx], un);
657 const std::string &name_ux = mcf.varname_of_boundary(ibx);
658 I_ux_ = md.interval_of_variable(name_ux);
660 const std::string &name_lx = mcf.multname_of_boundary(ibx);
661 have_lx = (name_lx.size() > 0);
663 mf_lx_ = &(mcf.mfmult_of_boundary(ibx));
664 I_lx_ = md.interval_of_variable(name_lx);
665 pf_lx = mf_lx_->fem_of_element(cvx_);
666 qdim_lx = pf_lx->target_dim();
667 ndof_lx_ = pf_lx->nb_dof(cvx_) * N / qdim_lx;
671 cvy_ = cp->master_ind_element;
672 iby = cp->master_ind_boundary;
673 fy = cp->master_ind_face;
674 mf_uy_ = &(mcf.mfdisp_of_boundary(iby));
675 pf_uy = mf_uy_->fem_of_element(cvy_);
676 qdim_uy = pf_uy->target_dim();
677 ndof_uy_ = pf_uy->nb_dof(cvy_) * N / qdim_uy;
678 pgty = meshy().trans_of_convex(cvy_);
680 const std::string &name_uy = mcf.varname_of_boundary(iby);
681 I_uy_ = md.interval_of_variable(name_uy);
682 const std::string &name_ly = mcf.multname_of_boundary(iby);
683 have_ly = (name_ly.size() > 0);
685 mf_ly_ = &(mcf.mfmult_of_boundary(iby));
686 I_ly_ = md.interval_of_variable(name_ly);
687 pf_ly = mf_ly_->fem_of_element(cvy_);
688 qdim_ly = pf_ly->target_dim();
689 ndof_ly_ = pf_ly->nb_dof(cvy_) * N / qdim_ly;
694 gauss_point_precomp(
size_type N_,
const model &md_,
695 const multi_contact_frame &mcf_, scalar_type alpha_) :
696 N(N_), mcf(mcf_), md(md_),
697 I_nxnx_(N,N), I_nyny_(N,N), I_nxny_(N,N),
698 lambda_x_(N), lambda_y_(N),
699 grad_phix_(N, N), grad_phix_inv_(N, N),
700 grad_phiy_(N, N), grad_phiy_inv_(N, N),
alpha(alpha_),
701 x0_(N), y0_(N), nx0_(N), Vs_(N), grad_phiy0_(N, N), un(N) {}
779 void integral_large_sliding_contact_brick::asm_real_tangent_terms
780 (
const model &md,
size_type ,
const model::varnamelist &vl,
781 const model::varnamelist &dl,
const model::mimlist &,
782 model::real_matlist &matl, model::real_veclist &vecl,
784 build_version version)
const {
787 GMM_ASSERT1((with_friction && dl.size() >= 2 && dl.size() <= 3)
788 || (!with_friction && dl.size() >= 1 && dl.size() <= 2),
789 "Wrong number of data for integral large sliding contact brick");
791 GMM_ASSERT1(vl.size() == mcf.nb_variables() + mcf.nb_multipliers(),
792 "For the moment, it is not allowed to add boundaries to "
793 "the multi contact frame object after a model brick has "
796 const model_real_plain_vector &vr = md.real_variable(dl[0]);
797 GMM_ASSERT1(gmm::vect_size(vr) == 1,
"Large sliding contact "
798 "brick: parameter r should be a scalar");
799 scalar_type r = vr[0];
801 model_real_plain_vector f_coeff;
803 f_coeff = md.real_variable(dl[1]);
804 GMM_ASSERT1(gmm::vect_size(f_coeff) <= 3,
805 "Large sliding contact "
806 "brick: the friction law has less than 3 parameters");
808 if (gmm::vect_size(f_coeff) == 0)
809 { f_coeff.resize(1); f_coeff[0] = scalar_type(0); }
811 scalar_type
alpha(0);
813 if (dl.size() >= ind+1) {
814 GMM_ASSERT1(md.real_variable(dl[ind]).size() == 1,
815 "Large sliding contact "
816 "brick: parameter alpha should be a scalar");
817 alpha = md.real_variable(dl[ind])[0];
820 GMM_ASSERT1(matl.size() == 1,
821 "Large sliding contact brick should have only one term");
822 model_real_sparse_matrix &M = matl[0];
gmm::clear(M);
823 model_real_plain_vector &V = vecl[0];
gmm::clear(V);
825 mcf.set_raytrace(
true);
826 mcf.set_nodes_mode(0);
827 mcf.compute_contact_pairs();
831 base_matrix dlambdaF(N, N), dnF(N, N), dVsF(N, N);
832 base_small_vector F(N), dgF(N);
834 scalar_type FMULT = 1.;
837 for (
size_type i = 0; i < mcf.nb_boundaries(); ++i)
838 if (mcf.is_self_contact() || mcf.is_slave_boundary(i)) {
839 size_type region = mcf.region_of_boundary(i);
840 const std::string &name_lx = mcf.multname_of_boundary(i);
841 GMM_ASSERT1(name_lx.size() > 0,
"This brick need "
842 "multipliers defined on the multi_contact_frame object");
843 const mesh_fem &mflambda = mcf.mfmult_of_boundary(i);
844 const mesh_im &mim = mcf.mim_of_boundary(i);
845 const gmm::sub_interval &I = md.interval_of_variable(name_lx);
847 if (version & model::BUILD_MATRIX) {
848 model_real_sparse_matrix M1(mflambda.nb_dof(), mflambda.nb_dof());
850 gmm::add(gmm::scaled(M1, FMULT/r), gmm::sub_matrix(M, I, I));
853 if (version & model::BUILD_RHS) {
854 model_real_plain_vector V1(mflambda.nb_dof());
856 (V1, mim, mflambda, mflambda,
857 md.real_variable(mcf.multname_of_boundary(i)), region);
858 gmm::add(gmm::scaled(V1, -FMULT/r), gmm::sub_vector(V, I));
862 gauss_point_precomp gpp(N, md, mcf, alpha);
866 base_matrix auxNN1(N, N), auxNN2(N, N);
867 base_small_vector auxN1(N), auxN2(N);
870 for (
size_type icp = 0; icp < mcf.nb_contact_pairs(); ++icp) {
871 const multi_contact_frame::contact_pair &cp = mcf.get_contact_pair(icp);
873 const base_small_vector &nx = gpp.nx(), &ny = gpp.ny();
874 const mesh_fem *mf_ux = gpp.mf_ux(), *mf_lx = gpp.mf_lx(), *mf_uy(0);
875 size_type ndof_ux = gpp.ndof_ux(), ndof_uy(0), ndof_lx = gpp.ndof_lx();
877 const gmm::sub_interval &I_ux = gpp.I_ux(), &I_lx = gpp.I_lx();
878 gmm::sub_interval I_uy;
879 bool isrigid = gpp.isrigid();
881 ndof_uy = gpp.ndof_uy(); I_uy = gpp.I_uy();
882 mf_uy = gpp.mf_uy(); cvy = gpp.cvy();
884 scalar_type weight = gpp.weight(), g = gpp.g();
885 const base_small_vector &lambda = gpp.lx();
887 base_vector auxUX(ndof_ux), auxUY(ndof_uy);
889 if (version & model::BUILD_MATRIX) {
891 base_matrix auxUYN(ndof_uy, N);
892 base_matrix auxLXN1(ndof_lx, N), auxLXN2(ndof_lx, N);
894 aug_friction_grad(lambda, g, gpp.Vs(), nx, r, f_coeff, F, dlambdaF,
898 const base_tensor &vgrad_base_ux = gpp.vgrad_base_ux();
899 base_matrix graddeltaunx(ndof_ux, N);
903 graddeltaunx(i, j) += nx[k] * vgrad_base_ux(i, k, j);
905 #define CONSIDER_TERM1
906 #define CONSIDER_TERM2
907 #define CONSIDER_TERM3
910 #ifdef CONSIDER_TERM1
913 gmm::mult(gpp.vbase_ux(), gmm::transposed(gpp.vbase_lx()), Melem);
914 gmm::scale(Melem, -weight);
915 mat_elem_assembly(M, I_ux, I_lx, Melem, *mf_ux, cvx, *mf_lx, cvx);
918 #ifdef CONSIDER_TERM2
923 gmm::mult(gpp.vbase_uy(), gmm::transposed(gpp.vbase_lx()), Melem);
924 gmm::scale(Melem, weight);
925 mat_elem_assembly(M, I_uy, I_lx, Melem, *mf_uy, cvy, *mf_lx, cvx);
929 const base_tensor &vgrad_base_uy = gpp.vgrad_base_uy();
933 auxUYN(i, j) += lambda[k] * vgrad_base_uy(i, k, j);
934 base_matrix lgraddeltavgradphiyinv(ndof_uy, N);
935 gmm::mult(auxUYN, gpp.grad_phiy_inv(), lgraddeltavgradphiyinv);
939 gmm::mult(lgraddeltavgradphiyinv, gpp.I_nxny(), auxUYN);
940 gmm::mult(auxUYN, gmm::transposed(gpp.vbase_uy()), Melem);
942 gmm::scale(Melem, -weight);
943 mat_elem_assembly(M, I_uy, I_uy, Melem, *mf_uy, cvy, *mf_uy, cvy);
949 gmm::mult(auxUYN, gmm::transposed(gpp.vbase_ux()), Melem);
952 base_matrix auxUYUX(ndof_uy, ndof_ux);
953 gmm::mult(gpp.I_nxny(), gmm::transposed(gpp.grad_phix_inv()), auxNN1);
954 gmm::mult(lgraddeltavgradphiyinv, auxNN1, auxUYN);
955 gmm::mult(auxUYN, gmm::transposed(graddeltaunx), auxUYUX);
956 gmm::scale(auxUYUX, -g);
957 gmm::add(auxUYUX, Melem);
958 gmm::scale(Melem, weight);
959 mat_elem_assembly(M, I_uy, I_ux, Melem, *mf_uy, cvy, *mf_ux, cvx);
965 #ifdef CONSIDER_TERM3
971 gmm::copy(gmm::scaled(dlambdaF, scalar_type(-1)/r), auxNN1);
972 gmm::mult(gpp.vbase_lx(), auxNN1, auxLXN1);
973 gmm::mult(auxLXN1, gmm::transposed(gpp.vbase_lx()), Melem);
974 gmm::scale(Melem, weight*FMULT);
975 mat_elem_assembly(M, I_lx, I_lx, Melem, *mf_lx, cvx, *mf_lx, cvx);
980 gmm::mult(gpp.vbase_lx(), dnF, auxLXN1);
981 gmm::mult(auxLXN1, gpp.I_nxnx(), auxLXN2);
982 gmm::mult(auxLXN2, gmm::transposed(gpp.grad_phix_inv()), auxLXN1);
983 gmm::mult(auxLXN1, gmm::transposed(graddeltaunx), Melem);
984 gmm::scale(Melem, scalar_type(1)/r);
988 base_vector deltamudgF(ndof_lx);
989 gmm::mult(gpp.vbase_lx(),
990 gmm::scaled(dgF, scalar_type(1)/(r*gpp.nxdotny())),
994 gmm::mult(gpp.vbase_ux(), ny, auxUX);
997 gmm::mult(gpp.I_nxnx(), gmm::scaled(ny, -g), auxN1);
998 gmm::mult(gpp.grad_phix_inv(), auxN1, auxN2);
1000 gmm::rank_one_update(Melem, deltamudgF, auxUX);
1001 gmm::scale(Melem, weight*FMULT);
1002 mat_elem_assembly(M, I_lx, I_ux, Melem, *mf_lx, cvx, *mf_ux, cvx);
1008 gmm::mult(gpp.vbase_uy(), ny, auxUY);
1009 gmm::rank_one_update(Melem, deltamudgF, auxUY);
1010 gmm::scale(Melem, -weight*FMULT);
1011 mat_elem_assembly(M, I_lx, I_uy, Melem, *mf_lx, cvx, *mf_uy, cvy);
1014 if (alpha != scalar_type(0)) {
1018 #ifdef CONSIDER_FRAME_INDIFFERENCE
1019 base_matrix gphiy0gphiyinv(N, N);
1020 gmm::mult(gpp.grad_phiy0(), gpp.grad_phiy_inv(), gphiy0gphiyinv);
1021 gmm::mult(gphiy0gphiyinv, gpp.I_nxny(), auxNN1);
1022 gmm::rank_one_update(auxNN1, gpp.nx0(),
1023 gmm::scaled(gpp.ny(),scalar_type(1)/gpp.nxdotny()));
1024 gmm::mult(dVsF, auxNN1, auxNN2);
1030 gmm::mult(gpp.vbase_lx(), gmm::transposed(auxNN2), auxLXN1);
1032 gmm::mult(auxLXN1, gmm::transposed(gpp.vbase_ux()), Melem);
1035 base_matrix auxLXUX(ndof_lx, ndof_ux);
1036 gmm::mult(auxNN2, gpp.I_nxnx(), auxNN1);
1037 gmm::mult(auxNN1, gmm::transposed(gpp.grad_phix_inv()), auxNN2);
1038 gmm::mult(gpp.vbase_lx(), gmm::transposed(auxNN2), auxLXN2);
1039 gmm::mult(auxLXN2, gmm::transposed(graddeltaunx), auxLXUX);
1040 gmm::scale(auxLXUX, -g);
1041 gmm::add(auxLXUX, Melem);
1042 gmm::scale(Melem, -weight*alpha*FMULT/r);
1043 mat_elem_assembly(M, I_lx, I_ux, Melem, *mf_lx, cvx, *mf_ux, cvx);
1049 gmm::mult(auxLXN1, gmm::transposed(gpp.vbase_uy()), Melem);
1050 gmm::scale(Melem, weight*alpha*FMULT/r);
1051 mat_elem_assembly(M, I_lx, I_uy, Melem, *mf_lx, cvx, *mf_uy, cvy);
1053 base_matrix I_gphiy0gphiyinv(N, N);
1054 gmm::mult(gmm::scaled(gpp.grad_phiy0(), scalar_type(-1)),
1055 gpp.grad_phiy_inv(), I_gphiy0gphiyinv);
1056 gmm::add(gmm::identity_matrix(), I_gphiy0gphiyinv);
1061 gmm::mult(I_gphiy0gphiyinv, gpp.I_nxny(), auxNN1);
1062 for (
size_type j = 0; j < N; ++j) auxNN1(j,j) -= scalar_type(1);
1063 gmm::mult(dVsF, auxNN1, auxNN2);
1064 gmm::mult(gpp.vbase_lx(), gmm::transposed(auxNN2), auxLXN2);
1066 gmm::mult(auxLXN2, gmm::transposed(gpp.vbase_ux()), Melem);
1069 base_matrix auxLXUX(ndof_lx, ndof_ux);
1070 gmm::mult(dVsF, I_gphiy0gphiyinv, auxNN1);
1071 gmm::mult(auxNN1, gpp.I_nxny(), auxNN2);
1072 gmm::mult(auxNN2, gmm::transposed(gpp.grad_phix_inv()), auxNN1);
1073 gmm::mult(gpp.vbase_lx(), gmm::transposed(auxNN1), auxLXN1);
1074 gmm::mult(auxLXN1, gmm::transposed(graddeltaunx), auxLXUX);
1075 gmm::scale(auxLXUX, -g);
1076 gmm::add(auxLXUX, Melem);
1077 gmm::scale(Melem, weight*alpha*FMULT/r);
1078 mat_elem_assembly(M, I_lx, I_ux, Melem, *mf_lx, cvx, *mf_ux, cvx);
1084 gmm::mult(auxLXN2, gmm::transposed(gpp.vbase_uy()), Melem);
1085 gmm::scale(Melem, -weight*alpha*FMULT/r);
1086 mat_elem_assembly(M, I_lx, I_uy, Melem, *mf_lx, cvx, *mf_uy, cvy);
1090 gmm::mult(gpp.vbase_lx(), gmm::transposed(dVsF), auxLXN1);
1091 gmm::mult(auxLXN1, gmm::transposed(gpp.vbase_ux()), Melem);
1092 gmm::scale(Melem, -weight*alpha*FMULT/r);
1093 mat_elem_assembly(M, I_lx, I_ux, Melem, *mf_lx, cvx, *mf_ux, cvx);
1099 if (version & model::BUILD_RHS) {
1101 if (!(version & model::BUILD_MATRIX))
1102 aug_friction(lambda, g, gpp.Vs(), nx, r, f_coeff, F);
1104 #ifdef CONSIDER_TERM1
1107 gmm::mult(gpp.vbase_ux(), lambda, auxUX);
1108 gmm::scale(auxUX, weight);
1109 vec_elem_assembly(V, I_ux, auxUX, *mf_ux, cvx);
1112 #ifdef CONSIDER_TERM2
1116 gmm::mult(gpp.vbase_uy(), lambda, auxUY);
1117 gmm::scale(auxUY, -weight);
1118 vec_elem_assembly(V, I_uy, auxUY, *mf_uy, cvy);
1122 #ifdef CONSIDER_TERM3
1126 base_vector auxLX(ndof_lx);
1127 gmm::mult(gpp.vbase_lx(), gmm::scaled(F, weight*FMULT/r), auxLX);
1128 vec_elem_assembly(V, I_lx, auxLX, *mf_lx, cvx);
1138 const std::string &dataname_r,
const std::string &dataname_friction_coeff,
1139 const std::string &dataname_alpha) {
1141 bool with_friction = (dataname_friction_coeff.size() > 0);
1143 = std::make_shared<integral_large_sliding_contact_brick>(mcf,
1147 tl.push_back(model::term_description(
true,
false));
1149 model::varnamelist dl(1, dataname_r);
1150 if (with_friction) dl.push_back(dataname_friction_coeff);
1151 if (dataname_alpha.size()) dl.push_back(dataname_alpha);
1153 model::varnamelist vl;
1155 bool selfcontact = mcf.is_self_contact();
1157 dal::bit_vector uvar, mvar;
1158 for (
size_type i = 0; i < mcf.nb_boundaries(); ++i) {
1159 size_type ind_u = mcf.ind_varname_of_boundary(i);
1160 if (!(uvar.is_in(ind_u))) {
1161 vl.push_back(mcf.varname(ind_u));
1164 size_type ind_lambda = mcf.ind_multname_of_boundary(i);
1166 if (selfcontact || mcf.is_slave_boundary(i))
1167 GMM_ASSERT1(ind_lambda !=
size_type(-1),
"Large sliding contact "
1168 "brick: a multiplier should be associated to each slave "
1169 "boundary in the multi_contact_frame object.");
1170 if (ind_lambda !=
size_type(-1) && !(mvar.is_in(ind_lambda))) {
1171 vl.push_back(mcf.multname(ind_lambda));
1190 #include <getfem/getfem_arch_config.h>
1191 #if GETFEM_HAVE_MUPARSER_MUPARSER_H
1192 #include <muParser/muParser.h>
1193 #elif GETFEM_HAVE_MUPARSER_H
1194 #include <muParser.h>
1202 struct contact_frame {
1205 scalar_type friction_coef;
1206 std::vector<const model_real_plain_vector *> Us;
1207 std::vector<model_real_plain_vector> ext_Us;
1208 std::vector<const model_real_plain_vector *> lambdas;
1209 std::vector<model_real_plain_vector> ext_lambdas;
1210 struct contact_boundary {
1217 std::vector<contact_boundary> contact_boundaries;
1219 gmm::dense_matrix< model_real_sparse_matrix * > UU;
1220 gmm::dense_matrix< model_real_sparse_matrix * > UL;
1221 gmm::dense_matrix< model_real_sparse_matrix * > LU;
1222 gmm::dense_matrix< model_real_sparse_matrix * > LL;
1224 std::vector< model_real_plain_vector *> Urhs;
1225 std::vector< model_real_plain_vector *> Lrhs;
1229 std::vector<std::string> coordinates;
1231 #if GETFEM_HAVE_MUPARSER_MUPARSER_H || GETFEM_HAVE_MUPARSER_H
1232 std::vector<mu::Parser> obstacles_parsers;
1234 std::vector<std::string> obstacles;
1235 std::vector<std::string> obstacles_velocities;
1238 const model_real_plain_vector &U) {
1240 for (; i < Us.size(); ++i)
if (Us[i] == &U)
return i;
1243 mfu.extend_vector(U, ext_U);
1244 ext_Us.push_back(ext_U);
1249 const model_real_plain_vector &l) {
1251 for (; i < lambdas.size(); ++i)
if (lambdas[i] == &l)
return i;
1252 lambdas.push_back(&l);
1254 mfl.extend_vector(l, ext_l);
1255 ext_lambdas.push_back(ext_l);
1259 void extend_vectors(
void) {
1260 for (
size_type i = 0; i < contact_boundaries.size(); ++i) {
1261 size_type ind_U = contact_boundaries[i].ind_U;
1262 contact_boundaries[i].mfu->extend_vector(*(Us[ind_U]), ext_Us[ind_U]);
1263 size_type ind_lambda = contact_boundaries[i].ind_lambda;
1264 contact_boundaries[i].mflambda->extend_vector(*(lambdas[ind_lambda]),
1265 ext_lambdas[ind_lambda]);
1271 {
return *(contact_boundaries[n].mfu); }
1273 {
return *(contact_boundaries[n].mflambda); }
1274 const model_real_plain_vector &disp_of_boundary(
size_type n)
const
1275 {
return ext_Us[contact_boundaries[n].ind_U]; }
1276 const model_real_plain_vector &lambda_of_boundary(
size_type n)
const
1277 {
return ext_lambdas[contact_boundaries[n].ind_lambda]; }
1279 {
return contact_boundaries[n].region; }
1281 {
return *(UU(contact_boundaries[n].ind_U, contact_boundaries[m].ind_U)); }
1283 return *(LU(contact_boundaries[n].ind_lambda,
1284 contact_boundaries[m].ind_U));
1287 return *(UL(contact_boundaries[n].ind_U,
1288 contact_boundaries[m].ind_lambda));
1291 return *(LL(contact_boundaries[n].ind_lambda,
1292 contact_boundaries[m].ind_lambda));
1294 model_real_plain_vector &U_vector(
size_type n)
const
1295 {
return *(Urhs[contact_boundaries[n].ind_U]); }
1296 model_real_plain_vector &L_vector(
size_type n)
const
1297 {
return *(Lrhs[contact_boundaries[n].ind_lambda]); }
1299 contact_frame(
size_type NN) : N(NN), coordinates(N), pt_eval(N) {
1300 if (N > 0) coordinates[0] =
"x";
1301 if (N > 1) coordinates[1] =
"y";
1302 if (N > 2) coordinates[2] =
"z";
1303 if (N > 3) coordinates[3] =
"w";
1304 GMM_ASSERT1(N <= 4,
"Complete the definition for contact in "
1305 "dimension greater than 4");
1308 size_type add_obstacle(
const std::string &obs) {
1310 obstacles.push_back(obs);
1311 obstacles_velocities.push_back(
"");
1312 #if GETFEM_HAVE_MUPARSER_MUPARSER_H || GETFEM_HAVE_MUPARSER_H
1315 obstacles_parsers.push_back(mu);
1316 obstacles_parsers[ind].SetExpr(obstacles[ind]);
1318 obstacles_parsers[ind].DefineVar(coordinates[k], &pt_eval[k]);
1320 GMM_ASSERT1(
false,
"You have to link muparser with getfem to deal "
1321 "with rigid body obstacles");
1327 const model_real_plain_vector &U,
1329 const model_real_plain_vector &l,
1331 contact_boundary cb;
1335 cb.ind_U = add_U(mfu, U);
1336 cb.ind_lambda = add_lambda(mfl, l);
1337 size_type ind = contact_boundaries.size();
1338 contact_boundaries.push_back(cb);
1355 struct contact_elements {
1362 std::vector<size_type> boundary_of_elements;
1363 std::vector<size_type> ind_of_elements;
1364 std::vector<size_type> face_of_elements;
1365 std::vector<base_node> unit_normal_of_elements;
1367 contact_elements(contact_frame &ccf) : cf(ccf) {}
1369 bool add_point_contribution(
size_type boundary_num,
1372 scalar_type weight, scalar_type f_coeff,
1373 scalar_type r, model::build_version version);
1377 void contact_elements::init(
void) {
1378 fem_precomp_pool fppool;
1381 element_boxes.clear();
1382 unit_normal_of_elements.resize(0);
1383 boundary_of_elements.resize(0);
1384 ind_of_elements.resize(0);
1385 face_of_elements.resize(0);
1389 model_real_plain_vector coeff;
1390 cf.extend_vectors();
1391 for (
size_type i = 0; i < cf.contact_boundaries.size(); ++i) {
1392 size_type bnum = cf.region_of_boundary(i);
1393 const mesh_fem &mfu = cf.mfu_of_boundary(i);
1394 const model_real_plain_vector &U = cf.disp_of_boundary(i);
1395 const mesh &m = mfu.linked_mesh();
1396 if (i == 0) N = m.dim();
1397 GMM_ASSERT1(m.dim() == N,
1398 "Meshes are of mixed dimensions, cannot deal with that");
1399 base_node val(N), bmin(N), bmax(N), n0(N), n(N), n_mean(N);
1400 base_matrix grad(N,N);
1401 mesh_region region = m.region(bnum);
1402 GMM_ASSERT1(mfu.get_qdim() == N,
1403 "Wrong mesh_fem qdim to compute contact pairs");
1405 dal::bit_vector points_already_interpolated;
1406 std::vector<base_node> transformed_points(m.nb_max_points());
1410 pfem pf_s = mfu.fem_of_element(cv);
1413 bgeot::vectors_to_base_matrix
1414 (G, mfu.linked_mesh().points_of_convex(cv));
1416 pfem_precomp pfp = fppool(pf_s, &(pgt->geometric_nodes()));
1417 fem_interpolation_context ctx(pgt, pfp,
size_type(-1), G, cv);
1422 size_type ind = m.ind_points_of_convex(cv)[ip];
1425 if (!(points_already_interpolated.is_in(ind))) {
1427 pf_s->interpolation(ctx, coeff, val, dim_type(N));
1429 transformed_points[ind] = val;
1430 points_already_interpolated.add(ind);
1432 val = transformed_points[ind];
1435 bool is_on_face =
false;
1437 for (
size_type k = 0; k < cvs->nb_points_of_face(v.f()); ++k)
1438 if (cvs->ind_points_of_face(v.f())[k] == ip) is_on_face =
true;
1442 pf_s->interpolation_grad(ctx, coeff, grad, dim_type(N));
1443 gmm::add(gmm::identity_matrix(), grad);
1444 scalar_type J = bgeot::lu_inverse(&(*(grad.begin())), N);
1445 if (J <= scalar_type(0)) GMM_WARNING1(
"Inverted element ! " << J);
1446 gmm::mult(gmm::transposed(grad), n0, n);
1456 bmin[k] = std::min(bmin[k], val[k]);
1457 bmax[k] = std::max(bmax[k], val[k]);
1462 GMM_ASSERT1(nb_pt_on_face,
1463 "This element has not vertex on considered face !");
1467 scalar_type h = bmax[0] - bmin[0];
1469 h = std::max(h, bmax[k] - bmin[k]);
1471 { bmin[k] -= h; bmax[k] += h; }
1474 element_boxes.add_box(bmin, bmax, unit_normal_of_elements.size());
1476 unit_normal_of_elements.push_back(n_mean);
1477 boundary_of_elements.push_back(i);
1478 ind_of_elements.push_back(cv);
1479 face_of_elements.push_back(v.f());
1482 element_boxes.build_tree();
1487 bool contact_elements::add_point_contribution
1490 scalar_type , scalar_type r, model::build_version version) {
1491 const mesh_fem &mfu = cf.mfu_of_boundary(boundary_num);
1492 const mesh_fem &mfl = cf.mflambda_of_boundary(boundary_num);
1493 const model_real_plain_vector &U = cf.disp_of_boundary(boundary_num);
1494 const model_real_plain_vector &L = cf.lambda_of_boundary(boundary_num);
1496 base_node x0 = ctxu.
xreal();
1507 base_small_vector n(N), val(N), h(N);
1508 base_matrix gradinv(N,N), grad(N,N), gradtot(N,N), G;
1509 size_type cvnbdofu = mfu.nb_basic_dof_of_element(cv);
1510 size_type cvnbdofl = mfl.nb_basic_dof_of_element(cv);
1511 base_vector coeff(cvnbdofu);
1513 ctxu.
pf()->interpolation(ctxu, coeff, val, dim_type(N));
1514 base_node x = x0 + val;
1516 ctxu.
pf()->interpolation_grad(ctxu, coeff, gradinv, dim_type(N));
1517 gmm::add(gmm::identity_matrix(), gradinv);
1518 scalar_type J = bgeot::lu_inverse(&(*(grad_inv.begin())), N);
1519 if (J <= scalar_type(0)) {
1520 GMM_WARNING1(
"Inverted element !");
1522 GMM_ASSERT1(!(version & model::BUILD_MATRIX),
"Impossible to build "
1523 "tangent matrix for large sliding contact");
1524 if (version & model::BUILD_RHS) {
1525 base_vector Velem(cvnbdofl);
1526 for (
size_type i = 0; i < cvnbdofl; ++i) Velem[i] = 1E200;
1527 vec_elem_assembly(cf.L_vector(boundary_num), Velem, mfl, cv);
1532 gmm::mult(gmm::transposed(gradinv), n0, n);
1539 bgeot::rtree::pbox_set bset;
1540 element_boxes.find_boxes_at_point(x, bset);
1542 if (noisy) cout <<
"Number of boxes found : " << bset.size() << endl;
1549 bgeot::rtree::pbox_set::iterator it = bset.begin(), itnext;
1550 for (; it != bset.end(); it = itnext) {
1551 itnext = it; ++itnext;
1552 if (gmm::vect_sp(unit_normal_of_elements[(*it)->id], n)
1553 >= -scalar_type(1)/scalar_type(20)) bset.erase(it);
1557 cout <<
"Number of boxes satisfying the unit normal criterion : "
1558 << bset.size() << endl;
1568 std::vector<base_node> y0s;
1569 std::vector<base_small_vector> n0_y0s;
1570 std::vector<scalar_type> d0s;
1571 std::vector<scalar_type> d1s;
1572 std::vector<size_type> elt_nums;
1573 std::vector<fem_interpolation_context> ctx_y0s;
1574 for (; it != bset.end(); ++it) {
1575 size_type boundary_num_y0 = boundary_of_elements[(*it)->id];
1576 size_type cv_y0 = ind_of_elements[(*it)->id];
1578 const mesh_fem &mfu_y0 = cf.mfu_of_boundary(boundary_num_y0);
1579 pfem pf_s_y0 = mfu_y0.fem_of_element(cv_y0);
1580 const model_real_plain_vector &U_y0
1581 = cf.disp_of_boundary(boundary_num_y0);
1582 const mesh &m_y0 = mfu_y0.linked_mesh();
1589 for (; ind_dep_point < cvs_y0->nb_points(); ++ind_dep_point) {
1590 bool is_on_face =
false;
1592 k < cvs_y0->nb_points_of_face(face_y0); ++k)
1593 if (cvs_y0->ind_points_of_face(face_y0)[k]
1594 == ind_dep_point) is_on_face =
true;
1595 if (!is_on_face)
break;
1597 GMM_ASSERT1(ind_dep_point < cvs_y0->nb_points(),
1598 "No interior point found !");
1600 base_node y0_ref = pgt_y0->convex_ref()->points()[ind_dep_point];
1604 bgeot::vectors_to_base_matrix(G, m_y0.points_of_convex(cv_y0));
1606 fem_interpolation_context ctx_y0(pgt_y0, pf_s_y0, y0_ref, G, cv_y0);
1611 pf_s_y0->interpolation(ctx_y0, coeff, val, dim_type(N));
1612 val += ctx_y0.xreal() - x;
1615 if (init_res < 1E-12)
break;
1616 if (newton_iter > 100) {
1617 GMM_WARNING1(
"Newton has failed to invert transformation");
1618 GMM_ASSERT1(!(version & model::BUILD_MATRIX),
"Impossible to build "
1619 "tangent matrix for large sliding contact");
1620 if (version & model::BUILD_RHS) {
1621 base_vector Velem(cvnbdofl);
1622 for (
size_type i = 0; i < cvnbdofl; ++i) Velem[i] = 1E200;
1623 vec_elem_assembly(cf.L_vector(boundary_num), Velem, mfl, cv);
1628 pf_s_y0->interpolation_grad(ctx_y0, coeff, grad, dim_type(N));
1629 gmm::add(gmm::identity_matrix(), grad);
1630 gmm::mult(grad, ctx_y0.K(), gradtot);
1632 std::vector<long> ipvt(N);
1634 GMM_ASSERT1(!info,
"Singular system, pivot = " << info);
1635 gmm::lu_solve(gradtot, ipvt, h, val);
1640 for (alpha = 1;
alpha >= 1E-5;
alpha/=scalar_type(2)) {
1642 ctx_y0.set_xref(y0_ref - alpha*h);
1643 pf_s_y0->interpolation(ctx_y0, coeff, val, dim_type(N));
1644 val += ctx_y0.xreal() - x;
1646 if (gmm::vect_norm2(val) < init_res) { ok =
true;
break; }
1649 GMM_WARNING1(
"Line search has failed to invert transformation");
1651 ctx_y0.set_xref(y0_ref);
1655 base_node y0 = ctx_y0.xreal();
1657 scalar_type d0_ref = pgt_y0->convex_ref()->is_in_face(face_y0, y0_ref);
1661 scalar_type d1 = d0_ref;
1664 for (
short_type k = 0; k < pgt_y0->structure()->nb_faces(); ++k) {
1665 scalar_type dd = pgt_y0->convex_ref()->is_in_face(k, y0_ref);
1666 if (dd > scalar_type(0) && dd > gmm::abs(d1)) { d1 = dd; ifd = k; }
1671 if (gmm::abs(d1) < gmm::abs(d0)) d1 = d0;
1678 if (noisy) cout <<
"gmm::vect_norm2(n0_y0) = " <<
gmm::vect_norm2(n0_y0) << endl;
1680 if (noisy) cout <<
"autocontact status : x0 = " << x0 <<
" y0 = " << y0 <<
" " <<
gmm::vect_dist2(y0, x0) <<
" : " << d0*0.75 <<
" : " << d1*0.75 << endl;
1681 if (noisy) cout <<
"n = " << n <<
" unit_normal_of_elements[(*it)->id] = " << unit_normal_of_elements[(*it)->id] << endl;
1683 if (d0 < scalar_type(0)
1685 && (gmm::vect_dist2(y0, x0) < gmm::abs(d1)*scalar_type(3)/scalar_type(4)))
1686 || gmm::abs(d1) > 0.05)) {
1687 if (noisy) cout <<
"Eliminated x0 = " << x0 <<
" y0 = " << y0
1688 <<
" d0 = " << d0 << endl;
1700 y0s.push_back(ctx_y0.xreal());
1701 elt_nums.push_back((*it)->id);
1704 ctx_y0s.push_back(ctx_y0);
1706 n0_y0s.push_back(n0_y0);
1708 if (noisy) cout <<
"dist0 = " << d0 <<
" dist0 * area = "
1709 << pgt_y0->convex_ref()->is_in(y0_ref) << endl;
1718 scalar_type d0 = 1E100, d1 = 1E100;
1719 base_small_vector grad_obs(N);
1722 for (
size_type k = 0; k < y0s.size(); ++k)
1723 if (d1s[k] < d1) { d0 = d0s[k]; d1 = d1s[k]; ibound = k; state = 1; }
1727 #if GETFEM_HAVE_MUPARSER_MUPARSER_H || GETFEM_HAVE_MUPARSER_H
1728 gmm::copy(x, cf.pt_eval);
1729 for (
size_type i = 0; i < cf.obstacles.size(); ++i) {
1730 scalar_type d0_o = scalar_type(cf.obstacles_parsers[i].Eval());
1731 if (d0_o < d0) { d0 = d0_o; irigid_obstacle = i; state = 2; }
1734 scalar_type EPS = face_factor * 1E-9;
1736 cf.pt_eval[k] += EPS;
1738 (scalar_type(cf.obstacles_parsers[irigid_obstacle].Eval())-d0)/EPS;
1739 cf.pt_eval[k] -= EPS;
1744 if (cf.obstacles.size() > 0)
1745 GMM_WARNING1(
"Rigid obstacles are ignored. Recompile with "
1746 "muParser to account for rigid obstacles");
1755 if (noisy && state == 1) {
1756 cout <<
"Point : " << x0 <<
" of boundary " << boundary_num
1757 <<
" and element " << cv <<
" state = " << int(state);
1758 if (version & model::BUILD_RHS) cout <<
" RHS";
1759 if (version & model::BUILD_MATRIX) cout <<
" MATRIX";
1762 size_type boundary_num_y0 = boundary_of_elements[elt_nums[ibound]];
1763 const mesh_fem &mfu_y0 = cf.mfu_of_boundary(boundary_num_y0);
1764 const mesh &m_y0 = mfu_y0.linked_mesh();
1765 size_type cv_y0 = ind_of_elements[elt_nums[ibound]];
1767 if (noisy) cout <<
" y0 = " << y0s[ibound] <<
" of element "
1768 << cv_y0 <<
" of boundary " << boundary_num_y0 << endl;
1769 for (
size_type k = 0; k < m_y0.nb_points_of_convex(cv_y0); ++k)
1770 if (noisy) cout <<
"point " << k <<
" : "
1771 << m_y0.points()[m_y0.ind_points_of_convex(cv_y0)[k]] << endl;
1772 if (boundary_num_y0 == 0 && boundary_num == 0 && d0 < 0.0 && (version & model::BUILD_MATRIX)) GMM_ASSERT1(
false,
"oups");
1774 if (noisy) cout <<
" d0 = " << d0 << endl;
1780 GMM_ASSERT1(ctxu.
pf()->target_dim() == 1 && ctxl.
pf()->target_dim() == 1,
1781 "Large sliding contact assembly procedure has to be adapted "
1782 "to intrinsic vectorial elements. To be done.");
1794 base_small_vector lambda(N);
1796 ctxl.
pf()->interpolation(ctxl, coeff, lambda, dim_type(N));
1797 GMM_ASSERT1(!(isnan(lambda[0])),
"internal error");
1802 scalar_type aux1, aux2;
1807 base_small_vector zeta(N);
1808 gmm::add(lambda, gmm::scaled(n, r*d0), zeta);
1815 size_type boundary_num_y0 = 0, cv_y0 = 0, cvnbdofu_y0 = 0;
1817 ctx_y0s[ibound].base_value(tu_y0);
1818 boundary_num_y0 = boundary_of_elements[elt_nums[ibound]];
1819 cv_y0 = ind_of_elements[elt_nums[ibound]];
1820 cvnbdofu_y0 = cf.mfu_of_boundary(boundary_num_y0).nb_basic_dof_of_element(cv_y0);
1822 const mesh_fem &mfu_y0 = (state == 1) ?
1823 cf.mfu_of_boundary(boundary_num_y0) : mfu;
1825 if (version & model::BUILD_RHS) {
1830 base_small_vector vecaux(N);
1831 gmm::copy(zeta, vecaux);
1832 De_Saxce_projection(vecaux, n, scalar_type(0));
1833 gmm::scale(vecaux, -scalar_type(1));
1834 gmm::add(lambda, vecaux);
1835 for (
size_type i = 0; i < cvnbdofl; ++i)
1836 Velem[i] = tl[i/N] * vecaux[i%N] * weight/r;
1837 vec_elem_assembly(cf.L_vector(boundary_num), Velem, mfl, cv);
1841 for (
size_type i = 0; i < cvnbdofu; ++i)
1842 Velem[i] = tu[i/N] * lambda[i%N] * weight;
1843 vec_elem_assembly(cf.U_vector(boundary_num), Velem, mfu, cv);
1847 for (
size_type i = 0; i < cvnbdofu_y0; ++i)
1848 Velem[i] = -tu_y0[i/N] * lambda[i%N] * weight;
1849 vec_elem_assembly(cf.U_vector(boundary_num_y0), Velem, mfu_y0, cv_y0);
1853 if (version & model::BUILD_MATRIX) {
1855 base_small_vector gradinv_n(N);
1856 gmm::mult(gradinv, n, gradinv_n);
1859 base_matrix pgrad(N,N), pgradn(N,N);
1860 De_Saxce_projection_grad(zeta, n, scalar_type(0), pgrad);
1861 De_Saxce_projection_gradn(zeta, n, scalar_type(0), pgradn);
1863 base_small_vector pgrad_n(N), pgradn_n(N);
1864 gmm::mult(pgrad, n, pgrad_n);
1865 gmm::mult(pgradn, n, pgradn_n);
1866 base_matrix gradinv_pgrad(N,N), gradinv_pgradn(N,N);
1867 gmm::mult(gradinv, gmm::transposed(pgrad), gradinv_pgrad);
1868 gmm::mult(gradinv, gmm::transposed(pgradn), gradinv_pgradn);
1873 for (
size_type i = 0; i < cvnbdofl; i += N) {
1874 aux1 = -tl[i/N] * weight/r;
1875 for (
size_type j = 0; j < cvnbdofl; j += N) {
1876 aux2 = aux1 * tl[j/N];
1877 for (
size_type k = 0; k < N; k++) Melem(i+k,j+k) = aux2;
1881 for (
size_type i = 0, ii = 0; i < cvnbdofl; ++i, ii = i%N)
1882 for (
size_type j = 0, jj = 0; j < cvnbdofl; ++j, jj = j%N)
1883 Melem(i,j) += tl[i/N] * tl[j/N] * pgrad(ii,jj) * weight/r;
1884 mat_elem_assembly(cf.LL_matrix(boundary_num, boundary_num),
1885 Melem, mfl, cv, mfl, cv);
1890 for (
size_type i = 0; i < cvnbdofu; i += N) {
1891 aux1 = -tu[i/N] * weight;
1892 for (
size_type j = 0; j < cvnbdofl; j += N) {
1893 aux2 = aux1 * tl[j/N];
1894 for (
size_type k = 0; k < N; k++) Melem(i+k,j+k) = aux2;
1897 mat_elem_assembly(cf.UL_matrix(boundary_num, boundary_num),
1898 Melem, mfu, cv, mfl, cv);
1904 for (
size_type i = 0, ii = 0; i < cvnbdofl; ++i, ii = i%N)
1905 for (
size_type j = 0, jj = 0; j < cvnbdofu; ++j, jj = j%N) {
1906 aux1 = aux2 = scalar_type(0);
1908 aux1 += tgradu[j/N+N*k] * gradinv_n[k];
1909 aux2 += tgradu[j/N+N*k] * gradinv_pgrad(k,ii);
1911 Melem(i,j) = d0 * tl[i/N] * (pgrad_n[ii] * aux1 - aux2) * n[jj] * weight;
1917 for (
size_type i = 0, ii = 0; i < cvnbdofl; ++i, ii = i%N)
1918 for (
size_type j = 0, jj = 0; j < cvnbdofu; ++j, jj = j%N) {
1919 aux1 = aux2 = scalar_type(0);
1921 aux1 += tgradu[j/N+N*k] * gradinv_n[k];
1922 aux2 += tgradu[j/N+N*k] * gradinv_pgradn(k,ii);
1924 Melem(i,j) += tl[i/N] * (pgradn_n[ii] * aux1 - aux2) * n[jj] * weight / r;
1926 mat_elem_assembly(cf.LU_matrix(boundary_num, boundary_num),
1927 Melem, mfl, cv, mfu, cv);
1932 base_tensor tgradu_y0;
1933 ctx_y0s[ibound].grad_base_value(tgradu_y0);
1935 base_matrix gradinv_y0(N,N);
1936 base_small_vector ntilde_y0(N);
1938 base_matrix grad_y0(N,N);
1939 base_vector coeff_y0(cvnbdofu_y0);
1940 const model_real_plain_vector &U_y0
1941 = cf.disp_of_boundary(boundary_num_y0);
1943 ctx_y0s[ibound].pf()->interpolation_grad(ctx_y0s[ibound], coeff_y0,
1944 grad_y0, dim_type(N));
1945 gmm::add(gmm::identity_matrix(), grad_y0);
1947 gmm::copy(grad_y0, gradinv_y0);
1948 gmm::lu_inverse(gradinv_y0);
1949 gmm::mult(gmm::transposed(gradinv_y0), n0_y0s[ibound], ntilde_y0);
1954 for (
size_type i = 0; i < cvnbdofu_y0; i += N) {
1955 aux1 = tu_y0[i/N] * weight;
1956 for (
size_type j = 0; j < cvnbdofl; j += N) {
1957 aux2 = aux1 * tl[j/N];
1958 for (
size_type k = 0; k < N; k++) Melem(i+k,j+k) = aux2;
1961 mat_elem_assembly(cf.UL_matrix(boundary_num_y0, boundary_num),
1962 Melem, mfu_y0, cv_y0, mfl, cv);
1970 for (
size_type i = 0, ii = 0; i < cvnbdofu_y0; ++i, ii = i%N)
1971 for (
size_type j = 0, jj = 0; j < cvnbdofu; ++j, jj = j%N) {
1972 aux1 = scalar_type(0);
1974 aux1 += tgradu_y0[i/N+N*k]* gradinv_y0(k,jj);
1975 Melem(i,j) = lambda[ii] * aux1 * tu[j/N] * weight;
1977 mat_elem_assembly(cf.UU_matrix(boundary_num_y0, boundary_num),
1978 Melem, mfu_y0, cv_y0, mfu, cv);
1983 for (
size_type i = 0, ii = 0; i < cvnbdofu_y0; ++i, ii = i%N)
1984 for (
size_type j = 0, jj = 0; j < cvnbdofu_y0; ++j, jj = j%N) {
1985 aux1 = scalar_type(0);
1987 aux1 += tgradu_y0[i/N+N*k] * gradinv_y0(k,jj);
1988 Melem(i,j) = - lambda[ii] * aux1 * tu_y0[j/N] * weight;
1990 mat_elem_assembly(cf.UU_matrix(boundary_num_y0, boundary_num_y0),
1991 Melem, mfu_y0, cv_y0, mfu_y0, cv_y0);
1996 for (
size_type i = 0; i < cvnbdofl; ++i) {
1997 aux1 = tl[i/N] * pgrad_n[i%N] * weight;
1998 for (
size_type j = 0; j < cvnbdofu_y0; ++j)
1999 Melem(i,j) = - aux1 * tu_y0[j/N] * ntilde_y0[j%N];
2001 mat_elem_assembly(cf.LU_matrix(boundary_num, boundary_num_y0),
2002 Melem, mfl, cv, mfu_y0, cv_y0);
2007 for (
size_type i = 0; i < cvnbdofl; ++i) {
2008 aux1 = tl[i/N] * pgrad_n[i%N] * weight;
2009 for (
size_type j = 0; j < cvnbdofu; ++j)
2010 Melem(i,j) = aux1 * tu[j/N] * ntilde_y0[j%N];
2017 for (
size_type i = 0; i < cvnbdofl; ++i) {
2018 aux1 = tl[i/N] * pgrad_n[i%N] * weight;
2019 for (
size_type j = 0; j < cvnbdofu; ++j)
2020 Melem(i,j) = aux1 * tu[j/N] * grad_obs[j%N];
2023 mat_elem_assembly(cf.LU_matrix(boundary_num, boundary_num),
2024 Melem, mfl, cv, mfu, cv);
2031 if (version & model::BUILD_RHS) {
2033 for (
size_type i = 0; i < cvnbdofl; ++i)
2034 Velem[i] = tl[i/N] * lambda[i%N] * weight/r;
2035 vec_elem_assembly(cf.L_vector(boundary_num), Velem, mfl, cv);
2039 if (version & model::BUILD_MATRIX) {
2041 for (
size_type i = 0; i < cvnbdofl; i += N) {
2042 aux1 = -tl[i/N] * weight/r;
2043 for (
size_type j = 0; j < cvnbdofl; j += N) {
2044 aux2 = aux1 * tl[j/N];
2045 for (
size_type k = 0; k < N; k++) Melem(i+k,j+k) = aux2;
2048 mat_elem_assembly(cf.LL_matrix(boundary_num, boundary_num),
2049 Melem, mfl, cv, mfl, cv);
2060 struct integral_large_sliding_contact_brick_field_extension :
public virtual_brick {
2063 struct contact_boundary {
2065 std::string varname;
2066 std::string multname;
2070 std::vector<contact_boundary> boundaries;
2071 std::vector<std::string> obstacles;
2073 void add_boundary(
const std::string &varn,
const std::string &multn,
2075 contact_boundary cb;
2076 cb.region = region; cb.varname = varn; cb.multname = multn; cb.mim=&mim;
2077 boundaries.push_back(cb);
2080 void add_obstacle(
const std::string &obs)
2081 { obstacles.push_back(obs); }
2083 void build_contact_frame(
const model &md, contact_frame &cf)
const {
2084 for (
size_type i = 0; i < boundaries.size(); ++i) {
2085 const contact_boundary &cb = boundaries[i];
2086 cf.add_boundary(md.mesh_fem_of_variable(cb.varname),
2087 md.real_variable(cb.varname),
2088 md.mesh_fem_of_variable(cb.multname),
2089 md.real_variable(cb.multname), cb.region);
2091 for (
size_type i = 0; i < obstacles.size(); ++i)
2092 cf.add_obstacle(obstacles[i]);
2096 virtual void asm_real_tangent_terms(
const model &md,
size_type ,
2097 const model::varnamelist &vl,
2098 const model::varnamelist &dl,
2099 const model::mimlist &mims,
2100 model::real_matlist &matl,
2101 model::real_veclist &vecl,
2102 model::real_veclist &,
2104 build_version version)
const;
2106 integral_large_sliding_contact_brick_field_extension() {
2107 set_flags(
"Integral large sliding contact brick",
2118 void integral_large_sliding_contact_brick_field_extension::asm_real_tangent_terms
2119 (
const model &md,
size_type ,
const model::varnamelist &vl,
2120 const model::varnamelist &dl,
const model::mimlist &,
2121 model::real_matlist &matl, model::real_veclist &vecl,
2123 build_version version)
const {
2125 fem_precomp_pool fppool;
2127 size_type N = md.mesh_fem_of_variable(vl[0]).linked_mesh().dim();
2128 contact_frame cf(N);
2129 build_contact_frame(md, cf);
2131 size_type Nvar = vl.size(), Nu = cf.Urhs.size(), Nl = cf.Lrhs.size();
2132 GMM_ASSERT1(Nvar == Nu+Nl,
"Wrong size of variable list for integral "
2133 "large sliding contact brick");
2134 GMM_ASSERT1(matl.size() == Nvar*Nvar,
"Wrong size of terms for "
2135 "integral large sliding contact brick");
2137 if (version & model::BUILD_MATRIX) {
2141 if (i < Nu && j < Nu) cf.UU(i,j) = &(matl[i*Nvar+j]);
2142 if (i >= Nu && j < Nu) cf.LU(i-Nu,j) = &(matl[i*Nvar+j]);
2143 if (i < Nu && j >= Nu) cf.UL(i,j-Nu) = &(matl[i*Nvar+j]);
2144 if (i >= Nu && j >= Nu) cf.LL(i-Nu,j-Nu) = &(matl[i*Nvar+j]);
2147 if (version & model::BUILD_RHS) {
2148 for (
size_type i = 0; i < vl.size(); ++i) {
2149 if (i < Nu) cf.Urhs[i] = &(vecl[i*Nvar]);
2150 else cf.Lrhs[i-Nu] = &(vecl[i*Nvar]);
2155 GMM_ASSERT1(dl.size() == 2,
"Wrong number of data for integral large "
2156 "sliding contact brick");
2158 const model_real_plain_vector &vr = md.real_variable(dl[0]);
2159 GMM_ASSERT1(gmm::vect_size(vr) == 1,
"Parameter r should be a scalar");
2161 const model_real_plain_vector &f_coeff = md.real_variable(dl[1]);
2162 GMM_ASSERT1(gmm::vect_size(f_coeff) == 1,
2163 "Friction coefficient should be a scalar");
2165 contact_elements ce(cf);
2168 for (
size_type bnum = 0; bnum < boundaries.size(); ++bnum) {
2169 mesh_region rg(boundaries[bnum].region);
2170 const mesh_fem &mfu=md.mesh_fem_of_variable(boundaries[bnum].varname);
2171 const mesh_fem &mfl=md.mesh_fem_of_variable(boundaries[bnum].multname);
2172 const mesh_im &mim = *(boundaries[bnum].mim);
2173 const mesh &m = mfu.linked_mesh();
2174 mfu.linked_mesh().intersect_with_mpi_region(rg);
2180 pfem pf_s = mfu.fem_of_element(cv);
2181 pfem pf_sl = mfl.fem_of_element(cv);
2182 pintegration_method pim = mim.int_method_of_element(cv);
2183 bgeot::vectors_to_base_matrix(G, m.points_of_convex(cv));
2186 = fppool(pf_s, pim->approx_method()->pintegration_points());
2188 = fppool(pf_sl, pim->approx_method()->pintegration_points());
2189 fem_interpolation_context ctxu(pgt, pfpu,
size_type(-1), G, cv, v.f());
2190 fem_interpolation_context ctxl(pgt, pfpl,
size_type(-1), G, cv, v.f());
2193 k < pim->approx_method()->nb_points_on_face(v.f()); ++k) {
2195 = pim->approx_method()->ind_first_point_on_face(v.f()) + k;
2198 if (!(ce.add_point_contribution
2199 (bnum, ctxu, ctxl,pim->approx_method()->coeff(ind),
2200 f_coeff[0], vr[0], version)))
return;
2210 size_type add_integral_large_sliding_contact_brick_field_extension
2211 (model &md,
const mesh_im &mim,
const std::string &varname_u,
2212 const std::string &multname,
const std::string &dataname_r,
2213 const std::string &dataname_friction_coeff,
size_type region) {
2216 =std::make_shared<integral_large_sliding_contact_brick_field_extension>();
2218 pbr->add_boundary(varname_u, multname, mim, region);
2221 tl.push_back(model::term_description(varname_u, varname_u,
false));
2222 tl.push_back(model::term_description(varname_u, multname,
false));
2223 tl.push_back(model::term_description(multname, varname_u,
false));
2224 tl.push_back(model::term_description(multname, multname,
false));
2226 model::varnamelist dl(1, dataname_r);
2227 dl.push_back(dataname_friction_coeff);
2229 model::varnamelist vl(1, varname_u);
2230 vl.push_back(multname);
2232 return md.add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region);
2236 void add_boundary_to_large_sliding_contact_brick
2237 (model &md,
size_type indbrick,
const mesh_im &mim,
2238 const std::string &varname_u,
const std::string &multname,
2240 dim_type N = md.mesh_fem_of_variable(varname_u).linked_mesh().dim();
2241 pbrick pbr = md.brick_pointer(indbrick);
2242 md.touch_brick(indbrick);
2243 integral_large_sliding_contact_brick_field_extension *p
2244 =
dynamic_cast<integral_large_sliding_contact_brick_field_extension *
>
2245 (
const_cast<virtual_brick *
>(pbr.get()));
2246 GMM_ASSERT1(p,
"Wrong type of brick");
2247 p->add_boundary(varname_u, multname, mim, region);
2248 md.add_mim_to_brick(indbrick, mim);
2250 contact_frame cf(N);
2251 p->build_contact_frame(md, cf);
2253 model::varnamelist vl;
2255 for (
size_type i = 0; i < cf.contact_boundaries.size(); ++i)
2256 if (cf.contact_boundaries[i].ind_U >= nvaru)
2257 { vl.push_back(p->boundaries[i].varname); ++nvaru; }
2260 for (
size_type i = 0; i < cf.contact_boundaries.size(); ++i)
2261 if (cf.contact_boundaries[i].ind_lambda >= nvarl)
2262 { vl.push_back(p->boundaries[i].multname); ++nvarl; }
2263 md.change_variables_of_brick(indbrick, vl);
2266 for (
size_type i = 0; i < vl.size(); ++i)
2267 for (
size_type j = 0; j < vl.size(); ++j)
2268 tl.push_back(model::term_description(vl[i], vl[j],
false));
2270 md.change_terms_of_brick(indbrick, tl);
2274 (model &md,
size_type indbrick,
const std::string &obs) {
2275 pbrick pbr = md.brick_pointer(indbrick);
2276 md.touch_brick(indbrick);
2277 integral_large_sliding_contact_brick_field_extension *p
2278 =
dynamic_cast<integral_large_sliding_contact_brick_field_extension *
>
2279 (
const_cast<virtual_brick *
>(pbr.get()));
2280 GMM_ASSERT1(p,
"Wrong type of brick");
2281 p->add_obstacle(obs);
2293 struct intergral_large_sliding_contact_brick_raytracing
2294 :
public virtual_brick {
2296 struct contact_boundary {
2298 std::string varname_u;
2299 std::string varname_lambda;
2300 std::string varname_w;
2308 std::vector<contact_boundary> boundaries;
2309 std::string transformation_name;
2310 std::string u_group;
2311 std::string w_group;
2312 std::string friction_coeff;
2314 std::string augmentation_param;
2315 model::varnamelist vl, dl;
2318 bool sym_version, frame_indifferent;
2320 void add_contact_boundary(model &md,
const mesh_im &mim,
size_type region,
2321 bool is_master,
bool is_slave,
2322 const std::string &u,
2323 const std::string &lambda,
2324 const std::string &w =
"") {
2325 std::string test_u =
"Test_" + sup_previous_and_dot_to_varname(u);
2326 std::string test_u_group =
"Test_" + sup_previous_and_dot_to_varname(u_group);
2327 std::string test_lambda =
"Test_" + sup_previous_and_dot_to_varname(lambda);
2328 GMM_ASSERT1(is_slave || is_master,
"The contact boundary should be "
2329 "either master, slave or both");
2330 const mesh_fem *mf = md.pmesh_fem_of_variable(u);
2331 GMM_ASSERT1(mf,
"The displacement variable should be a f.e.m. one");
2332 GMM_ASSERT1(&(mf->linked_mesh()) == &(mim.linked_mesh()),
2333 "The displacement variable and the integration method "
2334 "should share the same mesh");
2336 const mesh_fem *mf_l = md.pmesh_fem_of_variable(lambda);
2337 GMM_ASSERT1(mf,
"The multiplier variable should be a f.e.m. one");
2338 GMM_ASSERT1(&(mf_l->linked_mesh()) == &(mim.linked_mesh()),
2339 "The displacement variable and the multiplier one "
2340 "should share the same mesh");
2344 const mesh_fem *mf2 = md.pmesh_fem_of_variable(w);
2345 GMM_ASSERT1(!mf2 || &(mf2->linked_mesh()) == &(mf->linked_mesh()),
2346 "The data for the sliding velocity should be defined on "
2347 " the same mesh as the displacement variable");
2350 for (
size_type i = 0; i < boundaries.size(); ++i) {
2351 const contact_boundary &cb = boundaries[i];
2352 if (&(md.mesh_fem_of_variable(cb.varname_u).linked_mesh())
2353 == &(mf->linked_mesh()) && cb.region == region)
2354 GMM_ASSERT1(
false,
"This contact boundary has already been added");
2358 (md, transformation_name, mf->linked_mesh(), u_group, region);
2361 (md, transformation_name, mf->linked_mesh(), u_group, region);
2363 boundaries.push_back(contact_boundary());
2364 contact_boundary &cb = boundaries.back();
2367 if (is_slave) cb.varname_lambda = lambda;
2369 cb.is_master = is_master;
2370 cb.is_slave = is_slave;
2373 std::string n, n0, Vs, g, Y;
2374 n =
"Transformed_unit_vector(Grad_"+u+
", Normal)";
2375 n0 =
"Transformed_unit_vector(Grad_"+w+
", Normal)";
2382 Y =
"Interpolate(X,"+transformation_name+
")";
2383 g =
"("+Y+
"+Interpolate("+u_group+
","+transformation_name+
")-X-"+u+
")."+n;
2384 Vs =
"("+u+
"-Interpolate("+u_group+
","+transformation_name+
")";
2386 Vs +=
"-"+w+
"+Interpolate("+w_group+
","+transformation_name+
")";
2387 if (frame_indifferent)
2388 Vs +=
"+("+g+
")*("+n+
"-"+n0+
")";
2392 std::string coupled_projection_def =
2393 "Coulomb_friction_coupled_projection("
2394 + lambda+
","+n+
","+Vs+
","+g+
","+friction_coeff+
","
2395 + augmentation_param+
")";
2401 g =
"(Interpolate(X,"+transformation_name+
")-X-"+u+
")."+n;
2402 if (frame_indifferent && w.size())
2403 Vs =
"("+u+
"-"+w+
"+"+g+
"*("+n+
"-"+n0+
"))*"+
alpha;
2405 Vs =
"("+u+(w.size() ? (
"-"+w):
"")+
")*"+
alpha;
2407 std::string coupled_projection_rig =
2408 "Coulomb_friction_coupled_projection("
2409 + lambda+
","+n+
","+Vs+
","+g+
","+ friction_coeff+
","
2410 + augmentation_param+
")";
2414 (sym_version ?
"" : (
"-"+lambda+
"."+test_u))
2417 + (sym_version ? (
"+ Interpolate_filter("+transformation_name+
",-"
2418 +coupled_projection_def+
"."+test_u+
",1)") :
"")
2419 + (sym_version ? (
"+ Interpolate_filter("+transformation_name+
",-"
2420 +coupled_projection_rig+
"."+test_u+
",2)") :
"")
2426 +
"+ Interpolate_filter("+transformation_name+
","
2427 + (sym_version ? coupled_projection_def : lambda)
2428 +
".Interpolate("+test_u_group+
"," + transformation_name+
"), 1)"
2430 +
"-(1/"+augmentation_param+
")*"+lambda+
"."+test_lambda
2433 +
"+ Interpolate_filter("+transformation_name+
","
2434 +
"(1/"+augmentation_param+
")*"+ coupled_projection_rig
2435 +
"."+test_lambda+
", 2)"
2438 +
"+ Interpolate_filter("+transformation_name+
","
2439 +
"(1/"+augmentation_param+
")*" + coupled_projection_def +
"."
2440 + test_lambda+
", 1)";
2444 virtual void asm_real_tangent_terms(
const model &md,
size_type ,
2445 const model::varnamelist &,
2446 const model::varnamelist &,
2447 const model::mimlist &,
2448 model::real_matlist &,
2449 model::real_veclist &,
2450 model::real_veclist &,
2452 build_version)
const {
2457 for (
const contact_boundary &cb : boundaries) {
2459 md.add_generic_expression(cb.expr, *(cb.mim), cb.region);
2464 intergral_large_sliding_contact_brick_raytracing
2465 (
const std::string &r,
2466 const std::string &f_coeff,
const std::string &ug,
2467 const std::string &wg,
const std::string &tr,
2468 const std::string &alpha_ =
"1",
bool sym_v =
false,
2469 bool frame_indiff =
false) {
2470 transformation_name = tr;
2471 u_group = ug; w_group = wg;
2472 friction_coeff = f_coeff;
2474 augmentation_param = r;
2475 sym_version = sym_v;
2476 frame_indifferent = frame_indiff;
2478 set_flags(
"Integral large sliding contact bick raytracing",
2489 pbrick pbr = md.brick_pointer(indbrick);
2490 intergral_large_sliding_contact_brick_raytracing *p
2491 =
dynamic_cast<intergral_large_sliding_contact_brick_raytracing *
>
2493 GMM_ASSERT1(p,
"Wrong type of brick");
2494 return p->transformation_name;
2499 pbrick pbr = md.brick_pointer(indbrick);
2500 intergral_large_sliding_contact_brick_raytracing *p
2501 =
dynamic_cast<intergral_large_sliding_contact_brick_raytracing *
>
2503 GMM_ASSERT1(p,
"Wrong type of brick");
2509 pbrick pbr = md.brick_pointer(indbrick);
2510 intergral_large_sliding_contact_brick_raytracing *p
2511 =
dynamic_cast<intergral_large_sliding_contact_brick_raytracing *
>
2513 GMM_ASSERT1(p,
"Wrong type of brick");
2519 pbrick pbr = md.brick_pointer(indbrick);
2520 intergral_large_sliding_contact_brick_raytracing *p
2521 =
dynamic_cast<intergral_large_sliding_contact_brick_raytracing *
>
2523 GMM_ASSERT1(p,
"Wrong type of brick");
2525 (md, p->transformation_name, expr, N);
2530 bool is_master,
bool is_slave,
const std::string &u,
2531 const std::string &lambda,
const std::string &w) {
2533 pbrick pbr = md.brick_pointer(indbrick);
2534 intergral_large_sliding_contact_brick_raytracing *p
2535 =
dynamic_cast<intergral_large_sliding_contact_brick_raytracing *
>
2537 GMM_ASSERT1(p,
"Wrong type of brick");
2539 bool found_u =
false, found_lambda =
false;
2540 for (
const auto & v : p->vl) {
2541 if (v.compare(u) == 0) found_u =
true;
2542 if (v.compare(lambda) == 0) found_lambda =
true;
2544 if (!found_u) p->vl.push_back(u);
2545 GMM_ASSERT1(!is_slave || lambda.size(),
2546 "You should define a multiplier on each slave boundary");
2547 if (is_slave && !found_lambda) p->vl.push_back(lambda);
2548 if (!found_u || (is_slave && !found_lambda))
2551 std::vector<std::string> ug = md.variable_group(p->u_group);
2553 for (
const auto &uu : ug)
2554 if (uu.compare(u) == 0) { found_u =
true;
break; }
2557 md.define_variable_group(p->u_group, ug);
2561 bool found_w =
false;
2562 for (
const auto &ww : p->dl)
2563 if (ww.compare(w) == 0) { found_w =
true;
break; }
2568 std::vector<std::string> wg = md.variable_group(p->w_group);
2570 for (
const auto &ww : wg)
2571 if (ww.compare(w) == 0) { found_w =
true;
break; }
2574 md.define_variable_group(p->w_group, wg);
2578 bool found_mim =
false;
2579 for (
const auto &pmim : p->ml)
2580 if (pmim == &mim) { found_mim =
true;
break; }
2582 p->ml.push_back(&mim);
2586 p->add_contact_boundary(md, mim, region, is_master, is_slave,
2591 (
model &md,
const std::string &augm_param,
2592 scalar_type release_distance,
const std::string &f_coeff,
2593 const std::string &alpha,
bool sym_v,
bool frame_indifferent) {
2595 char ugroupname[50], wgroupname[50], transname[50];
2596 for (
int i = 0; i < 10000; ++i) {
2597 sprintf(ugroupname,
"disp__group_raytracing_%d", i);
2598 if (!(md.variable_group_exists(ugroupname))
2602 md.define_variable_group(ugroupname, std::vector<std::string>());
2604 for (
int i = 0; i < 10000; ++i) {
2605 sprintf(wgroupname,
"w__group_raytracing_%d", i);
2606 if (!(md.variable_group_exists(wgroupname))
2610 md.define_variable_group(wgroupname, std::vector<std::string>());
2612 for (
int i = 0; i < 10000; ++i) {
2613 sprintf(transname,
"trans__raytracing_%d", i);
2619 model::varnamelist vl, dl;
2624 auto p = std::make_shared<intergral_large_sliding_contact_brick_raytracing>
2625 (augm_param, f_coeff, ugroupname, wgroupname, transname, alpha,
2626 sym_v, frame_indifferent);
2630 return md.
add_brick(pbr, p->vl, p->dl, model::termlist(), model::mimlist(),
2636 struct Nitsche_large_sliding_contact_brick_raytracing
2637 :
public virtual_brick {
2639 struct contact_boundary {
2641 std::string varname_u;
2642 std::string sigma_u;
2643 std::string varname_w;
2652 std::vector<contact_boundary> boundaries;
2653 std::string transformation_name;
2654 std::string u_group;
2655 std::string w_group;
2656 std::string friction_coeff;
2658 std::string Nitsche_param;
2659 model::varnamelist vl, dl;
2662 bool sym_version, frame_indifferent, unbiased;
2664 void add_contact_boundary(model &md,
const mesh_im &mim,
size_type region,
2665 bool is_master,
bool is_slave,
bool is_unbiased,
2666 const std::string &u,
2667 const std::string &sigma_u,
2668 const std::string &w =
"") {
2669 std::string test_u =
"Test_" + sup_previous_and_dot_to_varname(u);
2670 std::string test_u_group =
"Test_" + sup_previous_and_dot_to_varname(u_group);
2671 GMM_ASSERT1(is_slave || is_master,
"The contact boundary should be "
2672 "either master, slave or both");
2674 GMM_ASSERT1((is_slave && is_master),
"The contact boundary should be "
2675 "both master and slave for the unbiased version");
2676 is_slave=
true; is_master=
true;
2678 const mesh_fem *mf = md.pmesh_fem_of_variable(u);
2679 GMM_ASSERT1(mf,
"The displacement variable should be a f.e.m. one");
2680 GMM_ASSERT1(&(mf->linked_mesh()) == &(mim.linked_mesh()),
2681 "The displacement variable and the integration method "
2682 "should share the same mesh");
2685 const mesh_fem *mf2 = md.pmesh_fem_of_variable(w);
2686 GMM_ASSERT1(!mf2 || &(mf2->linked_mesh()) == &(mf->linked_mesh()),
2687 "The data for the sliding velocity should be defined on "
2688 " the same mesh as the displacement variable");
2691 for (
size_type i = 0; i < boundaries.size(); ++i) {
2692 const contact_boundary &cb = boundaries[i];
2693 if (&(md.mesh_fem_of_variable(cb.varname_u).linked_mesh())
2694 == &(mf->linked_mesh()) && cb.region == region)
2695 GMM_ASSERT1(
false,
"This contact boundary has already been added");
2699 (md, transformation_name, mf->linked_mesh(), u_group, region);
2702 (md, transformation_name, mf->linked_mesh(), u_group, region);
2704 boundaries.push_back(contact_boundary());
2705 contact_boundary &cb = boundaries.back();
2708 if (is_slave) cb.sigma_u = sigma_u;
2710 cb.is_master = is_master;
2711 cb.is_slave = is_slave;
2712 cb.is_unbiased= is_unbiased;
2715 std::string n, n0, Vs, g, Y, gamma;
2717 gamma =
"("+Nitsche_param+
"/element_size)";
2718 n =
"Transformed_unit_vector(Grad_"+u+
", Normal)";
2719 n0 =
"Transformed_unit_vector(Grad_"+w+
", Normal)";
2727 Y =
"Interpolate(X,"+transformation_name+
")";
2728 g =
"("+Y+
"+Interpolate("+u_group+
","+transformation_name+
")-X-"+u+
")."+n;
2729 Vs =
"("+u+
"-Interpolate("+u_group+
","+transformation_name+
")";
2731 Vs +=
"-"+w+
"+Interpolate("+w_group+
","+transformation_name+
")";
2732 if (frame_indifferent)
2733 Vs +=
"+("+g+
")*("+n+
"-"+n0+
")";
2737 std::string coupled_projection_def =
2738 "Coulomb_friction_coupled_projection("
2739 + sigma_u +
","+n+
","+Vs+
","+g+
","+friction_coeff+
","
2747 g =
"(Interpolate(X,"+transformation_name+
")-X-"+u+
")."+n;
2748 if (frame_indifferent && w.size())
2749 Vs =
"("+u+
"-"+w+
"+"+g+
"*("+n+
"-"+n0+
"))*"+
alpha;
2751 Vs =
"("+u+(w.size() ? (
"-"+w):
"")+
")*"+
alpha;
2753 std::string coupled_projection_rig =
2754 "Coulomb_friction_coupled_projection("
2755 + sigma_u +
","+n+
","+Vs+
","+g+
","+ friction_coeff+
","
2760 (is_unbiased ?
"-0.5*" :
"-")
2762 + (
"Interpolate_filter("+transformation_name+
","
2763 +coupled_projection_def+
"."+test_u+
",1) ")
2764 +(is_unbiased ?
"":
"-Interpolate_filter("+transformation_name+
","
2765 +coupled_projection_rig+
"."+test_u+
",2) ")
2771 + (is_unbiased ?
"+ 0.5*" :
"+ ")
2772 +
"Interpolate_filter("+transformation_name+
","
2773 +coupled_projection_def +
".Interpolate("+test_u_group+
"," + transformation_name+
"), 1)"
2774 +(is_unbiased ?
"":
"+ Interpolate_filter("+transformation_name+
","
2775 +coupled_projection_rig +
".Interpolate("+test_u_group+
"," + transformation_name+
"), 2)");
2779 virtual void asm_real_tangent_terms(
const model &md,
size_type ,
2780 const model::varnamelist &,
2781 const model::varnamelist &,
2782 const model::mimlist &,
2783 model::real_matlist &,
2784 model::real_veclist &,
2785 model::real_veclist &,
2787 build_version)
const {
2792 for (
const contact_boundary &cb : boundaries) {
2794 md.add_generic_expression(cb.expr, *(cb.mim), cb.region);
2799 Nitsche_large_sliding_contact_brick_raytracing
2801 const std::string &Nitsche_parameter,
2802 const std::string &f_coeff,
const std::string &ug,
2803 const std::string &wg,
const std::string &tr,
2804 const std::string &alpha_ =
"1",
bool sym_v =
false,
2805 bool frame_indiff =
false) {
2806 transformation_name = tr;
2807 u_group = ug; w_group = wg;
2808 friction_coeff = f_coeff;
2810 Nitsche_param = Nitsche_parameter;
2811 sym_version = sym_v;
2812 frame_indifferent = frame_indiff;
2815 set_flags(
"Integral large sliding contact bick raytracing",
2826 pbrick pbr = md.brick_pointer(indbrick);
2827 Nitsche_large_sliding_contact_brick_raytracing *p
2828 =
dynamic_cast<Nitsche_large_sliding_contact_brick_raytracing *
>
2830 GMM_ASSERT1(p,
"Wrong type of brick");
2831 return p->transformation_name;
2836 pbrick pbr = md.brick_pointer(indbrick);
2837 Nitsche_large_sliding_contact_brick_raytracing *p
2838 =
dynamic_cast<Nitsche_large_sliding_contact_brick_raytracing *
>
2840 GMM_ASSERT1(p,
"Wrong type of brick");
2846 pbrick pbr = md.brick_pointer(indbrick);
2847 Nitsche_large_sliding_contact_brick_raytracing *p
2848 =
dynamic_cast<Nitsche_large_sliding_contact_brick_raytracing *
>
2850 GMM_ASSERT1(p,
"Wrong type of brick");
2856 pbrick pbr = md.brick_pointer(indbrick);
2857 Nitsche_large_sliding_contact_brick_raytracing *p
2858 =
dynamic_cast<Nitsche_large_sliding_contact_brick_raytracing *
>
2860 GMM_ASSERT1(p,
"Wrong type of brick");
2862 (md, p->transformation_name, expr, N);
2867 bool is_master,
bool is_slave,
bool is_unbiased,
const std::string &u,
2868 const std::string &sigma_u,
const std::string &w) {
2870 pbrick pbr = md.brick_pointer(indbrick);
2871 Nitsche_large_sliding_contact_brick_raytracing *p
2872 =
dynamic_cast<Nitsche_large_sliding_contact_brick_raytracing *
>
2874 GMM_ASSERT1(p,
"Wrong type of brick");
2876 bool found_u =
false, found_sigma =
false;
2877 for (
const auto & v : p->vl) {
2878 if (v.compare(u) == 0) found_u =
true;
2879 if (v.compare(sigma_u) == 0) found_sigma =
true;
2881 if (!found_u) p->vl.push_back(u);
2882 GMM_ASSERT1(!is_slave || sigma_u.size(),
2883 "You should define an expression of sigma(u) on each slave boundary");
2888 std::vector<std::string> ug = md.variable_group(p->u_group);
2890 for (
const auto &uu : ug)
2891 if (uu.compare(u) == 0) { found_u =
true;
break; }
2894 md.define_variable_group(p->u_group, ug);
2898 bool found_w =
false;
2899 for (
const auto &ww : p->dl)
2900 if (ww.compare(w) == 0) { found_w =
true;
break; }
2905 std::vector<std::string> wg = md.variable_group(p->w_group);
2907 for (
const auto &ww : wg)
2908 if (ww.compare(w) == 0) { found_w =
true;
break; }
2911 md.define_variable_group(p->w_group, wg);
2915 bool found_mim =
false;
2916 for (
const auto &pmim : p->ml)
2917 if (pmim == &mim) { found_mim =
true;
break; }
2919 p->ml.push_back(&mim);
2923 p->add_contact_boundary(md, mim, region, is_master, is_slave,is_unbiased,
2928 (
model &md,
bool is_unbiased,
const std::string &Nitsche_param,
2929 scalar_type release_distance,
const std::string &f_coeff,
2930 const std::string &alpha,
bool sym_v,
bool frame_indifferent) {
2932 char ugroupname[50], wgroupname[50], transname[50];
2933 for (
int i = 0; i < 10000; ++i) {
2934 sprintf(ugroupname,
"disp__group_raytracing_%d", i);
2935 if (!(md.variable_group_exists(ugroupname))
2939 md.define_variable_group(ugroupname, std::vector<std::string>());
2941 for (
int i = 0; i < 10000; ++i) {
2942 sprintf(wgroupname,
"w__group_raytracing_%d", i);
2943 if (!(md.variable_group_exists(wgroupname))
2947 md.define_variable_group(wgroupname, std::vector<std::string>());
2949 for (
int i = 0; i < 10000; ++i) {
2950 sprintf(transname,
"trans__raytracing_%d", i);
2956 model::varnamelist vl, dl;
2961 auto p = std::make_shared<Nitsche_large_sliding_contact_brick_raytracing>
2962 (is_unbiased, Nitsche_param , f_coeff, ugroupname, wgroupname, transname, alpha,
2963 sym_v, frame_indifferent);
2967 return md.
add_brick(pbr, p->vl, p->dl, model::termlist(), model::mimlist(),