31 template <
typename T>
inline static T Heav(T a)
32 {
return (a < T(0)) ? T(0) : T(1); }
41 void contact_nonlinear_term::adjust_tensor_size(
void) {
42 sizes_.resize(1); sizes_[0] = 1;
45 case RHS_U_V1:
case RHS_U_V2:
case RHS_U_V4:
46 case RHS_U_V5:
case RHS_U_FRICT_V6:
case RHS_U_FRICT_V7:
47 case RHS_U_FRICT_V8:
case RHS_U_FRICT_V1:
48 case RHS_U_FRICT_V4:
case RHS_U_FRICT_V5:
49 case RHS_L_FRICT_V1:
case RHS_L_FRICT_V2:
case RHS_L_FRICT_V4:
50 case K_UL_V1:
case K_UL_V2:
case K_UL_V3:
51 case UZAWA_PROJ_FRICT:
case UZAWA_PROJ_FRICT_SAXCE:
54 case K_UU_V1:
case K_UU_V2:
55 case K_UL_FRICT_V1:
case K_UL_FRICT_V2:
case K_UL_FRICT_V3:
56 case K_UL_FRICT_V4:
case K_UL_FRICT_V5:
57 case K_UL_FRICT_V7:
case K_UL_FRICT_V8:
58 case K_LL_FRICT_V1:
case K_LL_FRICT_V2:
case K_LL_FRICT_V4:
59 case K_UU_FRICT_V1:
case K_UU_FRICT_V2:
60 case K_UU_FRICT_V3:
case K_UU_FRICT_V4:
case K_UU_FRICT_V5:
61 sizes_.resize(2); sizes_[0] = sizes_[1] = N;
break;
65 lnt.resize(N); lt.resize(N); zt.resize(N); no.resize(N);
66 aux1.resize(1); auxN.resize(N); V.resize(N);
70 void contact_nonlinear_term::friction_law
71 (scalar_type p, scalar_type &tau) {
72 tau = (p > scalar_type(0)) ? tau_adh + f_coeff * p : scalar_type(0);
73 if (tau > tresca_lim) tau = tresca_lim;
76 void contact_nonlinear_term::friction_law
77 (scalar_type p, scalar_type &tau, scalar_type &tau_grad) {
78 if (p <= scalar_type(0)) {
80 tau_grad = scalar_type(0);
83 tau = tau_adh + f_coeff * p;
84 if (tau > tresca_lim) {
86 tau_grad = scalar_type(0);
93 void contact_nonlinear_term::compute
94 (fem_interpolation_context &, bgeot::base_tensor &t) {
96 t.adjust_sizes(sizes_);
97 scalar_type e, augm_ln, rho, rho_grad;
106 t[0] = (ln+gmm::neg(ln-r*(un - g)))/r;
break;
108 t[0] = (un-g) + gmm::pos(ln)/r;
break;
111 t[0] = (Heav(r*(un-g)-ln) - scalar_type(1))/r;
break;
113 t[0] = -Heav(ln)/r;
break;
116 t[0] = -gmm::neg(ln - r*(un - g));
break;
121 t[0] = Heav(un-g - ln);
break;
122 case CONTACT_PRESSURE:
128 for (i=0; i<N; ++i) t[i] = ln * no[i];
131 e = -gmm::neg(ln-r*(un - g));
132 for (i=0; i<N; ++i) t[i] = e * no[i];
136 for (i=0; i<N; ++i) t[i] = e * no[i];
139 e = - gmm::pos(un-g) * r;
140 for (i=0; i<N; ++i) t[i] = e * no[i];
143 e = gmm::neg(ln-r*(un - g));
144 friction_law(e, rho);
145 auxN = lt - zt; ball_projection(auxN, rho);
146 for (i=0; i<N; ++i) t[i] = auxN[i] - e*no[i];
149 e = gmm::neg(-r*(un - g));
150 friction_law(e, rho);
151 auxN = - zt; ball_projection(auxN, rho);
152 for (i=0; i<N; ++i) t[i] = auxN[i] - e*no[i];
155 auxN = lnt - (r*(un-g) - f_coeff * gmm::vect_norm2(zt)) * no - zt;
156 De_Saxce_projection(auxN, no, f_coeff);
157 for (i=0; i<N; ++i) t[i] = auxN[i];
160 for (i=0; i<N; ++i) t[i] = lnt[i];
166 friction_law(e, rho);
167 auxN = lt; ball_projection(auxN, rho);
170 for (i=0; i<N; ++i) t[i] = auxN[i] - e*no[i];
173 auxN = lnt; De_Saxce_projection(auxN, no, f_coeff);
174 for (i=0; i<N; ++i) t[i] = auxN[i];
177 e = gmm::neg(ln-r*(un-g));
178 friction_law(e, rho);
179 auxN = zt - lt; ball_projection(auxN, rho); auxN += lt;
180 for (i=0; i<N; ++i) t[i] = ((e+ln)*no[i] + auxN[i])/ r;
183 e = r*(un-g) + gmm::pos(ln);
184 friction_law(gmm::neg(ln), rho);
185 auxN = lt; ball_projection(auxN, rho);
186 for (i=0; i<N; ++i) t[i] = (no[i]*e + zt[i] + lt[i] - auxN[i])/r;
190 De_Saxce_projection(auxN, no, f_coeff);
191 auxN -= lnt + (r*(un-g) - f_coeff * gmm::vect_norm2(zt)) * no + zt;
192 for (i=0; i<N; ++i) t[i] = -auxN[i]/r;
195 for (i=0; i<N; ++i) t[i] = -no[i];
199 for (i=0; i<N; ++i) t[i] = e*no[i];
202 e = -Heav(r*(un-g)-ln);
203 for (i=0; i<N; ++i) t[i] = e*no[i];
205 case UZAWA_PROJ_FRICT:
206 e = gmm::neg(ln - r*(un - g));
207 friction_law(e, rho);
208 auxN = lt - zt; ball_projection(auxN, rho);
209 for (i=0; i<N; ++i) t[i] = auxN[i] - e*no[i];
211 case UZAWA_PROJ_FRICT_SAXCE:
212 auxN = lnt - (r*(un-g) - f_coeff * gmm::vect_norm2(zt)) * no - zt;
213 De_Saxce_projection(auxN, no, f_coeff);
214 for (i=0; i<N; ++i) t[i] = auxN[i];
220 e = r * Heav(un - g);
221 for (i=0; i<N; ++i)
for (j=0; j<N; ++j) t[i*N+j] = e * no[i] * no[j];
224 e = r * Heav(r*(un - g)-ln);
225 for (i=0; i<N; ++i)
for (j=0; j<N; ++j) t[i*N+j] = e * no[i] * no[j];
229 for (i=0; i<N; ++i)
for (j=0; j<N; ++j)
230 t[i*N+j] = ((i == j) ? -scalar_type(1) : scalar_type(0));
233 friction_law(gmm::neg(ln), rho, rho_grad);
234 ball_projection_grad(lt, rho, GP);
236 coulomb = (rho_grad > 0) &&
bool(Heav(-ln));
237 if (coulomb) ball_projection_grad_r(lt, rho, V);
238 for (i=0; i<N; ++i)
for (j=0; j<N; ++j)
239 t[i*N+j] = no[i]*no[j]*e - GP(i,j) +
240 (coulomb ? rho_grad*no[i]*V[j] : scalar_type(0));
243 augm_ln = ln - r*(un-g);
244 friction_law(gmm::neg(augm_ln), rho, rho_grad);
246 ball_projection_grad(auxN, rho, GP);
248 coulomb = (rho_grad > 0) &&
bool(Heav(-augm_ln));
249 if (coulomb) ball_projection_grad_r(auxN, rho, V);
250 for (i=0; i<N; ++i)
for (j=0; j<N; ++j)
251 t[i*N+j] = no[i]*no[j]*e - GP(i,j) +
252 (coulomb ? rho_grad*no[i]*V[j] : scalar_type(0));
255 augm_ln = ln - r*(un-g);
256 friction_law(gmm::neg(augm_ln), rho, rho_grad);
258 ball_projection_grad(auxN, rho, GP); gmm::scale(GP, alpha);
260 coulomb = (rho_grad > 0) &&
bool(Heav(-augm_ln));
261 if (coulomb) ball_projection_grad_r(auxN, rho, V);
262 for (i=0; i<N; ++i)
for (j=0; j<N; ++j)
263 t[i*N+j] = no[i]*no[j]*e - GP(i,j) +
264 (coulomb ? rho_grad*V[i]*no[j] : scalar_type(0));
267 e =
alpha - scalar_type(1);
268 for (i=0; i<N; ++i)
for (j=0; j<N; ++j)
269 t[i*N+j] = no[i]*no[j]*e - ((i == j) ? alpha : scalar_type(0));
272 De_Saxce_projection_grad(lnt, no, f_coeff, GP);
273 for (i=0; i<N; ++i)
for (j=0; j<N; ++j) t[i*N+j] = -GP(j,i);
278 gmm::copy(gmm::identity_matrix(), GP); gmm::scale(GP, alpha);
279 gmm::rank_one_update(GP, gmm::scaled(no, scalar_type(1)-alpha), no);
280 if (nzt != scalar_type(0))
281 gmm::rank_one_update(GP, gmm::scaled(no, -f_coeff*alpha/nzt), zt);
282 for (i=0; i<N; ++i)
for (j=0; j<N; ++j) t[i*N+j] = - GP(i,j);
286 augm_ln = ln - r*(un-g);
287 friction_law(gmm::neg(augm_ln), rho, rho_grad);
289 ball_projection_grad(auxN, rho, GP);
291 coulomb = (rho_grad > 0) &&
bool(Heav(-augm_ln));
292 if (coulomb) ball_projection_grad_r(auxN, rho, V);
293 for (i=0; i<N; ++i)
for (j=0; j<N; ++j)
294 t[i*N+j] = (no[i]*no[j]*e + GP(i,j)
295 - ((i == j) ? scalar_type(1) : scalar_type(0))
296 - (coulomb ? rho_grad*no[i]*V[j] : scalar_type(0))) / r;
299 friction_law(gmm::neg(ln), rho, rho_grad);
300 ball_projection_grad(lt, rho, GP);
302 coulomb = (rho_grad > 0) &&
bool(Heav(-ln));
303 if (coulomb) ball_projection_grad_r(lt, rho, V);
304 for (i=0; i<N; ++i)
for (j=0; j<N; ++j)
305 t[i*N+j] = (no[i]*no[j]*e + GP(i,j)
306 - ((i == j) ? scalar_type(1) : scalar_type(0))
307 - (coulomb ? rho_grad*no[i]*V[j] : scalar_type(0))) / r;
310 De_Saxce_projection_grad(lnt, no, f_coeff, GP);
311 for (i=0; i<N; ++i)
for (j=0; j<N; ++j)
312 t[i*N+j] = (GP(i,j) - ((i == j) ? scalar_type(1) : scalar_type(0)))/r;
315 e = r * Heav(r*(un-g)-ln);
316 for (i=0; i<N; ++i)
for (j=0; j<N; ++j) t[i*N+j] = no[i]*no[j]*e;
319 friction_law(-ln, rho, rho_grad);
321 ball_projection_grad(auxN, rho, GP); gmm::scale(GP, alpha);
323 for (i=0; i<N; ++i)
for (j=0; j<N; ++j)
324 t[i*N+j] = r*(no[i]*no[j]*e + GP(i,j));
328 augm_ln = (option == K_UU_FRICT_V3) ? ln - r*(un-g) : - r*(un-g);
329 auxN = (option == K_UU_FRICT_V3) ? lt - zt : -zt;
330 friction_law(gmm::neg(augm_ln), rho, rho_grad);
331 ball_projection_grad(auxN, rho, GP); gmm::scale(GP, alpha);
333 coulomb = (rho_grad > 0) &&
bool(Heav(-augm_ln));
334 if (coulomb) ball_projection_grad_r(auxN, rho, V);
335 for (i=0; i<N; ++i)
for (j=0; j<N; ++j)
336 t[i*N+j] = r*(no[i]*no[j]*e + GP(i,j)
337 - (coulomb ? rho_grad*no[i]*V[j] : scalar_type(0)));
342 auxN = lnt - (r*(un-g) - f_coeff * nzt) * no - zt;
343 base_matrix A(N, N), B(N, N);
344 De_Saxce_projection_grad(auxN, no, f_coeff, A);
345 gmm::copy(gmm::identity_matrix(), B); gmm::scale(B, alpha);
346 gmm::rank_one_update(B, gmm::scaled(no, scalar_type(1)-alpha), no);
347 if (nzt != scalar_type(0))
348 gmm::rank_one_update(B, gmm::scaled(no, -f_coeff*alpha/nzt), zt);
350 for (i=0; i<N; ++i)
for (j=0; j<N; ++j) t[i*N+j] = r*GP(j,i);
353 default : GMM_ASSERT1(
false,
"Invalid option");
364 void contact_rigid_obstacle_nonlinear_term::prepare
365 (fem_interpolation_context& ctx,
size_type nb) {
371 ctx.pf()->interpolation(ctx, coeff, V, N);
374 if (gmm::vect_size(WT) == gmm::vect_size(U)) {
376 ctx.pf()->interpolation(ctx, coeff, auxN, N);
378 if (gmm::vect_size(VT) == gmm::vect_size(U)) {
380 ctx.pf()->interpolation(ctx, coeff, vt, N);
383 zt = (((V - un * no) - auxN) *
alpha + vt * (1 - gamma)) * r;
386 zt = ((V - un * no) - auxN) * (r *
alpha);
390 zt = (V - un * no) * (r * alpha);
398 ctx.pf()->interpolation_grad(ctx, coeff, grad, 1);
401 ctx.pf()->interpolation(ctx, coeff, aux1, 1);
404 if (!contact_only && pmf_lambda) {
415 ctx.pf()->interpolation(ctx, coeff, aux1, 1);
418 ctx.pf()->interpolation(ctx, coeff, lnt, N);
426 GMM_ASSERT1(!contact_only,
"Invalid friction option");
429 ctx.pf()->interpolation(ctx, coeff, aux1, 1);
431 if (gmm::vect_size(tau_adhesion)) {
433 ctx.pf()->interpolation(ctx, coeff, aux1, 1);
435 if (gmm::vect_size(tresca_limit)) {
437 ctx.pf()->interpolation(ctx, coeff, aux1, 1);
438 tresca_lim = aux1[0];
444 default : GMM_ASSERT1(
false,
"Invalid option");
456 void contact_nonmatching_meshes_nonlinear_term::prepare
457 (fem_interpolation_context& ctx,
size_type nb) {
473 ctx.pf()->interpolation(ctx, coeff, V, N);
477 if (gmm::vect_size(WT1) == gmm::vect_size(U1)) {
479 ctx.pf()->interpolation(ctx, coeff, auxN, N);
481 zt = ((V - un1 * no) - auxN) * (r *
alpha) - zt;
483 zt = (V - un1 * no) * (r * alpha) - zt;
494 const projected_fem &pfe =
dynamic_cast<const projected_fem&
>(*ctx.pf());
495 pfe.projection_data(ctx, no, g);
496 gmm::scale(no, scalar_type(-1));
499 if (!contact_only && pmf_lambda) {
505 ctx.pf()->interpolation(ctx, coeff, V, N);
508 if (gmm::vect_size(WT2) == gmm::vect_size(U2)) {
510 ctx.pf()->interpolation(ctx, coeff, auxN, N);
512 zt = ((V - un * no) - auxN) * (r *
alpha);
514 zt = (V - un * no) * (r * alpha);
523 ctx.pf()->interpolation(ctx, coeff, aux1, 1);
526 ctx.pf()->interpolation(ctx, coeff, lnt, N);
534 GMM_ASSERT1(!contact_only,
"Invalid friction option");
537 ctx.pf()->interpolation(ctx, coeff, aux1, 1);
539 if (gmm::vect_size(tau_adhesion)) {
541 ctx.pf()->interpolation(ctx, coeff, aux1, 1);
543 if (gmm::vect_size(tresca_limit)) {
545 ctx.pf()->interpolation(ctx, coeff, aux1, 1);
546 tresca_lim = aux1[0];
552 default : GMM_ASSERT1(
false,
"Invalid option");
564 template<
typename MAT,
typename VECT1>
565 void asm_Alart_Curnier_contact_rigid_obstacle_tangent_matrix
566 (MAT &Kul, MAT &Klu, MAT &Kll, MAT &Kuu,
571 scalar_type r,
const mesh_region &rg,
int option = 1) {
573 size_type subterm1 = (option == 3) ? K_UL_V2 : K_UL_V1;
574 size_type subterm2 = (option == 3) ? K_UL_V1 : K_UL_V3;
575 size_type subterm3 = (option == 3) ? K_LL_V2 : K_LL_V1;
576 size_type subterm4 = (option == 2) ? K_UU_V2 : K_UU_V1;
578 contact_rigid_obstacle_nonlinear_term
579 nterm1(subterm1, r, mf_u, U, mf_obs, obs, &mf_lambda, &lambda),
580 nterm2(subterm2, r, mf_u, U, mf_obs, obs, &mf_lambda, &lambda),
581 nterm3(subterm3, r, mf_u, U, mf_obs, obs, &mf_lambda, &lambda),
582 nterm4(subterm4, r, mf_u, U, mf_obs, obs, &mf_lambda, &lambda);
588 (
"M$1(#1,#3)+=comp(NonLin$1(#1,#1,#2,#3).vBase(#1).Base(#3))(i,:,i,:); "
589 "M$2(#3,#1)+=comp(NonLin$2(#1,#1,#2,#3).Base(#3).vBase(#1))(i,:,:,i); "
590 "M$3(#3,#3)+=comp(NonLin$3(#1,#1,#2,#3).Base(#3).Base(#3))(i,:,:)");
594 (
"M$1(#1,#3)+=comp(NonLin$2(#1,#1,#2,#3).vBase(#1).Base(#3))(i,:,i,:); "
595 "M$3(#3,#3)+=comp(NonLin$3(#1,#1,#2,#3).Base(#3).Base(#3))(i,:,:);"
596 "M$4(#1,#1)+=comp(NonLin$4(#1,#1,#2,#3).vBase(#1).vBase(#1))(i,j,:,i,:,j)");
614 template<
typename MAT,
typename VECT1>
615 void asm_Alart_Curnier_contact_rigid_obstacle_tangent_matrix
616 (MAT &Kul, MAT &Klu, MAT &Kll, MAT &Kuu,
622 scalar_type
alpha,
const VECT1 *WT,
623 scalar_type gamma,
const VECT1 *VT,
624 const mesh_region &rg,
int option = 1) {
628 case 1 : subterm1 = K_UL_FRICT_V1; subterm2 = K_UL_FRICT_V4;
629 subterm3 = K_LL_FRICT_V1;
break;
630 case 2 : subterm1 = K_UL_FRICT_V3; subterm2 = K_UL_FRICT_V4;
631 subterm3 = K_LL_FRICT_V1;
break;
632 case 3 : subterm1 = K_UL_FRICT_V2; subterm2 = K_UL_FRICT_V5;
633 subterm3 = K_LL_FRICT_V2;
break;
634 case 4 : subterm1 = K_UL_FRICT_V7; subterm2 = K_UL_FRICT_V8;
635 subterm3 = K_LL_FRICT_V4;
break;
636 default : GMM_ASSERT1(
false,
"Incorrect option");
641 contact_rigid_obstacle_nonlinear_term
642 nterm1(subterm1, r, mf_u, U, mf_obs, obs, &mf_lambda, &lambda,
643 pmf_coeff, f_coeffs, alpha, WT, gamma, VT),
644 nterm2(subterm2, r, mf_u, U, mf_obs, obs, &mf_lambda, &lambda,
645 pmf_coeff, f_coeffs, alpha, WT, gamma, VT),
646 nterm3(subterm3, r, mf_u, U, mf_obs, obs, &mf_lambda, &lambda,
647 pmf_coeff, f_coeffs, alpha, WT, gamma, VT),
648 nterm4(subterm4, r, mf_u, U, mf_obs, obs, &mf_lambda, &lambda,
649 pmf_coeff, f_coeffs, alpha, WT, gamma, VT);
651 const std::string aux_fems = pmf_coeff ?
"#1,#2,#3,#4" :
"#1,#2,#3";
655 case 1:
case 3:
case 4:
657 (
"M$1(#1,#3)+=comp(NonLin$1(#1," + aux_fems +
").vBase(#1).vBase(#3))(i,j,:,i,:,j); "
658 "M$2(#3,#1)+=comp(NonLin$2(#1," + aux_fems +
").vBase(#3).vBase(#1))(i,j,:,j,:,i); "
659 "M$3(#3,#3)+=comp(NonLin$3(#1," + aux_fems +
").vBase(#3).vBase(#3))(i,j,:,i,:,j)");
663 (
"M$1(#1,#3)+=comp(NonLin$1(#1," + aux_fems +
").vBase(#1).vBase(#3))(i,j,:,i,:,j); "
664 "M$2(#3,#1)+=comp(NonLin$2(#1," + aux_fems +
").vBase(#3).vBase(#1))(i,j,:,j,:,i); "
665 "M$3(#3,#3)+=comp(NonLin$3(#1," + aux_fems +
").vBase(#3).vBase(#3))(i,j,:,i,:,j);"
666 "M$4(#1,#1)+=comp(NonLin$4(#1," + aux_fems +
").vBase(#1).vBase(#1))(i,j,:,i,:,j)");
686 template<
typename VECT1>
687 void asm_Alart_Curnier_contact_rigid_obstacle_rhs
688 (VECT1 &Ru, VECT1 &Rl,
693 scalar_type r,
const mesh_region &rg,
int option = 1) {
697 case 1 : subterm1 = RHS_U_V1;
break;
698 case 2 : subterm1 = RHS_U_V2;
break;
699 case 3 : subterm1 = RHS_U_V4;
break;
700 default : GMM_ASSERT1(
false,
"Incorrect option");
702 size_type subterm2 = (option == 3) ? RHS_L_V2 : RHS_L_V1;
704 contact_rigid_obstacle_nonlinear_term
705 nterm1(subterm1, r, mf_u, U, mf_obs, obs, &mf_lambda, &lambda),
706 nterm2(subterm2, r, mf_u, U, mf_obs, obs, &mf_lambda, &lambda);
709 assem.set(
"V$1(#1)+=comp(NonLin$1(#1,#1,#2,#3).vBase(#1))(i,:,i); "
710 "V$2(#3)+=comp(NonLin$2(#1,#1,#2,#3).Base(#3))(i,:)");
723 template<
typename VECT1>
724 void asm_Alart_Curnier_contact_rigid_obstacle_rhs
725 (VECT1 &Ru, VECT1 &Rl,
731 scalar_type
alpha,
const VECT1 *WT,
732 scalar_type gamma,
const VECT1 *VT,
733 const mesh_region &rg,
int option = 1) {
737 case 1 : subterm1 = RHS_U_FRICT_V1; subterm2 = RHS_L_FRICT_V1;
break;
738 case 2 : subterm1 = RHS_U_FRICT_V6; subterm2 = RHS_L_FRICT_V1;
break;
739 case 3 : subterm1 = RHS_U_FRICT_V4; subterm2 = RHS_L_FRICT_V2;
break;
740 case 4 : subterm1 = RHS_U_FRICT_V5; subterm2 = RHS_L_FRICT_V4;
break;
741 default : GMM_ASSERT1(
false,
"Incorrect option");
744 contact_rigid_obstacle_nonlinear_term
745 nterm1(subterm1, r, mf_u, U, mf_obs, obs, &mf_lambda, &lambda,
746 pmf_coeff, f_coeffs, alpha, WT, gamma, VT),
747 nterm2(subterm2, r, mf_u, U, mf_obs, obs, &mf_lambda, &lambda,
748 pmf_coeff, f_coeffs, alpha, WT, gamma, VT);
750 const std::string aux_fems = pmf_coeff ?
"#1,#2,#3,#4" :
"#1,#2,#3";
753 assem.set(
"V$1(#1)+=comp(NonLin$1(#1," + aux_fems +
").vBase(#1))(i,:,i); "
754 "V$2(#3)+=comp(NonLin$2(#1," + aux_fems +
").vBase(#3))(i,:,i)");
768 struct integral_contact_rigid_obstacle_brick :
public virtual_brick {
779 virtual void asm_real_tangent_terms(
const model &md,
size_type ,
780 const model::varnamelist &vl,
781 const model::varnamelist &dl,
782 const model::mimlist &mims,
783 model::real_matlist &matl,
784 model::real_veclist &vecl,
785 model::real_veclist &,
787 build_version version)
const {
788 GMM_ASSERT1(mims.size() == 1,
789 "Integral contact with rigid obstacle bricks need a single mesh_im");
790 GMM_ASSERT1(vl.size() == 2,
791 "Integral contact with rigid obstacle bricks need two variables");
792 GMM_ASSERT1(dl.size() >= 2 && dl.size() <= 7,
793 "Wrong number of data for integral contact with rigid obstacle "
794 <<
"brick, " << dl.size() <<
" should be between 2 and 7.");
795 GMM_ASSERT1(matl.size() ==
size_type(3 + (option == 2 && !contact_only)),
796 "Wrong number of terms for "
797 "integral contact with rigid obstacle brick");
808 const model_real_plain_vector &u = md.real_variable(vl[0]);
809 const mesh_fem &mf_u = md.mesh_fem_of_variable(vl[0]);
810 const model_real_plain_vector &lambda = md.real_variable(vl[1]);
811 const mesh_fem &mf_lambda = md.mesh_fem_of_variable(vl[1]);
812 GMM_ASSERT1(mf_lambda.get_qdim() == (contact_only ? 1 : mf_u.get_qdim()),
813 "The contact stress has not the right dimension");
814 const model_real_plain_vector &obstacle = md.real_variable(dl[0]);
815 const mesh_fem &mf_obstacle = md.mesh_fem_of_variable(dl[0]);
816 size_type sl = gmm::vect_size(obstacle) * mf_obstacle.get_qdim()
817 / mf_obstacle.nb_dof();
818 GMM_ASSERT1(sl == 1,
"the data corresponding to the obstacle has not "
821 const model_real_plain_vector &vr = md.real_variable(dl[1]);
822 GMM_ASSERT1(gmm::vect_size(vr) == 1,
"Parameter r should be a scalar");
823 const mesh_im &mim = *mims[0];
825 const model_real_plain_vector dummy_vec(0);
826 const model_real_plain_vector &friction_coeffs = contact_only
827 ? dummy_vec : md.real_variable(dl[2]);
828 const mesh_fem *pmf_coeff = contact_only ? 0 : md.pmesh_fem_of_variable(dl[2]);
829 sl = gmm::vect_size(friction_coeffs);
830 if (pmf_coeff) { sl *= pmf_coeff->get_qdim(); sl /= pmf_coeff->nb_dof(); }
831 GMM_ASSERT1(sl == 1 || sl == 2 || sl == 3 || contact_only,
832 "the data corresponding to the friction coefficient "
833 "has not the right format");
835 scalar_type
alpha = 1;
836 if (!contact_only && dl.size() >= 4) {
837 alpha = md.real_variable(dl[3])[0];
838 GMM_ASSERT1(gmm::vect_size(md.real_variable(dl[3])) == 1,
839 "Parameter alpha should be a scalar");
842 const model_real_plain_vector *WT = 0;
843 if (!contact_only && dl.size() >= 5) {
844 if (dl[4].compare(vl[0]) != 0)
845 WT = &(md.real_variable(dl[4]));
846 else if (md.n_iter_of_variable(vl[0]) > 1)
847 WT = &(md.real_variable(vl[0],1));
850 scalar_type gamma = 1;
851 if (!contact_only && dl.size() >= 6) {
852 GMM_ASSERT1(gmm::vect_size(md.real_variable(dl[5])) == 1,
853 "Parameter gamma should be a scalar");
854 gamma = md.real_variable(dl[5])[0];
857 const model_real_plain_vector *VT
858 = (!contact_only && dl.size()>=7) ? &(md.real_variable(dl[6])) : 0;
860 mesh_region rg(region);
861 mf_u.linked_mesh().intersect_with_mpi_region(rg);
863 if (version & model::BUILD_MATRIX) {
864 GMM_TRACE2(
"Integral contact with rigid obstacle friction tangent term");
867 size_type fourthmat = (matl.size() >= 4) ? 3 : 1;
869 asm_Alart_Curnier_contact_rigid_obstacle_tangent_matrix
870 (matl[0], matl[1], matl[2], matl[fourthmat], mim,
871 mf_u, u, mf_obstacle, obstacle, mf_lambda, lambda, vr[0],
874 asm_Alart_Curnier_contact_rigid_obstacle_tangent_matrix
875 (matl[0], matl[1], matl[2], matl[fourthmat], mim,
876 mf_u, u, mf_obstacle, obstacle, mf_lambda, lambda,
877 pmf_coeff, &friction_coeffs, vr[0], alpha, WT, gamma, VT,
881 if (version & model::BUILD_RHS) {
886 asm_Alart_Curnier_contact_rigid_obstacle_rhs
887 (vecl[0], vecl[2], mim,
888 mf_u, u, mf_obstacle, obstacle, mf_lambda, lambda, vr[0],
891 asm_Alart_Curnier_contact_rigid_obstacle_rhs
892 (vecl[0], vecl[2], mim,
893 mf_u, u, mf_obstacle, obstacle, mf_lambda, lambda,
894 pmf_coeff, &friction_coeffs, vr[0], alpha, WT, gamma, VT,
900 integral_contact_rigid_obstacle_brick(
bool contact_only_,
int option_) {
902 contact_only = contact_only_;
903 set_flags(contact_only
904 ?
"Integral contact with rigid obstacle brick"
905 :
"Integral contact and friction with rigid obstacle brick",
907 (option==2) && contact_only ,
921 (
model &md,
const mesh_im &mim,
const std::string &varname_u,
922 const std::string &multname_n,
const std::string &dataname_obs,
923 const std::string &dataname_r,
size_type region,
int option) {
926 = std::make_shared<integral_contact_rigid_obstacle_brick>(
true, option);
932 tl.push_back(model::term_description(varname_u, multname_n,
false));
933 tl.push_back(model::term_description(multname_n, varname_u,
false));
934 tl.push_back(model::term_description(multname_n, multname_n,
true));
937 tl.push_back(model::term_description(varname_u, multname_n,
true));
938 tl.push_back(model::term_description(varname_u, varname_u,
true));
939 tl.push_back(model::term_description(multname_n, multname_n,
true));
941 default :GMM_ASSERT1(
false,
942 "Incorrect option for integral contact brick");
945 model::varnamelist dl(1, dataname_obs);
946 dl.push_back(dataname_r);
948 model::varnamelist vl(1, varname_u);
949 vl.push_back(multname_n);
951 return md.
add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region);
961 (
model &md,
const mesh_im &mim,
const std::string &varname_u,
962 const std::string &multname,
const std::string &dataname_obs,
963 const std::string &dataname_r,
const std::string &dataname_friction_coeffs,
965 const std::string &dataname_alpha,
const std::string &dataname_wt,
966 const std::string &dataname_gamma,
const std::string &dataname_vt) {
968 pbrick pbr = std::make_shared<integral_contact_rigid_obstacle_brick>
974 case 1:
case 3:
case 4:
975 tl.push_back(model::term_description(varname_u, multname,
false));
976 tl.push_back(model::term_description(multname, varname_u,
false));
977 tl.push_back(model::term_description(multname, multname,
true));
980 tl.push_back(model::term_description(varname_u, multname,
false));
981 tl.push_back(model::term_description(multname, varname_u,
false));
982 tl.push_back(model::term_description(multname, multname,
true));
983 tl.push_back(model::term_description(varname_u, varname_u,
true));
985 default :GMM_ASSERT1(
false,
986 "Incorrect option for integral contact brick");
988 model::varnamelist dl(1, dataname_obs);
989 dl.push_back(dataname_r);
990 dl.push_back(dataname_friction_coeffs);
991 if (dataname_alpha.size()) {
992 dl.push_back(dataname_alpha);
993 if (dataname_wt.size()) {
994 dl.push_back(dataname_wt);
995 if (dataname_gamma.size()) {
996 dl.push_back(dataname_gamma);
997 if (dataname_vt.size()) dl.push_back(dataname_vt);
1002 model::varnamelist vl(1, varname_u);
1003 vl.push_back(multname);
1005 return md.
add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region);
1015 template<
typename MAT,
typename VECT1>
1016 void asm_penalized_contact_rigid_obstacle_tangent_matrix
1022 scalar_type r,
const mesh_region &rg,
int option = 1) {
1024 contact_rigid_obstacle_nonlinear_term
1025 nterm((option == 1) ? K_UU_V1 : K_UU_V2, r,
1026 mf_u, U, mf_obs, obs, pmf_lambda, lambda);
1028 const std::string aux_fems = pmf_lambda ?
"#1,#2,#3":
"#1,#2";
1030 assem.set(
"M(#1,#1)+=comp(NonLin(#1," + aux_fems +
").vBase(#1).vBase(#1))(i,j,:,i,:,j)");
1042 template<
typename VECT1>
1043 void asm_penalized_contact_rigid_obstacle_rhs
1049 scalar_type r,
const mesh_region &rg,
int option = 1) {
1051 contact_rigid_obstacle_nonlinear_term
1052 nterm((option == 1) ? RHS_U_V5 : RHS_U_V2, r,
1053 mf_u, U, mf_obs, obs, pmf_lambda, lambda);
1055 const std::string aux_fems = pmf_lambda ?
"#1,#2,#3":
"#1,#2";
1057 assem.set(
"V(#1)+=comp(NonLin$1(#1," + aux_fems +
").vBase(#1))(i,:,i); ");
1068 template<
typename MAT,
typename VECT1>
1069 void asm_penalized_contact_rigid_obstacle_tangent_matrix
1076 scalar_type
alpha,
const VECT1 *WT,
1077 const mesh_region &rg,
int option = 1) {
1081 case 1 : subterm = K_UU_FRICT_V4;
break;
1082 case 2 : subterm = K_UU_FRICT_V3;
break;
1083 case 3 : subterm = K_UU_FRICT_V5;
break;
1086 contact_rigid_obstacle_nonlinear_term
1087 nterm(subterm, r, mf_u, U, mf_obs, obs, pmf_lambda, lambda,
1088 pmf_coeff, f_coeffs, alpha, WT);
1090 const std::string aux_fems = pmf_coeff ?
"#1,#2,#3,#4"
1091 : (pmf_lambda ?
"#1,#2,#3":
"#1,#2");
1093 assem.set(
"M(#1,#1)+=comp(NonLin(#1," + aux_fems +
").vBase(#1).vBase(#1))(i,j,:,i,:,j)");
1112 template<
typename VECT1>
1113 void asm_penalized_contact_rigid_obstacle_rhs
1120 scalar_type
alpha,
const VECT1 *WT,
1121 const mesh_region &rg,
int option = 1) {
1125 case 1 : subterm = RHS_U_FRICT_V7;
break;
1126 case 2 : subterm = RHS_U_FRICT_V6;
break;
1127 case 3 : subterm = RHS_U_FRICT_V8;
break;
1130 contact_rigid_obstacle_nonlinear_term
1131 nterm(subterm, r, mf_u, U, mf_obs, obs, pmf_lambda, lambda,
1132 pmf_coeff, f_coeffs, alpha, WT);
1134 const std::string aux_fems = pmf_coeff ?
"#1,#2,#3,#4"
1135 : (pmf_lambda ?
"#1,#2,#3":
"#1,#2");
1137 assem.set(
"V(#1)+=comp(NonLin$1(#1," + aux_fems +
").vBase(#1))(i,:,i); ");
1156 struct penalized_contact_rigid_obstacle_brick :
public virtual_brick {
1161 virtual void asm_real_tangent_terms(
const model &md,
size_type ,
1162 const model::varnamelist &vl,
1163 const model::varnamelist &dl,
1164 const model::mimlist &mims,
1165 model::real_matlist &matl,
1166 model::real_veclist &vecl,
1167 model::real_veclist &,
1169 build_version version)
const {
1171 GMM_ASSERT1(mims.size() == 1,
1172 "Penalized contact with rigid obstacle bricks need a single mesh_im");
1173 const mesh_im &mim = *mims[0];
1176 GMM_ASSERT1(vl.size() == 1,
1177 "Penalized contact with rigid obstacle bricks need a single variable");
1178 const model_real_plain_vector &u = md.real_variable(vl[0]);
1179 const mesh_fem &mf_u = md.mesh_fem_of_variable(vl[0]);
1184 size_type nb_data_1 = ((option == 1) ? 2 : 3) + (contact_only ? 0 : 1);
1185 size_type nb_data_2 = nb_data_1 + (contact_only ? 0 : 2);
1186 GMM_ASSERT1(dl.size() >= nb_data_1 && dl.size() <= nb_data_2,
1187 "Wrong number of data for penalized contact with rigid obstacle "
1188 <<
"brick, " << dl.size() <<
" should be between "
1189 << nb_data_1 <<
" and " << nb_data_2 <<
".");
1192 const model_real_plain_vector &obs = md.real_variable(dl[nd]);
1193 const mesh_fem &mf_obs = md.mesh_fem_of_variable(dl[nd]);
1194 size_type sl = gmm::vect_size(obs) * mf_obs.get_qdim() / mf_obs.nb_dof();
1195 GMM_ASSERT1(sl == 1,
"the data corresponding to the obstacle has not "
1196 "the right format");
1199 const model_real_plain_vector &vr = md.real_variable(dl[nd]);
1200 GMM_ASSERT1(gmm::vect_size(vr) == 1,
"Parameter r should be a scalar");
1202 const model_real_plain_vector *lambda = 0;
1203 const mesh_fem *pmf_lambda = 0;
1206 lambda = &(md.real_variable(dl[nd]));
1207 pmf_lambda = md.pmesh_fem_of_variable(dl[nd]);
1208 sl = gmm::vect_size(*lambda) * pmf_lambda->get_qdim() / pmf_lambda->nb_dof();
1209 GMM_ASSERT1(sl == (contact_only ? 1 : N),
1210 "the data corresponding to the contact stress "
1211 "has not the right format");
1214 const model_real_plain_vector *f_coeffs = 0;
1215 const mesh_fem *pmf_coeff = 0;
1216 scalar_type
alpha = 1;
1217 const model_real_plain_vector *WT = 0;
1218 if (!contact_only) {
1220 f_coeffs = &(md.real_variable(dl[nd]));
1221 pmf_coeff = md.pmesh_fem_of_variable(dl[nd]);
1222 sl = gmm::vect_size(*f_coeffs);
1223 if (pmf_coeff) { sl *= pmf_coeff->get_qdim(); sl /= pmf_coeff->nb_dof(); }
1224 GMM_ASSERT1(sl == 1 || sl == 2 || sl == 3,
1225 "the data corresponding to the friction coefficient "
1226 "has not the right format");
1227 if (dl.size() > nd+1) {
1229 alpha = md.real_variable(dl[nd])[0];
1230 GMM_ASSERT1(gmm::vect_size(md.real_variable(dl[nd])) == 1,
1231 "Parameter alpha should be a scalar");
1234 if (dl.size() > nd+1) {
1236 if (dl[nd].compare(vl[0]) != 0)
1237 WT = &(md.real_variable(dl[nd]));
1238 else if (md.n_iter_of_variable(vl[0]) > 1)
1239 WT = &(md.real_variable(vl[0],1));
1243 GMM_ASSERT1(matl.size() == 1,
"Wrong number of terms for "
1244 "penalized contact with rigid obstacle brick");
1246 mesh_region rg(region);
1247 mf_u.linked_mesh().intersect_with_mpi_region(rg);
1249 if (version & model::BUILD_MATRIX) {
1250 GMM_TRACE2(
"Penalized contact with rigid obstacle tangent term");
1253 asm_penalized_contact_rigid_obstacle_tangent_matrix
1254 (matl[0], mim, mf_u, u, mf_obs, obs, pmf_lambda, lambda,
1257 asm_penalized_contact_rigid_obstacle_tangent_matrix
1258 (matl[0], mim, mf_u, u, mf_obs, obs, pmf_lambda, lambda,
1259 pmf_coeff, f_coeffs, vr[0], alpha, WT, rg, option);
1262 if (version & model::BUILD_RHS) {
1265 asm_penalized_contact_rigid_obstacle_rhs
1266 (vecl[0], mim, mf_u, u, mf_obs, obs, pmf_lambda, lambda,
1269 asm_penalized_contact_rigid_obstacle_rhs
1270 (vecl[0], mim, mf_u, u, mf_obs, obs, pmf_lambda, lambda,
1271 pmf_coeff, f_coeffs, vr[0], alpha, WT, rg, option);
1276 penalized_contact_rigid_obstacle_brick(
bool contact_only_,
int option_) {
1277 contact_only = contact_only_;
1279 set_flags(contact_only
1280 ?
"Integral penalized contact with rigid obstacle brick"
1281 :
"Integral penalized contact and friction with rigid obstacle brick",
1282 false , contact_only ,
1296 (
model &md,
const mesh_im &mim,
const std::string &varname_u,
1297 const std::string &dataname_obs,
const std::string &dataname_r,
1298 size_type region,
int option,
const std::string &dataname_n) {
1300 pbrick pbr = std::make_shared<penalized_contact_rigid_obstacle_brick>
1304 tl.push_back(model::term_description(varname_u, varname_u,
true));
1306 model::varnamelist dl(1, dataname_obs);
1307 dl.push_back(dataname_r);
1310 case 2: dl.push_back(dataname_n);
break;
1311 default: GMM_ASSERT1(
false,
"Penalized contact brick : invalid option");
1314 model::varnamelist vl(1, varname_u);
1316 return md.
add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region);
1325 (
model &md,
const mesh_im &mim,
const std::string &varname_u,
1326 const std::string &dataname_obs,
const std::string &dataname_r,
1327 const std::string &dataname_friction_coeffs,
1328 size_type region,
int option,
const std::string &dataname_lambda,
1329 const std::string &dataname_alpha,
const std::string &dataname_wt) {
1331 pbrick pbr = std::make_shared<penalized_contact_rigid_obstacle_brick>
1335 tl.push_back(model::term_description(varname_u, varname_u,
false));
1337 model::varnamelist dl(1, dataname_obs);
1338 dl.push_back(dataname_r);
1341 case 2:
case 3: dl.push_back(dataname_lambda);
break;
1342 default: GMM_ASSERT1(
false,
"Penalized contact brick : invalid option");
1344 dl.push_back(dataname_friction_coeffs);
1345 if (dataname_alpha.size() > 0) {
1346 dl.push_back(dataname_alpha);
1347 if (dataname_wt.size() > 0) dl.push_back(dataname_wt);
1350 model::varnamelist vl(1, varname_u);
1352 return md.
add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region);
1362 template<
typename MAT,
typename VEC>
1363 void asm_Alart_Curnier_contact_nonmatching_meshes_tangent_matrix
1364 (MAT &Ku1l, MAT &Klu1, MAT &Ku2l, MAT &Klu2, MAT &Kll,
1365 MAT &Ku1u1, MAT &Ku2u2, MAT &Ku1u2,
1370 scalar_type r,
const mesh_region &rg,
int option = 1) {
1372 size_type subterm1 = (option == 3) ? K_UL_V2 : K_UL_V1;
1373 size_type subterm2 = (option == 3) ? K_UL_V1 : K_UL_V3;
1374 size_type subterm3 = (option == 3) ? K_LL_V2 : K_LL_V1;
1375 size_type subterm4 = (option == 2) ? K_UU_V2 : K_UU_V1;
1377 contact_nonmatching_meshes_nonlinear_term
1378 nterm1(subterm1, r, mf_u1, U1, mf_u2, U2, &mf_lambda, &lambda),
1379 nterm2(subterm2, r, mf_u1, U1, mf_u2, U2, &mf_lambda, &lambda),
1380 nterm3(subterm3, r, mf_u1, U1, mf_u2, U2, &mf_lambda, &lambda),
1381 nterm4(subterm4, r, mf_u1, U1, mf_u2, U2, &mf_lambda, &lambda);
1387 (
"M$1(#1,#3)+=comp(NonLin$1(#1,#1,#2,#3).vBase(#1).Base(#3))(i,:,i,:); "
1388 "M$2(#3,#1)+=comp(NonLin$2(#1,#1,#2,#3).Base(#3).vBase(#1))(i,:,:,i); "
1389 "M$3(#2,#3)+=comp(NonLin$1(#1,#1,#2,#3).vBase(#2).Base(#3))(i,:,i,:); "
1390 "M$4(#3,#2)+=comp(NonLin$2(#1,#1,#2,#3).Base(#3).vBase(#2))(i,:,:,i); "
1391 "M$5(#3,#3)+=comp(NonLin$3(#1,#1,#2,#3).Base(#3).Base(#3))(i,:,:)");
1395 (
"M$1(#1,#3)+=comp(NonLin$2(#1,#1,#2,#3).vBase(#1).Base(#3))(i,:,i,:); "
1396 "M$3(#2,#3)+=comp(NonLin$2(#1,#1,#2,#3).vBase(#2).Base(#3))(i,:,i,:); "
1397 "M$5(#3,#3)+=comp(NonLin$3(#1,#1,#2,#3).Base(#3).Base(#3))(i,:,:); "
1398 "M$6(#1,#1)+=comp(NonLin$4(#1,#1,#2,#3).vBase(#1).vBase(#1))(i,j,:,i,:,j); "
1399 "M$7(#2,#2)+=comp(NonLin$4(#1,#1,#2,#3).vBase(#2).vBase(#2))(i,j,:,i,:,j); "
1400 "M$8(#1,#2)+=comp(NonLin$4(#1,#1,#2,#3).vBase(#1).vBase(#2))(i,j,:,i,:,j)");
1421 gmm::scale(Ku2l, scalar_type(-1));
1423 gmm::scale(Klu2, scalar_type(-1));
1424 gmm::scale(Ku1u2, scalar_type(-1));
1427 template<
typename MAT,
typename VEC>
1428 void asm_Alart_Curnier_contact_nonmatching_meshes_tangent_matrix
1429 (MAT &Ku1l, MAT &Klu1, MAT &Ku2l, MAT &Klu2, MAT &Kll,
1430 MAT &Ku1u1, MAT &Ku2u2, MAT &Ku1u2, MAT &Ku2u1,
1436 scalar_type r, scalar_type
alpha,
1437 const VEC *WT1,
const VEC *WT2,
1438 const mesh_region &rg,
int option = 1) {
1443 subterm1 = K_UL_FRICT_V1; subterm2 = K_UL_FRICT_V4; subterm3 = K_LL_FRICT_V1;
1446 subterm1 = K_UL_FRICT_V3; subterm2 = K_UL_FRICT_V4; subterm3 = K_LL_FRICT_V1;
1449 subterm1 = K_UL_FRICT_V2; subterm2 = K_UL_FRICT_V5; subterm3 = K_LL_FRICT_V2;
1452 subterm1 = K_UL_FRICT_V7; subterm2 = K_UL_FRICT_V8; subterm3 = K_LL_FRICT_V4;
1454 default : GMM_ASSERT1(
false,
"Incorrect option");
1459 contact_nonmatching_meshes_nonlinear_term
1460 nterm1(subterm1, r, mf_u1, U1, mf_u2, U2, &mf_lambda, &lambda,
1461 pmf_coeff, f_coeffs, alpha, WT1, WT2),
1462 nterm2(subterm2, r, mf_u1, U1, mf_u2, U2, &mf_lambda, &lambda,
1463 pmf_coeff, f_coeffs, alpha, WT1, WT2),
1464 nterm3(subterm3, r, mf_u1, U1, mf_u2, U2, &mf_lambda, &lambda,
1465 pmf_coeff, f_coeffs, alpha, WT1, WT2),
1466 nterm4(subterm4, r, mf_u1, U1, mf_u2, U2, &mf_lambda, &lambda,
1467 pmf_coeff, f_coeffs, alpha, WT1, WT2);
1469 const std::string aux_fems = pmf_coeff ?
"#1,#2,#3,#4" :
"#1,#2,#3";
1473 case 1:
case 3:
case 4:
1475 (
"M$1(#1,#3)+=comp(NonLin$1(#1," + aux_fems +
").vBase(#1).vBase(#3))(i,j,:,i,:,j); "
1476 "M$2(#3,#1)+=comp(NonLin$2(#1," + aux_fems +
").vBase(#3).vBase(#1))(i,j,:,j,:,i); "
1477 "M$3(#2,#3)+=comp(NonLin$1(#1," + aux_fems +
").vBase(#2).vBase(#3))(i,j,:,i,:,j); "
1478 "M$4(#3,#2)+=comp(NonLin$2(#1," + aux_fems +
").vBase(#3).vBase(#2))(i,j,:,j,:,i); "
1479 "M$5(#3,#3)+=comp(NonLin$3(#1," + aux_fems +
").vBase(#3).vBase(#3))(i,j,:,i,:,j)");
1483 (
"M$1(#1,#3)+=comp(NonLin$1(#1," + aux_fems +
").vBase(#1).vBase(#3))(i,j,:,i,:,j); "
1484 "M$2(#3,#1)+=comp(NonLin$2(#1," + aux_fems +
").vBase(#3).vBase(#1))(i,j,:,j,:,i); "
1485 "M$3(#2,#3)+=comp(NonLin$1(#1," + aux_fems +
").vBase(#2).vBase(#3))(i,j,:,i,:,j); "
1486 "M$4(#3,#2)+=comp(NonLin$2(#1," + aux_fems +
").vBase(#3).vBase(#2))(i,j,:,j,:,i); "
1487 "M$5(#3,#3)+=comp(NonLin$3(#1," + aux_fems +
").vBase(#3).vBase(#3))(i,j,:,i,:,j); "
1488 "M$6(#1,#1)+=comp(NonLin$4(#1," + aux_fems +
").vBase(#1).vBase(#1))(i,j,:,i,:,j); "
1489 "M$7(#2,#2)+=comp(NonLin$4(#1," + aux_fems +
").vBase(#2).vBase(#2))(i,j,:,i,:,j); "
1490 "M$8(#1,#2)+=comp(NonLin$4(#1," + aux_fems +
").vBase(#1).vBase(#2))(i,j,:,i,:,j); "
1491 "M$9(#2,#1)+=comp(NonLin$4(#1," + aux_fems +
").vBase(#2).vBase(#1))(i,j,:,i,:,j)");
1515 gmm::scale(Ku2l, scalar_type(-1));
1516 gmm::scale(Klu2, scalar_type(-1));
1517 gmm::scale(Ku1u2, scalar_type(-1));
1520 template<
typename VECT1>
1521 void asm_Alart_Curnier_contact_nonmatching_meshes_rhs
1522 (VECT1 &Ru1, VECT1 &Ru2, VECT1 &Rl,
1527 scalar_type r,
const mesh_region &rg,
int option = 1) {
1531 case 1 : subterm1 = RHS_U_V1;
break;
1532 case 2 : subterm1 = RHS_U_V2;
break;
1533 case 3 : subterm1 = RHS_U_V4;
break;
1534 default : GMM_ASSERT1(
false,
"Incorrect option");
1536 size_type subterm2 = (option == 3) ? RHS_L_V2 : RHS_L_V1;
1538 contact_nonmatching_meshes_nonlinear_term
1539 nterm1(subterm1, r, mf_u1, U1, mf_u2, U2, &mf_lambda, &lambda),
1540 nterm2(subterm2, r, mf_u1, U1, mf_u2, U2, &mf_lambda, &lambda);
1543 assem.set(
"V$1(#1)+=comp(NonLin$1(#1,#1,#2,#3).vBase(#1))(i,:,i); "
1544 "V$2(#2)+=comp(NonLin$1(#1,#1,#2,#3).vBase(#2))(i,:,i); "
1545 "V$3(#3)+=comp(NonLin$2(#1,#1,#2,#3).Base(#3))(i,:)");
1557 gmm::scale(Ru2, scalar_type(-1));
1560 template<
typename VECT1>
1561 void asm_Alart_Curnier_contact_nonmatching_meshes_rhs
1562 (VECT1 &Ru1, VECT1 &Ru2, VECT1 &Rl,
1568 scalar_type r, scalar_type
alpha,
1569 const VECT1 *WT1,
const VECT1 *WT2,
1570 const mesh_region &rg,
int option = 1) {
1574 case 1 : subterm1 = RHS_U_FRICT_V1; subterm2 = RHS_L_FRICT_V1;
break;
1575 case 2 : subterm1 = RHS_U_FRICT_V6; subterm2 = RHS_L_FRICT_V1;
break;
1576 case 3 : subterm1 = RHS_U_FRICT_V4; subterm2 = RHS_L_FRICT_V2;
break;
1577 case 4 : subterm1 = RHS_U_FRICT_V5; subterm2 = RHS_L_FRICT_V4;
break;
1578 default : GMM_ASSERT1(
false,
"Incorrect option");
1581 contact_nonmatching_meshes_nonlinear_term
1582 nterm1(subterm1, r, mf_u1, U1, mf_u2, U2, &mf_lambda, &lambda,
1583 pmf_coeff, f_coeffs, alpha, WT1, WT2),
1584 nterm2(subterm2, r, mf_u1, U1, mf_u2, U2, &mf_lambda, &lambda,
1585 pmf_coeff, f_coeffs, alpha, WT1, WT2);
1587 const std::string aux_fems = pmf_coeff ?
"#1,#2,#3,#4" :
"#1,#2,#3";
1590 assem.set(
"V$1(#1)+=comp(NonLin$1(#1," + aux_fems +
").vBase(#1))(i,:,i); "
1591 "V$2(#2)+=comp(NonLin$1(#1," + aux_fems +
").vBase(#2))(i,:,i); "
1592 "V$3(#3)+=comp(NonLin$2(#1," + aux_fems +
").vBase(#3))(i,:,i)");
1606 gmm::scale(Ru2, scalar_type(-1));
1609 struct integral_contact_nonmatching_meshes_brick :
public virtual_brick {
1622 virtual void asm_real_tangent_terms(
const model &md,
size_type ,
1623 const model::varnamelist &vl,
1624 const model::varnamelist &dl,
1625 const model::mimlist &mims,
1626 model::real_matlist &matl,
1627 model::real_veclist &vecl,
1628 model::real_veclist &,
1630 build_version version)
const {
1632 GMM_ASSERT1(mims.size() == 1,
1633 "Integral contact between nonmatching meshes bricks need a single mesh_im");
1634 const mesh_im &mim = *mims[0];
1639 GMM_ASSERT1(vl.size() == 3,
1640 "Integral contact between nonmatching meshes bricks need three variables");
1641 const model_real_plain_vector &u1 = md.real_variable(vl[0]);
1642 const model_real_plain_vector &u2 = md.real_variable(vl[1]);
1643 const mesh_fem &mf_u1 = md.mesh_fem_of_variable(vl[0]);
1644 const mesh_fem &mf_u2 = md.mesh_fem_of_variable(vl[1]);
1645 const model_real_plain_vector &lambda = md.real_variable(vl[2]);
1646 const mesh_fem &mf_lambda = md.mesh_fem_of_variable(vl[2]);
1647 GMM_ASSERT1(mf_lambda.get_qdim() == (contact_only ? 1 : mf_u1.get_qdim()),
1648 "The contact stress variable has not the right dimension");
1653 GMM_ASSERT1(dl.size() == 1,
1654 "Wrong number of data for integral contact between nonmatching meshes "
1655 <<
"brick, the number of data should be equal to 1 .");
1658 GMM_ASSERT1(dl.size() >= 2 && dl.size() <= 5,
1659 "Wrong number of data for integral contact between nonmatching meshes "
1660 <<
"brick, it should be between 2 and 5 instead of " << dl.size() <<
" .");
1662 const model_real_plain_vector &vr = md.real_variable(dl[0]);
1663 GMM_ASSERT1(gmm::vect_size(vr) == 1,
"Parameter r should be a scalar");
1665 const model_real_plain_vector *f_coeffs = 0, *WT1 = 0, *WT2 = 0;
1666 const mesh_fem *pmf_coeff = 0;
1667 scalar_type
alpha = 1;
1668 if (!contact_only) {
1669 f_coeffs = &(md.real_variable(dl[1]));
1670 pmf_coeff = md.pmesh_fem_of_variable(dl[1]);
1672 size_type sl = gmm::vect_size(*f_coeffs);
1673 if (pmf_coeff) { sl *= pmf_coeff->get_qdim(); sl /= pmf_coeff->nb_dof(); }
1674 GMM_ASSERT1(sl == 1 || sl == 2 || sl ==3,
1675 "the data corresponding to the friction coefficient "
1676 "has not the right format");
1678 if (dl.size() >= 3) {
1679 alpha = md.real_variable(dl[2])[0];
1680 GMM_ASSERT1(gmm::vect_size(md.real_variable(dl[2])) == 1,
1681 "Parameter alpha should be a scalar");
1684 if (dl.size() >= 4) {
1685 if (dl[3].compare(vl[0]) != 0)
1686 WT1 = &(md.real_variable(dl[3]));
1687 else if (md.n_iter_of_variable(vl[0]) > 1)
1688 WT1 = &(md.real_variable(vl[0],1));
1691 if (dl.size() >= 5) {
1692 if (dl[4].compare(vl[1]) != 0)
1693 WT2 = &(md.real_variable(dl[4]));
1694 else if (md.n_iter_of_variable(vl[1]) > 1)
1695 WT2 = &(md.real_variable(vl[1],1));
1700 GMM_ASSERT1(matl.size() ==
size_type(3 +
1701 2 * !is_symmetric() +
1703 1 * (option == 2 && !is_symmetric())),
1704 "Wrong number of terms for "
1705 "integral contact between nonmatching meshes brick");
1707 mesh_region rg(region);
1708 mf_u1.linked_mesh().intersect_with_mpi_region(rg);
1710 size_type N = mf_u1.linked_mesh().dim();
1717 mf_u2_proj.set_finite_element(mim.linked_mesh().convex_index(), pfem_proj);
1720 size_type nbdof_lambda = mf_lambda.nb_dof();
1722 size_type nbsub = mf_u2_proj.nb_basic_dof();
1724 std::vector<size_type> ind;
1725 mf_u2_proj.get_global_dof_index(ind);
1726 gmm::unsorted_sub_index SUBI(ind);
1728 gmm::csc_matrix<scalar_type> Esub(nbsub, nbdof2);
1729 if (mf_u2.is_reduced())
1730 gmm::copy(gmm::sub_matrix(mf_u2.extension_matrix(),
1731 SUBI, gmm::sub_interval(0, nbdof2)),
1734 model_real_plain_vector u2_proj(nbsub);
1735 if (mf_u2.is_reduced())
1738 gmm::copy(gmm::sub_vector(u2, SUBI), u2_proj);
1740 model_real_plain_vector WT2_proj(0);
1743 if (mf_u2.is_reduced())
1746 gmm::copy(gmm::sub_vector(*WT2, SUBI), WT2_proj);
1759 if (version & model::BUILD_MATRIX) {
1760 GMM_TRACE2(
"Integral contact between nonmatching meshes "
1762 for (
size_type i = 0; i < matl.size(); i++) gmm::clear(matl[i]);
1764 model_real_sparse_matrix dummy_mat(0, 0);
1765 model_real_sparse_matrix &Klu1 = (LU1 ==
size_type(-1)) ? dummy_mat : matl[LU1];
1766 model_real_sparse_matrix &Ku1u1 = (U1U1 ==
size_type(-1)) ? dummy_mat : matl[U1U1];
1768 model_real_sparse_matrix Ku2l(nbsub, nbdof_lambda);
1769 model_real_sparse_matrix Klu2(nbdof_lambda, nbsub);
1770 model_real_sparse_matrix Ku2u2(nbsub, nbsub);
1771 model_real_sparse_matrix Ku1u2(nbdof1, nbsub);
1772 model_real_sparse_matrix Ku2u1(nbsub, nbdof1);
1775 asm_Alart_Curnier_contact_nonmatching_meshes_tangent_matrix
1776 (matl[U1L], Klu1, Ku2l, Klu2, matl[LL], Ku1u1, Ku2u2, Ku1u2,
1777 mim, mf_u1, u1, mf_u2_proj, u2_proj, mf_lambda, lambda,
1780 asm_Alart_Curnier_contact_nonmatching_meshes_tangent_matrix
1781 (matl[U1L], Klu1, Ku2l, Klu2, matl[LL], Ku1u1, Ku2u2, Ku1u2, Ku2u1,
1782 mim, mf_u1, u1, mf_u2_proj, u2_proj, mf_lambda, lambda,
1783 pmf_coeff, f_coeffs, vr[0], alpha, WT1, &WT2_proj, rg, option);
1785 if (mf_u2.is_reduced()) {
1786 gmm::mult(gmm::transposed(Esub), Ku2l, matl[U2L]);
1789 model_real_sparse_matrix tmp(nbsub, nbdof2);
1791 gmm::mult(gmm::transposed(Esub), tmp, matl[U2U2]);
1797 gmm::copy(Ku2l, gmm::sub_matrix(matl[U2L], SUBI, gmm::sub_interval(0, nbdof_lambda)));
1799 gmm::copy(Klu2, gmm::sub_matrix(matl[LU2], gmm::sub_interval(0, nbdof_lambda), SUBI));
1801 gmm::copy(Ku2u2, gmm::sub_matrix(matl[U2U2], SUBI));
1803 gmm::copy(Ku1u2, gmm::sub_matrix(matl[U1U2], gmm::sub_interval(0, nbdof1), SUBI));
1805 gmm::copy(Ku2u1, gmm::sub_matrix(matl[U2U1], SUBI, gmm::sub_interval(0, nbdof1)));
1809 if (version & model::BUILD_RHS) {
1810 for (
size_type i = 0; i < matl.size(); i++) gmm::clear(vecl[i]);
1812 model_real_plain_vector Ru2(nbsub);
1815 asm_Alart_Curnier_contact_nonmatching_meshes_rhs
1816 (vecl[U1L], Ru2, vecl[LL],
1817 mim, mf_u1, u1, mf_u2_proj, u2_proj, mf_lambda, lambda,
1820 asm_Alart_Curnier_contact_nonmatching_meshes_rhs
1821 (vecl[U1L], Ru2, vecl[LL],
1822 mim, mf_u1, u1, mf_u2_proj, u2_proj, mf_lambda, lambda,
1823 pmf_coeff, f_coeffs, vr[0], alpha, WT1, &WT2_proj, rg, option);
1825 if (mf_u2.is_reduced())
1826 gmm::mult(gmm::transposed(Esub), Ru2, vecl[U2L]);
1828 gmm::copy(Ru2, gmm::sub_vector(vecl[U2L], SUBI));
1833 bool contact_only_,
int option_)
1834 : rg1(rg1_), rg2(rg2_), pfem_proj(0),
1835 contact_only(contact_only_), option(option_)
1837 set_flags(contact_only
1838 ?
"Integral contact between nonmatching meshes brick"
1839 :
"Integral contact and friction between nonmatching "
1842 (option==2) && contact_only ,
1847 ~integral_contact_nonmatching_meshes_brick()
1859 (
model &md,
const mesh_im &mim,
const std::string &varname_u1,
1860 const std::string &varname_u2,
const std::string &multname_n,
1861 const std::string &dataname_r,
1864 pbrick pbr = std::make_shared<integral_contact_nonmatching_meshes_brick>
1865 (region1, region2,
true , option);
1871 tl.push_back(model::term_description(varname_u1, multname_n,
false));
1872 tl.push_back(model::term_description(multname_n, varname_u1,
false));
1873 tl.push_back(model::term_description(varname_u2, multname_n,
false));
1874 tl.push_back(model::term_description(multname_n, varname_u2,
false));
1875 tl.push_back(model::term_description(multname_n, multname_n,
true));
1878 tl.push_back(model::term_description(varname_u1, multname_n,
true));
1879 tl.push_back(model::term_description(varname_u2, multname_n,
true));
1880 tl.push_back(model::term_description(multname_n, multname_n,
true));
1881 tl.push_back(model::term_description(varname_u1, varname_u1,
true));
1882 tl.push_back(model::term_description(varname_u2, varname_u2,
true));
1883 tl.push_back(model::term_description(varname_u1, varname_u2,
true));
1885 default : GMM_ASSERT1(
false,
1886 "Incorrect option for integral contact brick");
1889 model::varnamelist dl(1, dataname_r);
1891 model::varnamelist vl(1, varname_u1);
1892 vl.push_back(varname_u2);
1893 vl.push_back(multname_n);
1895 return md.
add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region1);
1905 (
model &md,
const mesh_im &mim,
const std::string &varname_u1,
1906 const std::string &varname_u2,
const std::string &multname,
1907 const std::string &dataname_r,
const std::string &dataname_friction_coeffs,
1909 const std::string &dataname_alpha,
1910 const std::string &dataname_wt1,
const std::string &dataname_wt2) {
1912 pbrick pbr = std::make_shared<integral_contact_nonmatching_meshes_brick>
1913 (region1, region2,
false , option);
1918 case 1 :
case 3 :
case 4 :
1919 tl.push_back(model::term_description(varname_u1, multname,
false));
1920 tl.push_back(model::term_description(multname, varname_u1,
false));
1921 tl.push_back(model::term_description(varname_u2, multname,
false));
1922 tl.push_back(model::term_description(multname, varname_u2,
false));
1923 tl.push_back(model::term_description(multname, multname,
true));
1926 tl.push_back(model::term_description(varname_u1, multname,
false));
1927 tl.push_back(model::term_description(multname, varname_u1,
false));
1928 tl.push_back(model::term_description(varname_u2, multname,
false));
1929 tl.push_back(model::term_description(multname, varname_u2,
false));
1930 tl.push_back(model::term_description(multname, multname,
true));
1931 tl.push_back(model::term_description(varname_u1, varname_u1,
true));
1932 tl.push_back(model::term_description(varname_u2, varname_u2,
true));
1933 tl.push_back(model::term_description(varname_u1, varname_u2,
true));
1934 tl.push_back(model::term_description(varname_u2, varname_u1,
true));
1936 default : GMM_ASSERT1(
false,
1937 "Incorrect option for integral contact brick");
1940 model::varnamelist dl(1, dataname_r);
1941 dl.push_back(dataname_friction_coeffs);
1942 if (dataname_alpha.size()) {
1943 dl.push_back(dataname_alpha);
1944 if (dataname_wt1.size()) {
1945 dl.push_back(dataname_wt1);
1946 if (dataname_wt2.size()) {
1947 dl.push_back(dataname_wt2);
1953 model::varnamelist vl(1, varname_u1);
1954 vl.push_back(varname_u2);
1955 vl.push_back(multname);
1957 return md.
add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region1);
1967 template<
typename MAT,
typename VECT1>
1968 void asm_penalized_contact_nonmatching_meshes_tangent_matrix
1969 (MAT &Ku1u1, MAT &Ku2u2, MAT &Ku1u2,
1974 const scalar_type r,
const mesh_region &rg,
int option = 1) {
1976 contact_nonmatching_meshes_nonlinear_term
1977 nterm((option == 1) ? K_UU_V1 : K_UU_V2, r,
1978 mf_u1, U1, mf_u2, U2, pmf_lambda, lambda);
1980 const std::string aux_fems = pmf_lambda ?
"#1,#2,#3" :
"#1,#2";
1983 assem.set(
"M$1(#1,#1)+=comp(NonLin(#1," + aux_fems +
").vBase(#1).vBase(#1))(i,j,:,i,:,j); "
1984 "M$2(#2,#2)+=comp(NonLin(#1," + aux_fems +
").vBase(#2).vBase(#2))(i,j,:,i,:,j); "
1985 "M$3(#1,#2)+=comp(NonLin(#1," + aux_fems +
").vBase(#1).vBase(#2))(i,j,:,i,:,j)");
1997 gmm::scale(Ku1u2, scalar_type(-1));
2000 template<
typename VECT1>
2001 void asm_penalized_contact_nonmatching_meshes_rhs
2002 (VECT1 &Ru1, VECT1 &Ru2,
2007 scalar_type r,
const mesh_region &rg,
int option = 1) {
2009 contact_nonmatching_meshes_nonlinear_term
2010 nterm((option == 1) ? RHS_U_V5 : RHS_U_V2, r,
2011 mf_u1, U1, mf_u2, U2, pmf_lambda, lambda);
2013 const std::string aux_fems = pmf_lambda ?
"#1,#2,#3":
"#1,#2";
2015 assem.set(
"V$1(#1)+=comp(NonLin$1(#1," + aux_fems +
").vBase(#1))(i,:,i); "
2016 "V$2(#2)+=comp(NonLin$1(#1," + aux_fems +
").vBase(#2))(i,:,i)");
2027 gmm::scale(Ru2, scalar_type(-1));
2031 template<
typename MAT,
typename VECT1>
2032 void asm_penalized_contact_nonmatching_meshes_tangent_matrix
2033 (MAT &Ku1u1, MAT &Ku2u2, MAT &Ku1u2, MAT &Ku2u1,
2039 scalar_type
alpha,
const VECT1 *WT1,
const VECT1 *WT2,
2040 const mesh_region &rg,
int option = 1) {
2044 case 1 : subterm = K_UU_FRICT_V4;
break;
2045 case 2 : subterm = K_UU_FRICT_V3;
break;
2046 case 3 : subterm = K_UU_FRICT_V5;
break;
2049 contact_nonmatching_meshes_nonlinear_term
2050 nterm(subterm, r, mf_u1, U1, mf_u2, U2, pmf_lambda, lambda,
2051 pmf_coeff, f_coeffs, alpha, WT1, WT2);
2053 const std::string aux_fems = pmf_coeff ?
"#1,#2,#3,#4"
2054 : (pmf_lambda ?
"#1,#2,#3":
"#1,#2");
2057 assem.set(
"M$1(#1,#1)+=comp(NonLin(#1," + aux_fems +
").vBase(#1).vBase(#1))(i,j,:,i,:,j); "
2058 "M$2(#2,#2)+=comp(NonLin(#1," + aux_fems +
").vBase(#2).vBase(#2))(i,j,:,i,:,j); "
2059 "M$3(#1,#2)+=comp(NonLin(#1," + aux_fems +
").vBase(#1).vBase(#2))(i,j,:,i,:,j); "
2060 "M$4(#2,#1)+=comp(NonLin(#1," + aux_fems +
").vBase(#2).vBase(#1))(i,j,:,i,:,j)");
2080 gmm::scale(Ku1u2, scalar_type(-1));
2081 gmm::scale(Ku2u1, scalar_type(-1));
2085 template<
typename VECT1>
2086 void asm_penalized_contact_nonmatching_meshes_rhs
2087 (VECT1 &Ru1, VECT1 &Ru2,
2093 scalar_type
alpha,
const VECT1 *WT1,
const VECT1 *WT2,
2094 const mesh_region &rg,
int option = 1) {
2098 case 1 : subterm = RHS_U_FRICT_V7;
break;
2099 case 2 : subterm = RHS_U_FRICT_V6;
break;
2100 case 3 : subterm = RHS_U_FRICT_V8;
break;
2103 contact_nonmatching_meshes_nonlinear_term
2104 nterm(subterm, r, mf_u1, U1, mf_u2, U2, pmf_lambda, lambda,
2105 pmf_coeff, f_coeffs, alpha, WT1, WT2);
2107 const std::string aux_fems = pmf_coeff ?
"#1,#2,#3,#4"
2108 : (pmf_lambda ?
"#1,#2,#3":
"#1,#2");
2110 assem.set(
"V$1(#1)+=comp(NonLin$1(#1," + aux_fems +
").vBase(#1))(i,:,i); "
2111 "V$2(#2)+=comp(NonLin$1(#1," + aux_fems +
").vBase(#2))(i,:,i)");
2130 gmm::scale(Ru2, scalar_type(-1));
2134 struct penalized_contact_nonmatching_meshes_brick :
public virtual_brick {
2142 virtual void asm_real_tangent_terms(
const model &md,
size_type ,
2143 const model::varnamelist &vl,
2144 const model::varnamelist &dl,
2145 const model::mimlist &mims,
2146 model::real_matlist &matl,
2147 model::real_veclist &vecl,
2148 model::real_veclist &,
2150 build_version version)
const {
2152 GMM_ASSERT1(mims.size() == 1,
2153 "Penalized contact between nonmatching meshes bricks need a single mesh_im");
2154 const mesh_im &mim = *mims[0];
2157 GMM_ASSERT1(vl.size() == 2,
2158 "Penalized contact between nonmatching meshes bricks need two variables");
2159 const model_real_plain_vector &u1 = md.real_variable(vl[0]);
2160 const model_real_plain_vector &u2 = md.real_variable(vl[1]);
2161 const mesh_fem &mf_u1 = md.mesh_fem_of_variable(vl[0]);
2162 const mesh_fem &mf_u2 = md.mesh_fem_of_variable(vl[1]);
2164 size_type N = mf_u1.linked_mesh().dim();
2167 size_type nb_data_1 = ((option == 1) ? 1 : 2) + (contact_only ? 0 : 1);
2168 size_type nb_data_2 = nb_data_1 + (contact_only ? 0 : 3);
2169 GMM_ASSERT1(dl.size() >= nb_data_1 && dl.size() <= nb_data_2,
2170 "Wrong number of data for penalized contact between nonmatching meshes "
2171 <<
"brick, " << dl.size() <<
" should be between "
2172 << nb_data_1 <<
" and " << nb_data_2 <<
".");
2175 const model_real_plain_vector &vr = md.real_variable(dl[nd]);
2176 GMM_ASSERT1(gmm::vect_size(vr) == 1,
"Parameter r should be a scalar");
2179 const model_real_plain_vector *lambda = 0;
2180 const mesh_fem *pmf_lambda = 0;
2183 lambda = &(md.real_variable(dl[nd]));
2184 pmf_lambda = md.pmesh_fem_of_variable(dl[nd]);
2185 sl = gmm::vect_size(*lambda) * pmf_lambda->get_qdim() / pmf_lambda->nb_dof();
2186 GMM_ASSERT1(sl == (contact_only ? 1 : N),
2187 "the data corresponding to the contact stress "
2188 "has not the right format");
2191 const model_real_plain_vector *f_coeffs = 0;
2192 const mesh_fem *pmf_coeff = 0;
2193 scalar_type
alpha = 1;
2194 const model_real_plain_vector *WT1 = 0;
2195 const model_real_plain_vector *WT2 = 0;
2196 if (!contact_only) {
2198 f_coeffs = &(md.real_variable(dl[nd]));
2199 pmf_coeff = md.pmesh_fem_of_variable(dl[nd]);
2200 sl = gmm::vect_size(*f_coeffs);
2201 if (pmf_coeff) { sl *= pmf_coeff->get_qdim(); sl /= pmf_coeff->nb_dof(); }
2202 GMM_ASSERT1(sl == 1 || sl == 2 || sl == 3,
2203 "the data corresponding to the friction coefficient "
2204 "has not the right format");
2206 if (dl.size() > nd+1) {
2208 alpha = md.real_variable(dl[nd])[0];
2209 GMM_ASSERT1(gmm::vect_size(md.real_variable(dl[nd])) == 1,
2210 "Parameter alpha should be a scalar");
2213 if (dl.size() > nd+1) {
2215 if (dl[nd].compare(vl[0]) != 0)
2216 WT1 = &(md.real_variable(dl[nd]));
2217 else if (md.n_iter_of_variable(vl[0]) > 1)
2218 WT1 = &(md.real_variable(vl[0],1));
2221 if (dl.size() > nd+1) {
2223 if (dl[nd].compare(vl[1]) != 0)
2224 WT2 = &(md.real_variable(dl[nd]));
2225 else if (md.n_iter_of_variable(vl[1]) > 1)
2226 WT2 = &(md.real_variable(vl[1],1));
2230 GMM_ASSERT1(matl.size() == (contact_only ? 3 : 4),
2231 "Wrong number of terms for penalized contact "
2232 "between nonmatching meshes brick");
2234 mesh_region rg(region);
2235 mf_u1.linked_mesh().intersect_with_mpi_region(rg);
2242 mf_u2_proj.set_finite_element(mim.linked_mesh().convex_index(), pfem_proj);
2248 std::vector<size_type> ind;
2249 mf_u2_proj.get_global_dof_index(ind);
2250 gmm::unsorted_sub_index SUBI(ind);
2252 gmm::csc_matrix<scalar_type> Esub(nbsub, nbdof2);
2253 if (mf_u2.is_reduced())
2254 gmm::copy(gmm::sub_matrix(mf_u2.extension_matrix(),
2255 SUBI, gmm::sub_interval(0, nbdof2)),
2258 model_real_plain_vector u2_proj(nbsub);
2259 if (mf_u2.is_reduced())
2262 gmm::copy(gmm::sub_vector(u2, SUBI), u2_proj);
2264 model_real_plain_vector WT2_proj(0);
2267 if (mf_u2.is_reduced())
2270 gmm::copy(gmm::sub_vector(*WT2, SUBI), WT2_proj);
2273 if (version & model::BUILD_MATRIX) {
2274 GMM_TRACE2(
"Penalized contact between nonmatching meshes tangent term");
2279 model_real_sparse_matrix Ku2u2(nbsub,nbsub);
2280 model_real_sparse_matrix Ku1u2(nbdof1,nbsub);
2283 asm_penalized_contact_nonmatching_meshes_tangent_matrix
2284 (matl[0], Ku2u2, Ku1u2, mim, mf_u1, u1, mf_u2_proj, u2_proj,
2285 pmf_lambda, lambda, vr[0], rg, option);
2289 model_real_sparse_matrix Ku2u1(nbsub,nbdof1);
2290 asm_penalized_contact_nonmatching_meshes_tangent_matrix
2291 (matl[0], Ku2u2, Ku1u2, Ku2u1, mim, mf_u1, u1, mf_u2_proj, u2_proj,
2292 pmf_lambda, lambda, pmf_coeff, f_coeffs, vr[0], alpha, WT1, &WT2_proj, rg, option);
2293 if (mf_u2.is_reduced())
2294 gmm::mult(gmm::transposed(Esub), Ku2u1, matl[3]);
2296 gmm::copy(Ku2u1, gmm::sub_matrix(matl[3], SUBI, gmm::sub_interval(0, nbdof1)));
2299 if (mf_u2.is_reduced()) {
2300 model_real_sparse_matrix tmp(nbsub, nbdof2);
2302 gmm::mult(gmm::transposed(Esub), tmp, matl[1]);
2306 gmm::copy(Ku2u2, gmm::sub_matrix(matl[1], SUBI));
2307 gmm::copy(Ku1u2, gmm::sub_matrix(matl[2], gmm::sub_interval(0, nbdof1), SUBI));
2311 if (version & model::BUILD_RHS) {
2315 model_real_plain_vector Ru2(nbsub);
2318 asm_penalized_contact_nonmatching_meshes_rhs
2319 (vecl[0], Ru2, mim, mf_u1, u1, mf_u2_proj, u2_proj, pmf_lambda, lambda,
2322 asm_penalized_contact_nonmatching_meshes_rhs
2323 (vecl[0], Ru2, mim, mf_u1, u1, mf_u2_proj, u2_proj, pmf_lambda, lambda,
2324 pmf_coeff, f_coeffs, vr[0], alpha, WT1, &WT2_proj, rg, option);
2326 if (mf_u2.is_reduced())
2327 gmm::mult(gmm::transposed(Esub), Ru2, vecl[1]);
2329 gmm::copy(Ru2, gmm::sub_vector(vecl[1], SUBI));
2334 bool contact_only_,
int option_)
2335 : rg1(rg1_), rg2(rg2_), pfem_proj(0),
2336 contact_only(contact_only_), option(option_)
2338 set_flags(contact_only
2339 ?
"Integral penalized contact between nonmatching meshes brick"
2340 :
"Integral penalized contact and friction between nonmatching "
2342 false , contact_only ,
2347 ~penalized_contact_nonmatching_meshes_brick()
2359 (
model &md,
const mesh_im &mim,
const std::string &varname_u1,
2360 const std::string &varname_u2,
const std::string &dataname_r,
2362 int option,
const std::string &dataname_n) {
2364 pbrick pbr = std::make_shared<penalized_contact_nonmatching_meshes_brick>
2365 (region1, region2,
true , option);
2367 tl.push_back(model::term_description(varname_u1, varname_u1,
true));
2368 tl.push_back(model::term_description(varname_u2, varname_u2,
true));
2369 tl.push_back(model::term_description(varname_u1, varname_u2,
true));
2371 model::varnamelist dl(1, dataname_r);
2374 case 2: dl.push_back(dataname_n);
break;
2375 default: GMM_ASSERT1(
false,
"Penalized contact brick : invalid option");
2378 model::varnamelist vl(1, varname_u1);
2379 vl.push_back(varname_u2);
2381 return md.
add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region1);
2391 (
model &md,
const mesh_im &mim,
const std::string &varname_u1,
2392 const std::string &varname_u2,
const std::string &dataname_r,
2393 const std::string &dataname_friction_coeffs,
2395 const std::string &dataname_lambda,
const std::string &dataname_alpha,
2396 const std::string &dataname_wt1,
const std::string &dataname_wt2) {
2398 pbrick pbr = std::make_shared<penalized_contact_nonmatching_meshes_brick>
2399 (region1, region2,
false , option);
2401 tl.push_back(model::term_description(varname_u1, varname_u1,
true));
2402 tl.push_back(model::term_description(varname_u2, varname_u2,
true));
2403 tl.push_back(model::term_description(varname_u1, varname_u2,
true));
2404 tl.push_back(model::term_description(varname_u2, varname_u1,
true));
2406 model::varnamelist dl(1, dataname_r);
2409 case 2:
case 3: dl.push_back(dataname_lambda);
break;
2410 default: GMM_ASSERT1(
false,
"Penalized contact brick : invalid option");
2412 dl.push_back(dataname_friction_coeffs);
2413 if (dataname_alpha.size() > 0) {
2414 dl.push_back(dataname_alpha);
2415 if (dataname_wt1.size() > 0) {
2416 dl.push_back(dataname_wt1);
2417 if (dataname_wt2.size() > 0)
2418 dl.push_back(dataname_wt2);
2422 model::varnamelist vl(1, varname_u1);
2423 vl.push_back(varname_u2);
2425 return md.
add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region1);
2430 void compute_integral_contact_area_and_force
2431 (model &md,
size_type indbrick, scalar_type &area,
2432 model_real_plain_vector &F) {
2434 pbrick pbr = md.brick_pointer(indbrick);
2435 const model::mimlist &ml = md.mimlist_of_brick(indbrick);
2436 const model::varnamelist &vl = md.varnamelist_of_brick(indbrick);
2437 const model::varnamelist &dl = md.datanamelist_of_brick(indbrick);
2438 size_type reg = md.region_of_brick(indbrick);
2440 GMM_ASSERT1(ml.size() == 1,
"Wrong size");
2442 if (pbr->brick_name() ==
"Integral contact with rigid obstacle brick" ||
2443 pbr->brick_name() ==
"Integral contact and friction with rigid obstacle brick") {
2444 integral_contact_rigid_obstacle_brick *p
2445 =
dynamic_cast<integral_contact_rigid_obstacle_brick *
>
2446 (
const_cast<virtual_brick *
>(pbr.get()));
2447 GMM_ASSERT1(p,
"Wrong type of brick");
2449 GMM_ASSERT1(vl.size() >= 2,
"Wrong size");
2450 const model_real_plain_vector &u = md.real_variable(vl[0]);
2451 const mesh_fem &mf_u = md.mesh_fem_of_variable(vl[0]);
2452 const model_real_plain_vector &lambda = md.real_variable(vl[1]);
2453 const mesh_fem &mf_lambda = md.mesh_fem_of_variable(vl[1]);
2454 GMM_ASSERT1(dl.size() >= 1,
"Wrong size");
2455 const model_real_plain_vector &obs = md.real_variable(dl[0]);
2456 const mesh_fem &mf_obs = md.mesh_fem_of_variable(dl[0]);
2459 area = asm_level_set_contact_area(*ml[0], mf_u, u, mf_obs, obs, reg, -1e-3,
2460 &mf_lambda, &lambda, 1e-1);
2462 gmm::resize(F, mf_u.nb_dof());
2464 (F, *ml[0], mf_u, mf_obs, obs, mf_lambda, lambda, reg);
2466 else if (pbr->brick_name() ==
"Integral penalized contact with rigid obstacle brick" ||
2467 pbr->brick_name() ==
"Integral penalized contact and friction with rigid "
2469 penalized_contact_rigid_obstacle_brick *p
2470 =
dynamic_cast<penalized_contact_rigid_obstacle_brick *
>
2471 (
const_cast<virtual_brick *
>(pbr.get()));
2472 GMM_ASSERT1(p,
"Wrong type of brick");
2473 GMM_ASSERT1(
false,
"Not implemented yet");
2475 else if (pbr->brick_name() ==
"Integral contact between nonmatching meshes brick" ||
2476 pbr->brick_name() ==
"Integral contact and friction between nonmatching "
2478 integral_contact_nonmatching_meshes_brick *p
2479 =
dynamic_cast<integral_contact_nonmatching_meshes_brick *
>
2480 (
const_cast<virtual_brick *
>(pbr.get()));
2481 GMM_ASSERT1(p,
"Wrong type of brick");
2483 GMM_ASSERT1(vl.size() == 3,
"Wrong size");
2484 const model_real_plain_vector &u1 = md.real_variable(vl[0]);
2485 const model_real_plain_vector &u2 = md.real_variable(vl[1]);
2486 const mesh_fem &mf_u1 = md.mesh_fem_of_variable(vl[0]);
2487 const mesh_fem &mf_u2 = md.mesh_fem_of_variable(vl[1]);
2488 const model_real_plain_vector &lambda = md.real_variable(vl[2]);
2489 const mesh_fem &mf_lambda = md.mesh_fem_of_variable(vl[2]);
2492 getfem::mesh_fem mf_u2_proj(mf_u1.linked_mesh(), mf_u1.linked_mesh().dim());
2493 mf_u2_proj.set_finite_element(mf_u1.linked_mesh().convex_index(), pfem_proj);
2495 std::vector<size_type> ind;
2496 mf_u2_proj.get_global_dof_index(ind);
2497 gmm::unsorted_sub_index SUBI(ind);
2500 size_type nbsub = mf_u2_proj.nb_basic_dof();
2501 model_real_plain_vector u2_proj(nbsub);
2503 if (mf_u2.is_reduced()) {
2504 gmm::csc_matrix<scalar_type> Esub(nbsub, nbdof2);
2505 gmm::copy(gmm::sub_matrix(mf_u2.extension_matrix(),
2506 SUBI, gmm::sub_interval(0, nbdof2)),
2511 gmm::copy(gmm::sub_vector(u2, SUBI), u2_proj);
2514 area = asm_nonmatching_meshes_contact_area
2515 (*ml[0], mf_u1, u1, mf_u2_proj, u2_proj, reg, -1e-3,
2516 &mf_lambda, &lambda, 1e-1);
2519 asm_nonmatching_meshes_normal_source_term
2520 (F, *ml[0], mf_u1, mf_u2_proj, mf_lambda, lambda, reg);
2524 else if (pbr->brick_name() ==
"Integral penalized contact between nonmatching meshes brick" ||
2525 pbr->brick_name() ==
"Integral penalized contact and friction between nonmatching "
2527 penalized_contact_nonmatching_meshes_brick *p
2528 =
dynamic_cast<penalized_contact_nonmatching_meshes_brick *
>
2529 (
const_cast<virtual_brick *
>(pbr.get()));
2530 GMM_ASSERT1(p,
"Wrong type of brick");
2531 GMM_ASSERT1(
false,
"Not implemented yet");
2543 (
model &md,
const mesh_im &mim,
const std::string &varname_u,
2544 const std::string &Neumannterm,
2545 const std::string &obs,
const std::string &dataname_gamma0,
2547 std::string dataname_friction_coeff,
2548 const std::string &dataname_alpha,
2549 const std::string &dataname_wt,
2552 std::string theta = std::to_string(theta_);
2553 ga_workspace workspace(md, ga_workspace::inherit::ALL);
2554 size_type order = workspace.add_expression(Neumannterm, mim, region, 1);
2555 GMM_ASSERT1(order == 0,
"Wrong expression of the Neumann term");
2559 std::string gamma =
"(("+dataname_gamma0+
")/element_size)";
2560 std::string thetagamma =
"("+theta+
"/"+gamma+
")";
2561 std::string contact_normal =
"(-Normalized(Grad_"+obs+
"))";
2562 std::string gap =
"("+obs+
"-"+varname_u+
"."+contact_normal+
")";
2563 std::string Vs =
"("+varname_u +
2564 (dataname_wt.size() ?
"-("+dataname_wt+
"))" :
")");
2565 if (dataname_alpha.size()) Vs =
"(("+dataname_alpha+
")*"+Vs;
2566 if (dataname_friction_coeff.size() == 0)
2567 dataname_friction_coeff = std::string(
"0");
2569 std::string expr =
"Coulomb_friction_coupled_projection("+Neumannterm
2570 +
", "+contact_normal+
", "+Vs+
", "+gap+
", "+dataname_friction_coeff
2573 if (theta_ != scalar_type(0)) {
2574 std::string derivative_Neumann=workspace.extract_order1_term(varname_u);
2575 expr =
"-"+thetagamma+
"*("+Neumannterm+
").("+derivative_Neumann
2576 +
") + "+expr+thetagamma+
"*("+derivative_Neumann+
")";
2578 expr +=
"-Test_"+varname_u+
")";
2581 (md, mim, expr, region,
false,
false,
2582 "Nitsche contact with rigid obstacle");
2585 #ifdef EXPERIMENTAL_PURPOSE_ONLY
2595 size_type add_Nitsche_contact_with_rigid_obstacle_brick_modified_midpoint
2596 (model &md,
const mesh_im &mim,
const std::string &varname_u,
2597 const std::string &Neumannterm,
2598 const std::string &Neumannterm_wt,
2599 const std::string &obs,
const std::string &dataname_gamma0,
2601 std::string dataname_friction_coeff,
2602 const std::string &,
2603 const std::string &dataname_wt,
2606 std::string theta = std::to_string(theta_);
2607 ga_workspace workspace(md, ga_workspace::inherit::ALL);
2608 size_type order = workspace.add_expression(Neumannterm, mim, region, 1);
2609 GMM_ASSERT1(order == 0,
"Wrong expression of the Neumann term");
2611 std::string gamma =
"((1/("+dataname_gamma0+
"))*element_size)";
2612 std::string thetagamma =
"("+theta+
"*"+gamma+
")";
2613 std::string contact_normal =
"(-Normalized(Grad_"+obs+
"))";
2614 std::string gap =
"("+obs+
"-"+varname_u+
"."+contact_normal+
")";
2615 std::string gap_wt =
"("+obs+
"-"+dataname_wt+
"."+contact_normal+
")";
2616 std::string Vs =
"("+varname_u +
2617 (dataname_wt.size() ?
"-("+dataname_wt+
"))" :
")");
2618 std::string Vs_wt = Vs;
2619 if (dataname_friction_coeff.size() == 0)
2620 dataname_friction_coeff = std::string(
"0");
2622 std::string Pg_wt =
"(-"+gamma+
"*("+Neumannterm_wt+
")."+contact_normal+
2626 =
"((Heaviside("+Pg_wt+
")*Coulomb_friction_coupled_projection("
2627 +Neumannterm+
", "+contact_normal+
", "+Vs+
", "+gap+
", "
2628 +dataname_friction_coeff+
",1/"+gamma+
"))+"
2629 +
"((1-Heaviside("+Pg_wt+
"))*(Coulomb_friction_coupled_projection("
2630 +Neumannterm_wt+
", "+contact_normal+
", "+Vs_wt+
", "+gap_wt+
", "
2631 +dataname_friction_coeff+
",1/"+gamma+
")*0.5+"
2632 "Coulomb_friction_coupled_projection(2*("
2633 +Neumannterm+
")-("+Neumannterm_wt+
"), "+contact_normal
2634 +
", 2*"+Vs+
"-"+Vs_wt+
", 2*"+gap+
"-"+gap_wt+
", "
2635 +dataname_friction_coeff+
",1/"+gamma+
")*0.5))).(";
2637 if (theta_ != scalar_type(0)) {
2638 std::string derivative_Neumann=workspace.extract_order1_term(varname_u);
2639 expr =
"-"+thetagamma+
"*("+Neumannterm+
").("+derivative_Neumann
2640 +
") + "+expr+thetagamma+
"*("+derivative_Neumann+
")";
2642 expr +=
"-Test_"+varname_u+
")";
2645 (md, mim, expr, region,
false,
false,
2646 "Nitsche contact with rigid obstacle");
region-tree for window/point search on a set of rectangles.
Generic assembly of vectors, matrices.
void push_vec(VEC &v)
Add a new output vector.
void push_mat(const MAT &m)
Add a new output matrix (fake const version..)
void assembly(const mesh_region ®ion=mesh_region::all_convexes())
do the assembly on the specified region (boundary or set of convexes)
void push_nonlinear_term(pnonlinear_elem_term net)
Add a new non-linear term.
void push_mi(const mesh_im &im_)
Add a new mesh_im.
void push_mf(const mesh_fem &mf_)
Add a new mesh_fem.
Describe a finite element method linked to a mesh.
Describe an integration method linked to a mesh.
`‘Model’' variables store the variables, the data and the description of a model.
size_type add_brick(pbrick pbr, const varnamelist &varnames, const varnamelist &datanames, const termlist &terms, const mimlist &mims, size_type region)
Add a brick to the model.
FEM which projects a mesh_fem on a different mesh.
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.
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)
*/
computation of the condition number of dense matrices.
std::shared_ptr< const getfem::virtual_fem > pfem
type of pointer on a fem description
size_t size_type
used as the common size type in the library
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.
size_type add_integral_contact_between_nonmatching_meshes_brick(model &md, const mesh_im &mim, const std::string &varname_u1, const std::string &varname_u2, const std::string &multname_n, const std::string &dataname_r, size_type region1, size_type region2, int option=1)
Add a frictionless contact condition between nonmatching meshes to the model.
size_type APIDECL add_nonlinear_term(model &md, const mesh_im &mim, const std::string &expr, size_type region=size_type(-1), bool is_sym=false, bool is_coercive=false, const std::string &brickname="")
Add a nonlinear term given by the weak form language expression expr which will be assembled in regio...
size_type add_integral_contact_with_rigid_obstacle_brick(model &md, const mesh_im &mim, const std::string &varname_u, const std::string &multname_n, const std::string &dataname_obs, const std::string &dataname_r, size_type region, int option=1)
Add a frictionless contact condition with a rigid obstacle to the model, which is defined in an integ...
size_type add_penalized_contact_with_rigid_obstacle_brick(model &md, const mesh_im &mim, const std::string &varname_u, const std::string &dataname_obs, const std::string &dataname_r, size_type region, int option=1, const std::string &dataname_lambda_n="")
Add a penalized contact frictionless condition with a rigid obstacle to the model.
void asm_level_set_normal_source_term(VEC &R, const mesh_im &mim, const getfem::mesh_fem &mf_u, const getfem::mesh_fem &mf_obs, const VEC &obs, const getfem::mesh_fem &mf_lambda, const VEC &lambda, const mesh_region &rg)
Specific assembly procedure for the use of an Uzawa algorithm to solve contact problems.
void del_projected_fem(pfem pf)
release a projected fem
size_type add_penalized_contact_between_nonmatching_meshes_brick(model &md, const mesh_im &mim, const std::string &varname_u1, const std::string &varname_u2, const std::string &dataname_r, size_type region1, size_type region2, int option=1, const std::string &dataname_lambda_n="")
Add a penalized contact frictionless condition between nonmatching meshes to the model.
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
pfem new_projected_fem(const mesh_fem &mf_source, const mesh_im &mim_target, size_type rg_source_=size_type(-1), size_type rg_target_=size_type(-1), dal::bit_vector blocked_dofs=dal::bit_vector(), bool store_val=true)
create a new projected FEM.
size_type add_Nitsche_contact_with_rigid_obstacle_brick(model &md, const mesh_im &mim, const std::string &varname_u, const std::string &Neumannterm, const std::string &expr_obs, const std::string &dataname_gamma0, scalar_type theta_, std::string dataexpr_friction_coeff, const std::string &dataname_alpha, const std::string &dataname_wt, size_type region)
Adds a contact condition with or without Coulomb friction on the variable varname_u and the mesh boun...