32 template <
typename T>
inline static T Heav(T a)
33 {
return (a < T(0)) ? T(0) : T(1); }
42 void contact_nonlinear_term::adjust_tensor_size(
void) {
43 sizes_.resize(1); sizes_[0] = 1;
46 case RHS_U_V1:
case RHS_U_V2:
case RHS_U_V4:
47 case RHS_U_V5:
case RHS_U_FRICT_V6:
case RHS_U_FRICT_V7:
48 case RHS_U_FRICT_V8:
case RHS_U_FRICT_V1:
49 case RHS_U_FRICT_V4:
case RHS_U_FRICT_V5:
50 case RHS_L_FRICT_V1:
case RHS_L_FRICT_V2:
case RHS_L_FRICT_V4:
51 case K_UL_V1:
case K_UL_V2:
case K_UL_V3:
52 case UZAWA_PROJ_FRICT:
case UZAWA_PROJ_FRICT_SAXCE:
55 case K_UU_V1:
case K_UU_V2:
56 case K_UL_FRICT_V1:
case K_UL_FRICT_V2:
case K_UL_FRICT_V3:
57 case K_UL_FRICT_V4:
case K_UL_FRICT_V5:
58 case K_UL_FRICT_V7:
case K_UL_FRICT_V8:
59 case K_LL_FRICT_V1:
case K_LL_FRICT_V2:
case K_LL_FRICT_V4:
60 case K_UU_FRICT_V1:
case K_UU_FRICT_V2:
61 case K_UU_FRICT_V3:
case K_UU_FRICT_V4:
case K_UU_FRICT_V5:
62 sizes_.resize(2); sizes_[0] = sizes_[1] = N;
break;
66 lnt.resize(N); lt.resize(N); zt.resize(N); no.resize(N);
67 aux1.resize(1); auxN.resize(N); V.resize(N);
71 void contact_nonlinear_term::friction_law
72 (scalar_type p, scalar_type &tau) {
73 tau = (p > scalar_type(0)) ? tau_adh + f_coeff * p : scalar_type(0);
74 if (tau > tresca_lim) tau = tresca_lim;
77 void contact_nonlinear_term::friction_law
78 (scalar_type p, scalar_type &tau, scalar_type &tau_grad) {
79 if (p <= scalar_type(0)) {
81 tau_grad = scalar_type(0);
84 tau = tau_adh + f_coeff * p;
85 if (tau > tresca_lim) {
87 tau_grad = scalar_type(0);
94 void contact_nonlinear_term::compute
95 (fem_interpolation_context &, bgeot::base_tensor &t) {
97 t.adjust_sizes(sizes_);
98 scalar_type e, augm_ln, rho, rho_grad;
107 t[0] = (ln+gmm::neg(ln-r*(un - g)))/r;
break;
109 t[0] = (un-g) + gmm::pos(ln)/r;
break;
112 t[0] = (Heav(r*(un-g)-ln) - scalar_type(1))/r;
break;
114 t[0] = -Heav(ln)/r;
break;
117 t[0] = -gmm::neg(ln - r*(un - g));
break;
122 t[0] = Heav(un-g - ln);
break;
123 case CONTACT_PRESSURE:
129 for (i=0; i<N; ++i) t[i] = ln * no[i];
132 e = -gmm::neg(ln-r*(un - g));
133 for (i=0; i<N; ++i) t[i] = e * no[i];
137 for (i=0; i<N; ++i) t[i] = e * no[i];
140 e = - gmm::pos(un-g) * r;
141 for (i=0; i<N; ++i) t[i] = e * no[i];
144 e = gmm::neg(ln-r*(un - g));
145 friction_law(e, rho);
146 auxN = lt - zt; ball_projection(auxN, rho);
147 for (i=0; i<N; ++i) t[i] = auxN[i] - e*no[i];
150 e = gmm::neg(-r*(un - g));
151 friction_law(e, rho);
152 auxN = - zt; ball_projection(auxN, rho);
153 for (i=0; i<N; ++i) t[i] = auxN[i] - e*no[i];
156 auxN = lnt - (r*(un-g) - f_coeff * gmm::vect_norm2(zt)) * no - zt;
157 De_Saxce_projection(auxN, no, f_coeff);
158 for (i=0; i<N; ++i) t[i] = auxN[i];
161 for (i=0; i<N; ++i) t[i] = lnt[i];
167 friction_law(e, rho);
168 auxN = lt; ball_projection(auxN, rho);
171 for (i=0; i<N; ++i) t[i] = auxN[i] - e*no[i];
174 auxN = lnt; De_Saxce_projection(auxN, no, f_coeff);
175 for (i=0; i<N; ++i) t[i] = auxN[i];
178 e = gmm::neg(ln-r*(un-g));
179 friction_law(e, rho);
180 auxN = zt - lt; ball_projection(auxN, rho); auxN += lt;
181 for (i=0; i<N; ++i) t[i] = ((e+ln)*no[i] + auxN[i])/ r;
184 e = r*(un-g) + gmm::pos(ln);
185 friction_law(gmm::neg(ln), rho);
186 auxN = lt; ball_projection(auxN, rho);
187 for (i=0; i<N; ++i) t[i] = (no[i]*e + zt[i] + lt[i] - auxN[i])/r;
191 De_Saxce_projection(auxN, no, f_coeff);
192 auxN -= lnt + (r*(un-g) - f_coeff * gmm::vect_norm2(zt)) * no + zt;
193 for (i=0; i<N; ++i) t[i] = -auxN[i]/r;
196 for (i=0; i<N; ++i) t[i] = -no[i];
200 for (i=0; i<N; ++i) t[i] = e*no[i];
203 e = -Heav(r*(un-g)-ln);
204 for (i=0; i<N; ++i) t[i] = e*no[i];
206 case UZAWA_PROJ_FRICT:
207 e = gmm::neg(ln - r*(un - g));
208 friction_law(e, rho);
209 auxN = lt - zt; ball_projection(auxN, rho);
210 for (i=0; i<N; ++i) t[i] = auxN[i] - e*no[i];
212 case UZAWA_PROJ_FRICT_SAXCE:
213 auxN = lnt - (r*(un-g) - f_coeff * gmm::vect_norm2(zt)) * no - zt;
214 De_Saxce_projection(auxN, no, f_coeff);
215 for (i=0; i<N; ++i) t[i] = auxN[i];
221 e = r * Heav(un - g);
222 for (i=0; i<N; ++i)
for (j=0; j<N; ++j) t[i*N+j] = e * no[i] * no[j];
225 e = r * Heav(r*(un - g)-ln);
226 for (i=0; i<N; ++i)
for (j=0; j<N; ++j) t[i*N+j] = e * no[i] * no[j];
230 for (i=0; i<N; ++i)
for (j=0; j<N; ++j)
231 t[i*N+j] = ((i == j) ? -scalar_type(1) : scalar_type(0));
234 friction_law(gmm::neg(ln), rho, rho_grad);
235 ball_projection_grad(lt, rho, GP);
236 e = gmm::vect_sp(GP, no, no) - Heav(-ln);
237 coulomb = (rho_grad > 0) &&
bool(Heav(-ln));
238 if (coulomb) ball_projection_grad_r(lt, rho, V);
239 for (i=0; i<N; ++i)
for (j=0; j<N; ++j)
240 t[i*N+j] = no[i]*no[j]*e - GP(i,j) +
241 (coulomb ? rho_grad*no[i]*V[j] : scalar_type(0));
244 augm_ln = ln - r*(un-g);
245 friction_law(gmm::neg(augm_ln), rho, rho_grad);
247 ball_projection_grad(auxN, rho, GP);
248 e = gmm::vect_sp(GP, no, no) - Heav(-augm_ln);
249 coulomb = (rho_grad > 0) &&
bool(Heav(-augm_ln));
250 if (coulomb) ball_projection_grad_r(auxN, rho, V);
251 for (i=0; i<N; ++i)
for (j=0; j<N; ++j)
252 t[i*N+j] = no[i]*no[j]*e - GP(i,j) +
253 (coulomb ? rho_grad*no[i]*V[j] : scalar_type(0));
256 augm_ln = ln - r*(un-g);
257 friction_law(gmm::neg(augm_ln), rho, rho_grad);
259 ball_projection_grad(auxN, rho, GP); gmm::scale(GP, alpha);
260 e = gmm::vect_sp(GP, no, no) - Heav(-augm_ln);
261 coulomb = (rho_grad > 0) &&
bool(Heav(-augm_ln));
262 if (coulomb) ball_projection_grad_r(auxN, rho, V);
263 for (i=0; i<N; ++i)
for (j=0; j<N; ++j)
264 t[i*N+j] = no[i]*no[j]*e - GP(i,j) +
265 (coulomb ? rho_grad*V[i]*no[j] : scalar_type(0));
268 e =
alpha - scalar_type(1);
269 for (i=0; i<N; ++i)
for (j=0; j<N; ++j)
270 t[i*N+j] = no[i]*no[j]*e - ((i == j) ? alpha : scalar_type(0));
273 De_Saxce_projection_grad(lnt, no, f_coeff, GP);
274 for (i=0; i<N; ++i)
for (j=0; j<N; ++j) t[i*N+j] = -GP(j,i);
279 gmm::copy(gmm::identity_matrix(), GP); gmm::scale(GP, alpha);
280 gmm::rank_one_update(GP, gmm::scaled(no, scalar_type(1)-alpha), no);
281 if (nzt != scalar_type(0))
282 gmm::rank_one_update(GP, gmm::scaled(no, -f_coeff*alpha/nzt), zt);
283 for (i=0; i<N; ++i)
for (j=0; j<N; ++j) t[i*N+j] = - GP(i,j);
287 augm_ln = ln - r*(un-g);
288 friction_law(gmm::neg(augm_ln), rho, rho_grad);
290 ball_projection_grad(auxN, rho, GP);
291 e = Heav(-augm_ln) - gmm::vect_sp(GP, no, no);
292 coulomb = (rho_grad > 0) &&
bool(Heav(-augm_ln));
293 if (coulomb) ball_projection_grad_r(auxN, rho, V);
294 for (i=0; i<N; ++i)
for (j=0; j<N; ++j)
295 t[i*N+j] = (no[i]*no[j]*e + GP(i,j)
296 - ((i == j) ? scalar_type(1) : scalar_type(0))
297 - (coulomb ? rho_grad*no[i]*V[j] : scalar_type(0))) / r;
300 friction_law(gmm::neg(ln), rho, rho_grad);
301 ball_projection_grad(lt, rho, GP);
302 e = Heav(-ln) - gmm::vect_sp(GP, no, no);
303 coulomb = (rho_grad > 0) &&
bool(Heav(-ln));
304 if (coulomb) ball_projection_grad_r(lt, rho, V);
305 for (i=0; i<N; ++i)
for (j=0; j<N; ++j)
306 t[i*N+j] = (no[i]*no[j]*e + GP(i,j)
307 - ((i == j) ? scalar_type(1) : scalar_type(0))
308 - (coulomb ? rho_grad*no[i]*V[j] : scalar_type(0))) / r;
311 De_Saxce_projection_grad(lnt, no, f_coeff, GP);
312 for (i=0; i<N; ++i)
for (j=0; j<N; ++j)
313 t[i*N+j] = (GP(i,j) - ((i == j) ? scalar_type(1) : scalar_type(0)))/r;
316 e = r * Heav(r*(un-g)-ln);
317 for (i=0; i<N; ++i)
for (j=0; j<N; ++j) t[i*N+j] = no[i]*no[j]*e;
320 friction_law(-ln, rho, rho_grad);
322 ball_projection_grad(auxN, rho, GP); gmm::scale(GP, alpha);
323 e = Heav(r*(un-g)-ln) - gmm::vect_sp(GP, no, no);
324 for (i=0; i<N; ++i)
for (j=0; j<N; ++j)
325 t[i*N+j] = r*(no[i]*no[j]*e + GP(i,j));
329 augm_ln = (option == K_UU_FRICT_V3) ? ln - r*(un-g) : - r*(un-g);
330 auxN = (option == K_UU_FRICT_V3) ? lt - zt : -zt;
331 friction_law(gmm::neg(augm_ln), rho, rho_grad);
332 ball_projection_grad(auxN, rho, GP); gmm::scale(GP, alpha);
333 e = Heav(-augm_ln) - gmm::vect_sp(GP, no, no);
334 coulomb = (rho_grad > 0) &&
bool(Heav(-augm_ln));
335 if (coulomb) ball_projection_grad_r(auxN, rho, V);
336 for (i=0; i<N; ++i)
for (j=0; j<N; ++j)
337 t[i*N+j] = r*(no[i]*no[j]*e + GP(i,j)
338 - (coulomb ? rho_grad*no[i]*V[j] : scalar_type(0)));
343 auxN = lnt - (r*(un-g) - f_coeff * nzt) * no - zt;
344 base_matrix A(N, N), B(N, N);
345 De_Saxce_projection_grad(auxN, no, f_coeff, A);
346 gmm::copy(gmm::identity_matrix(), B); gmm::scale(B, alpha);
347 gmm::rank_one_update(B, gmm::scaled(no, scalar_type(1)-alpha), no);
348 if (nzt != scalar_type(0))
349 gmm::rank_one_update(B, gmm::scaled(no, -f_coeff*alpha/nzt), zt);
351 for (i=0; i<N; ++i)
for (j=0; j<N; ++j) t[i*N+j] = r*GP(j,i);
354 default : GMM_ASSERT1(
false,
"Invalid option");
365 void contact_rigid_obstacle_nonlinear_term::prepare
366 (fem_interpolation_context& ctx,
size_type nb) {
372 ctx.pf()->interpolation(ctx, coeff, V, N);
373 un = gmm::vect_sp(V, no);
375 if (gmm::vect_size(WT) == gmm::vect_size(U)) {
377 ctx.pf()->interpolation(ctx, coeff, auxN, N);
378 auxN -= gmm::vect_sp(auxN, no) * no;
379 if (gmm::vect_size(VT) == gmm::vect_size(U)) {
381 ctx.pf()->interpolation(ctx, coeff, vt, N);
382 vt -= gmm::vect_sp(vt, no) * no;
384 zt = (((V - un * no) - auxN) *
alpha + vt * (1 - gamma)) * r;
387 zt = ((V - un * no) - auxN) * (r *
alpha);
391 zt = (V - un * no) * (r * alpha);
399 ctx.pf()->interpolation_grad(ctx, coeff, grad, 1);
400 gmm::copy(gmm::mat_row(grad, 0), no);
402 ctx.pf()->interpolation(ctx, coeff, aux1, 1);
405 if (!contact_only && pmf_lambda) {
406 ln = gmm::vect_sp(lnt, no);
416 ctx.pf()->interpolation(ctx, coeff, aux1, 1);
419 ctx.pf()->interpolation(ctx, coeff, lnt, N);
427 GMM_ASSERT1(!contact_only,
"Invalid friction option");
430 ctx.pf()->interpolation(ctx, coeff, aux1, 1);
432 if (gmm::vect_size(tau_adhesion)) {
434 ctx.pf()->interpolation(ctx, coeff, aux1, 1);
436 if (gmm::vect_size(tresca_limit)) {
438 ctx.pf()->interpolation(ctx, coeff, aux1, 1);
439 tresca_lim = aux1[0];
445 default : GMM_ASSERT1(
false,
"Invalid option");
457 void contact_nonmatching_meshes_nonlinear_term::prepare
458 (fem_interpolation_context& ctx,
size_type nb) {
474 ctx.pf()->interpolation(ctx, coeff, V, N);
476 scalar_type un1 = gmm::vect_sp(V, no);
478 if (gmm::vect_size(WT1) == gmm::vect_size(U1)) {
480 ctx.pf()->interpolation(ctx, coeff, auxN, N);
481 auxN -= gmm::vect_sp(auxN, no) * no;
482 zt = ((V - un1 * no) - auxN) * (r *
alpha) - zt;
484 zt = (V - un1 * no) * (r * alpha) - zt;
495 const projected_fem &pfe =
dynamic_cast<const projected_fem&
>(*ctx.pf());
496 pfe.projection_data(ctx, no, g);
497 gmm::scale(no, scalar_type(-1));
500 if (!contact_only && pmf_lambda) {
501 ln = gmm::vect_sp(lnt, no);
506 ctx.pf()->interpolation(ctx, coeff, V, N);
507 un = gmm::vect_sp(V, no);
509 if (gmm::vect_size(WT2) == gmm::vect_size(U2)) {
511 ctx.pf()->interpolation(ctx, coeff, auxN, N);
512 auxN -= gmm::vect_sp(auxN, no) * no;
513 zt = ((V - un * no) - auxN) * (r *
alpha);
515 zt = (V - un * no) * (r * alpha);
524 ctx.pf()->interpolation(ctx, coeff, aux1, 1);
527 ctx.pf()->interpolation(ctx, coeff, lnt, N);
535 GMM_ASSERT1(!contact_only,
"Invalid friction option");
538 ctx.pf()->interpolation(ctx, coeff, aux1, 1);
540 if (gmm::vect_size(tau_adhesion)) {
542 ctx.pf()->interpolation(ctx, coeff, aux1, 1);
544 if (gmm::vect_size(tresca_limit)) {
546 ctx.pf()->interpolation(ctx, coeff, aux1, 1);
547 tresca_lim = aux1[0];
553 default : GMM_ASSERT1(
false,
"Invalid option");
565 template<
typename MAT,
typename VECT1>
566 void asm_Alart_Curnier_contact_rigid_obstacle_tangent_matrix
567 (MAT &Kul, MAT &Klu, MAT &Kll, MAT &Kuu,
572 scalar_type r,
const mesh_region &rg,
int option = 1) {
574 size_type subterm1 = (option == 3) ? K_UL_V2 : K_UL_V1;
575 size_type subterm2 = (option == 3) ? K_UL_V1 : K_UL_V3;
576 size_type subterm3 = (option == 3) ? K_LL_V2 : K_LL_V1;
577 size_type subterm4 = (option == 2) ? K_UU_V2 : K_UU_V1;
579 contact_rigid_obstacle_nonlinear_term
580 nterm1(subterm1, r, mf_u, U, mf_obs, obs, &mf_lambda, &lambda),
581 nterm2(subterm2, r, mf_u, U, mf_obs, obs, &mf_lambda, &lambda),
582 nterm3(subterm3, r, mf_u, U, mf_obs, obs, &mf_lambda, &lambda),
583 nterm4(subterm4, r, mf_u, U, mf_obs, obs, &mf_lambda, &lambda);
589 (
"M$1(#1,#3)+=comp(NonLin$1(#1,#1,#2,#3).vBase(#1).Base(#3))(i,:,i,:); "
590 "M$2(#3,#1)+=comp(NonLin$2(#1,#1,#2,#3).Base(#3).vBase(#1))(i,:,:,i); "
591 "M$3(#3,#3)+=comp(NonLin$3(#1,#1,#2,#3).Base(#3).Base(#3))(i,:,:)");
595 (
"M$1(#1,#3)+=comp(NonLin$2(#1,#1,#2,#3).vBase(#1).Base(#3))(i,:,i,:); "
596 "M$3(#3,#3)+=comp(NonLin$3(#1,#1,#2,#3).Base(#3).Base(#3))(i,:,:);"
597 "M$4(#1,#1)+=comp(NonLin$4(#1,#1,#2,#3).vBase(#1).vBase(#1))(i,j,:,i,:,j)");
615 template<
typename MAT,
typename VECT1>
616 void asm_Alart_Curnier_contact_rigid_obstacle_tangent_matrix
617 (MAT &Kul, MAT &Klu, MAT &Kll, MAT &Kuu,
623 scalar_type
alpha,
const VECT1 *WT,
624 scalar_type gamma,
const VECT1 *VT,
625 const mesh_region &rg,
int option = 1) {
629 case 1 : subterm1 = K_UL_FRICT_V1; subterm2 = K_UL_FRICT_V4;
630 subterm3 = K_LL_FRICT_V1;
break;
631 case 2 : subterm1 = K_UL_FRICT_V3; subterm2 = K_UL_FRICT_V4;
632 subterm3 = K_LL_FRICT_V1;
break;
633 case 3 : subterm1 = K_UL_FRICT_V2; subterm2 = K_UL_FRICT_V5;
634 subterm3 = K_LL_FRICT_V2;
break;
635 case 4 : subterm1 = K_UL_FRICT_V7; subterm2 = K_UL_FRICT_V8;
636 subterm3 = K_LL_FRICT_V4;
break;
637 default : GMM_ASSERT1(
false,
"Incorrect option");
642 contact_rigid_obstacle_nonlinear_term
643 nterm1(subterm1, r, mf_u, U, mf_obs, obs, &mf_lambda, &lambda,
644 pmf_coeff, f_coeffs, alpha, WT, gamma, VT),
645 nterm2(subterm2, r, mf_u, U, mf_obs, obs, &mf_lambda, &lambda,
646 pmf_coeff, f_coeffs, alpha, WT, gamma, VT),
647 nterm3(subterm3, r, mf_u, U, mf_obs, obs, &mf_lambda, &lambda,
648 pmf_coeff, f_coeffs, alpha, WT, gamma, VT),
649 nterm4(subterm4, r, mf_u, U, mf_obs, obs, &mf_lambda, &lambda,
650 pmf_coeff, f_coeffs, alpha, WT, gamma, VT);
652 const std::string aux_fems = pmf_coeff ?
"#1,#2,#3,#4" :
"#1,#2,#3";
656 case 1:
case 3:
case 4:
658 (
"M$1(#1,#3)+=comp(NonLin$1(#1," + aux_fems +
").vBase(#1).vBase(#3))(i,j,:,i,:,j); "
659 "M$2(#3,#1)+=comp(NonLin$2(#1," + aux_fems +
").vBase(#3).vBase(#1))(i,j,:,j,:,i); "
660 "M$3(#3,#3)+=comp(NonLin$3(#1," + aux_fems +
").vBase(#3).vBase(#3))(i,j,:,i,:,j)");
664 (
"M$1(#1,#3)+=comp(NonLin$1(#1," + aux_fems +
").vBase(#1).vBase(#3))(i,j,:,i,:,j); "
665 "M$2(#3,#1)+=comp(NonLin$2(#1," + aux_fems +
").vBase(#3).vBase(#1))(i,j,:,j,:,i); "
666 "M$3(#3,#3)+=comp(NonLin$3(#1," + aux_fems +
").vBase(#3).vBase(#3))(i,j,:,i,:,j);"
667 "M$4(#1,#1)+=comp(NonLin$4(#1," + aux_fems +
").vBase(#1).vBase(#1))(i,j,:,i,:,j)");
687 template<
typename VECT1>
688 void asm_Alart_Curnier_contact_rigid_obstacle_rhs
689 (VECT1 &Ru, VECT1 &Rl,
694 scalar_type r,
const mesh_region &rg,
int option = 1) {
698 case 1 : subterm1 = RHS_U_V1;
break;
699 case 2 : subterm1 = RHS_U_V2;
break;
700 case 3 : subterm1 = RHS_U_V4;
break;
701 default : GMM_ASSERT1(
false,
"Incorrect option");
703 size_type subterm2 = (option == 3) ? RHS_L_V2 : RHS_L_V1;
705 contact_rigid_obstacle_nonlinear_term
706 nterm1(subterm1, r, mf_u, U, mf_obs, obs, &mf_lambda, &lambda),
707 nterm2(subterm2, r, mf_u, U, mf_obs, obs, &mf_lambda, &lambda);
710 assem.set(
"V$1(#1)+=comp(NonLin$1(#1,#1,#2,#3).vBase(#1))(i,:,i); "
711 "V$2(#3)+=comp(NonLin$2(#1,#1,#2,#3).Base(#3))(i,:)");
724 template<
typename VECT1>
725 void asm_Alart_Curnier_contact_rigid_obstacle_rhs
726 (VECT1 &Ru, VECT1 &Rl,
732 scalar_type
alpha,
const VECT1 *WT,
733 scalar_type gamma,
const VECT1 *VT,
734 const mesh_region &rg,
int option = 1) {
738 case 1 : subterm1 = RHS_U_FRICT_V1; subterm2 = RHS_L_FRICT_V1;
break;
739 case 2 : subterm1 = RHS_U_FRICT_V6; subterm2 = RHS_L_FRICT_V1;
break;
740 case 3 : subterm1 = RHS_U_FRICT_V4; subterm2 = RHS_L_FRICT_V2;
break;
741 case 4 : subterm1 = RHS_U_FRICT_V5; subterm2 = RHS_L_FRICT_V4;
break;
742 default : GMM_ASSERT1(
false,
"Incorrect option");
745 contact_rigid_obstacle_nonlinear_term
746 nterm1(subterm1, r, mf_u, U, mf_obs, obs, &mf_lambda, &lambda,
747 pmf_coeff, f_coeffs, alpha, WT, gamma, VT),
748 nterm2(subterm2, r, mf_u, U, mf_obs, obs, &mf_lambda, &lambda,
749 pmf_coeff, f_coeffs, alpha, WT, gamma, VT);
751 const std::string aux_fems = pmf_coeff ?
"#1,#2,#3,#4" :
"#1,#2,#3";
754 assem.set(
"V$1(#1)+=comp(NonLin$1(#1," + aux_fems +
").vBase(#1))(i,:,i); "
755 "V$2(#3)+=comp(NonLin$2(#1," + aux_fems +
").vBase(#3))(i,:,i)");
769 struct integral_contact_rigid_obstacle_brick :
public virtual_brick {
780 virtual void asm_real_tangent_terms(
const model &md,
size_type ,
781 const model::varnamelist &vl,
782 const model::varnamelist &dl,
783 const model::mimlist &mims,
784 model::real_matlist &matl,
785 model::real_veclist &vecl,
786 model::real_veclist &,
788 build_version version)
const {
789 GMM_ASSERT1(mims.size() == 1,
790 "Integral contact with rigid obstacle bricks need a single mesh_im");
791 GMM_ASSERT1(vl.size() == 2,
792 "Integral contact with rigid obstacle bricks need two variables");
793 GMM_ASSERT1(dl.size() >= 2 && dl.size() <= 7,
794 "Wrong number of data for integral contact with rigid obstacle "
795 <<
"brick, " << dl.size() <<
" should be between 2 and 7.");
796 GMM_ASSERT1(matl.size() ==
size_type(3 + (option == 2 && !contact_only)),
797 "Wrong number of terms for "
798 "integral contact with rigid obstacle brick");
809 const model_real_plain_vector &u = md.real_variable(vl[0]);
810 const mesh_fem &mf_u = md.mesh_fem_of_variable(vl[0]);
811 const model_real_plain_vector &lambda = md.real_variable(vl[1]);
812 const mesh_fem &mf_lambda = md.mesh_fem_of_variable(vl[1]);
813 GMM_ASSERT1(mf_lambda.get_qdim() == (contact_only ? 1 : mf_u.get_qdim()),
814 "The contact stress has not the right dimension");
815 const model_real_plain_vector &obstacle = md.real_variable(dl[0]);
816 const mesh_fem &mf_obstacle = md.mesh_fem_of_variable(dl[0]);
817 size_type sl = gmm::vect_size(obstacle) * mf_obstacle.get_qdim()
818 / mf_obstacle.nb_dof();
819 GMM_ASSERT1(sl == 1,
"the data corresponding to the obstacle has not "
822 const model_real_plain_vector &vr = md.real_variable(dl[1]);
823 GMM_ASSERT1(gmm::vect_size(vr) == 1,
"Parameter r should be a scalar");
824 const mesh_im &mim = *mims[0];
826 const model_real_plain_vector dummy_vec(0);
827 const model_real_plain_vector &friction_coeffs = contact_only
828 ? dummy_vec : md.real_variable(dl[2]);
829 const mesh_fem *pmf_coeff = contact_only ? 0 : md.pmesh_fem_of_variable(dl[2]);
830 sl = gmm::vect_size(friction_coeffs);
831 if (pmf_coeff) { sl *= pmf_coeff->get_qdim(); sl /= pmf_coeff->nb_dof(); }
832 GMM_ASSERT1(sl == 1 || sl == 2 || sl == 3 || contact_only,
833 "the data corresponding to the friction coefficient "
834 "has not the right format");
836 scalar_type
alpha = 1;
837 if (!contact_only && dl.size() >= 4) {
838 alpha = md.real_variable(dl[3])[0];
839 GMM_ASSERT1(gmm::vect_size(md.real_variable(dl[3])) == 1,
840 "Parameter alpha should be a scalar");
843 const model_real_plain_vector *WT = 0;
844 if (!contact_only && dl.size() >= 5) {
845 if (dl[4].compare(vl[0]) != 0)
846 WT = &(md.real_variable(dl[4]));
847 else if (md.n_iter_of_variable(vl[0]) > 1)
848 WT = &(md.real_variable(vl[0],1));
851 scalar_type gamma = 1;
852 if (!contact_only && dl.size() >= 6) {
853 GMM_ASSERT1(gmm::vect_size(md.real_variable(dl[5])) == 1,
854 "Parameter gamma should be a scalar");
855 gamma = md.real_variable(dl[5])[0];
858 const model_real_plain_vector *VT
859 = (!contact_only && dl.size()>=7) ? &(md.real_variable(dl[6])) : 0;
861 mesh_region rg(region);
862 mf_u.linked_mesh().intersect_with_mpi_region(rg);
864 if (version & model::BUILD_MATRIX) {
865 GMM_TRACE2(
"Integral contact with rigid obstacle friction tangent term");
868 size_type fourthmat = (matl.size() >= 4) ? 3 : 1;
870 asm_Alart_Curnier_contact_rigid_obstacle_tangent_matrix
871 (matl[0], matl[1], matl[2], matl[fourthmat], mim,
872 mf_u, u, mf_obstacle, obstacle, mf_lambda, lambda, vr[0],
875 asm_Alart_Curnier_contact_rigid_obstacle_tangent_matrix
876 (matl[0], matl[1], matl[2], matl[fourthmat], mim,
877 mf_u, u, mf_obstacle, obstacle, mf_lambda, lambda,
878 pmf_coeff, &friction_coeffs, vr[0], alpha, WT, gamma, VT,
882 if (version & model::BUILD_RHS) {
887 asm_Alart_Curnier_contact_rigid_obstacle_rhs
888 (vecl[0], vecl[2], mim,
889 mf_u, u, mf_obstacle, obstacle, mf_lambda, lambda, vr[0],
892 asm_Alart_Curnier_contact_rigid_obstacle_rhs
893 (vecl[0], vecl[2], mim,
894 mf_u, u, mf_obstacle, obstacle, mf_lambda, lambda,
895 pmf_coeff, &friction_coeffs, vr[0], alpha, WT, gamma, VT,
901 integral_contact_rigid_obstacle_brick(
bool contact_only_,
int option_) {
903 contact_only = contact_only_;
904 set_flags(contact_only
905 ?
"Integral contact with rigid obstacle brick"
906 :
"Integral contact and friction with rigid obstacle brick",
908 (option==2) && contact_only ,
923 const std::string &multname_n,
const std::string &dataname_obs,
924 const std::string &dataname_r,
size_type region,
int option) {
927 = std::make_shared<integral_contact_rigid_obstacle_brick>(
true, option);
933 tl.push_back(model::term_description(varname_u, multname_n,
false));
934 tl.push_back(model::term_description(multname_n, varname_u,
false));
935 tl.push_back(model::term_description(multname_n, multname_n,
true));
938 tl.push_back(model::term_description(varname_u, multname_n,
true));
939 tl.push_back(model::term_description(varname_u, varname_u,
true));
940 tl.push_back(model::term_description(multname_n, multname_n,
true));
942 default :GMM_ASSERT1(
false,
943 "Incorrect option for integral contact brick");
946 model::varnamelist dl(1, dataname_obs);
947 dl.push_back(dataname_r);
949 model::varnamelist vl(1, varname_u);
950 vl.push_back(multname_n);
952 return md.
add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region);
963 const std::string &multname,
const std::string &dataname_obs,
964 const std::string &dataname_r,
const std::string &dataname_friction_coeffs,
966 const std::string &dataname_alpha,
const std::string &dataname_wt,
967 const std::string &dataname_gamma,
const std::string &dataname_vt) {
969 pbrick pbr = std::make_shared<integral_contact_rigid_obstacle_brick>
975 case 1:
case 3:
case 4:
976 tl.push_back(model::term_description(varname_u, multname,
false));
977 tl.push_back(model::term_description(multname, varname_u,
false));
978 tl.push_back(model::term_description(multname, multname,
true));
981 tl.push_back(model::term_description(varname_u, multname,
false));
982 tl.push_back(model::term_description(multname, varname_u,
false));
983 tl.push_back(model::term_description(multname, multname,
true));
984 tl.push_back(model::term_description(varname_u, varname_u,
true));
986 default :GMM_ASSERT1(
false,
987 "Incorrect option for integral contact brick");
989 model::varnamelist dl(1, dataname_obs);
990 dl.push_back(dataname_r);
991 dl.push_back(dataname_friction_coeffs);
992 if (dataname_alpha.size()) {
993 dl.push_back(dataname_alpha);
994 if (dataname_wt.size()) {
995 dl.push_back(dataname_wt);
996 if (dataname_gamma.size()) {
997 dl.push_back(dataname_gamma);
998 if (dataname_vt.size()) dl.push_back(dataname_vt);
1003 model::varnamelist vl(1, varname_u);
1004 vl.push_back(multname);
1006 return md.
add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region);
1016 template<
typename MAT,
typename VECT1>
1017 void asm_penalized_contact_rigid_obstacle_tangent_matrix
1023 scalar_type r,
const mesh_region &rg,
int option = 1) {
1025 contact_rigid_obstacle_nonlinear_term
1026 nterm((option == 1) ? K_UU_V1 : K_UU_V2, r,
1027 mf_u, U, mf_obs, obs, pmf_lambda, lambda);
1029 const std::string aux_fems = pmf_lambda ?
"#1,#2,#3":
"#1,#2";
1031 assem.set(
"M(#1,#1)+=comp(NonLin(#1," + aux_fems +
").vBase(#1).vBase(#1))(i,j,:,i,:,j)");
1043 template<
typename VECT1>
1044 void asm_penalized_contact_rigid_obstacle_rhs
1050 scalar_type r,
const mesh_region &rg,
int option = 1) {
1052 contact_rigid_obstacle_nonlinear_term
1053 nterm((option == 1) ? RHS_U_V5 : RHS_U_V2, r,
1054 mf_u, U, mf_obs, obs, pmf_lambda, lambda);
1056 const std::string aux_fems = pmf_lambda ?
"#1,#2,#3":
"#1,#2";
1058 assem.set(
"V(#1)+=comp(NonLin$1(#1," + aux_fems +
").vBase(#1))(i,:,i); ");
1069 template<
typename MAT,
typename VECT1>
1070 void asm_penalized_contact_rigid_obstacle_tangent_matrix
1077 scalar_type
alpha,
const VECT1 *WT,
1078 const mesh_region &rg,
int option = 1) {
1082 case 1 : subterm = K_UU_FRICT_V4;
break;
1083 case 2 : subterm = K_UU_FRICT_V3;
break;
1084 case 3 : subterm = K_UU_FRICT_V5;
break;
1087 contact_rigid_obstacle_nonlinear_term
1088 nterm(subterm, r, mf_u, U, mf_obs, obs, pmf_lambda, lambda,
1089 pmf_coeff, f_coeffs, alpha, WT);
1091 const std::string aux_fems = pmf_coeff ?
"#1,#2,#3,#4"
1092 : (pmf_lambda ?
"#1,#2,#3":
"#1,#2");
1094 assem.set(
"M(#1,#1)+=comp(NonLin(#1," + aux_fems +
").vBase(#1).vBase(#1))(i,j,:,i,:,j)");
1113 template<
typename VECT1>
1114 void asm_penalized_contact_rigid_obstacle_rhs
1121 scalar_type
alpha,
const VECT1 *WT,
1122 const mesh_region &rg,
int option = 1) {
1126 case 1 : subterm = RHS_U_FRICT_V7;
break;
1127 case 2 : subterm = RHS_U_FRICT_V6;
break;
1128 case 3 : subterm = RHS_U_FRICT_V8;
break;
1131 contact_rigid_obstacle_nonlinear_term
1132 nterm(subterm, r, mf_u, U, mf_obs, obs, pmf_lambda, lambda,
1133 pmf_coeff, f_coeffs, alpha, WT);
1135 const std::string aux_fems = pmf_coeff ?
"#1,#2,#3,#4"
1136 : (pmf_lambda ?
"#1,#2,#3":
"#1,#2");
1138 assem.set(
"V(#1)+=comp(NonLin$1(#1," + aux_fems +
").vBase(#1))(i,:,i); ");
1157 struct penalized_contact_rigid_obstacle_brick :
public virtual_brick {
1162 virtual void asm_real_tangent_terms(
const model &md,
size_type ,
1163 const model::varnamelist &vl,
1164 const model::varnamelist &dl,
1165 const model::mimlist &mims,
1166 model::real_matlist &matl,
1167 model::real_veclist &vecl,
1168 model::real_veclist &,
1170 build_version version)
const {
1172 GMM_ASSERT1(mims.size() == 1,
1173 "Penalized contact with rigid obstacle bricks need a single mesh_im");
1174 const mesh_im &mim = *mims[0];
1177 GMM_ASSERT1(vl.size() == 1,
1178 "Penalized contact with rigid obstacle bricks need a single variable");
1179 const model_real_plain_vector &u = md.real_variable(vl[0]);
1180 const mesh_fem &mf_u = md.mesh_fem_of_variable(vl[0]);
1185 size_type nb_data_1 = ((option == 1) ? 2 : 3) + (contact_only ? 0 : 1);
1186 size_type nb_data_2 = nb_data_1 + (contact_only ? 0 : 2);
1187 GMM_ASSERT1(dl.size() >= nb_data_1 && dl.size() <= nb_data_2,
1188 "Wrong number of data for penalized contact with rigid obstacle "
1189 <<
"brick, " << dl.size() <<
" should be between "
1190 << nb_data_1 <<
" and " << nb_data_2 <<
".");
1193 const model_real_plain_vector &obs = md.real_variable(dl[nd]);
1194 const mesh_fem &mf_obs = md.mesh_fem_of_variable(dl[nd]);
1195 size_type sl = gmm::vect_size(obs) * mf_obs.get_qdim() / mf_obs.nb_dof();
1196 GMM_ASSERT1(sl == 1,
"the data corresponding to the obstacle has not "
1197 "the right format");
1200 const model_real_plain_vector &vr = md.real_variable(dl[nd]);
1201 GMM_ASSERT1(gmm::vect_size(vr) == 1,
"Parameter r should be a scalar");
1203 const model_real_plain_vector *lambda = 0;
1204 const mesh_fem *pmf_lambda = 0;
1207 lambda = &(md.real_variable(dl[nd]));
1208 pmf_lambda = md.pmesh_fem_of_variable(dl[nd]);
1209 sl = gmm::vect_size(*lambda) * pmf_lambda->get_qdim() / pmf_lambda->nb_dof();
1210 GMM_ASSERT1(sl == (contact_only ? 1 : N),
1211 "the data corresponding to the contact stress "
1212 "has not the right format");
1215 const model_real_plain_vector *f_coeffs = 0;
1216 const mesh_fem *pmf_coeff = 0;
1217 scalar_type
alpha = 1;
1218 const model_real_plain_vector *WT = 0;
1219 if (!contact_only) {
1221 f_coeffs = &(md.real_variable(dl[nd]));
1222 pmf_coeff = md.pmesh_fem_of_variable(dl[nd]);
1223 sl = gmm::vect_size(*f_coeffs);
1224 if (pmf_coeff) { sl *= pmf_coeff->get_qdim(); sl /= pmf_coeff->nb_dof(); }
1225 GMM_ASSERT1(sl == 1 || sl == 2 || sl == 3,
1226 "the data corresponding to the friction coefficient "
1227 "has not the right format");
1228 if (dl.size() > nd+1) {
1230 alpha = md.real_variable(dl[nd])[0];
1231 GMM_ASSERT1(gmm::vect_size(md.real_variable(dl[nd])) == 1,
1232 "Parameter alpha should be a scalar");
1235 if (dl.size() > nd+1) {
1237 if (dl[nd].compare(vl[0]) != 0)
1238 WT = &(md.real_variable(dl[nd]));
1239 else if (md.n_iter_of_variable(vl[0]) > 1)
1240 WT = &(md.real_variable(vl[0],1));
1244 GMM_ASSERT1(matl.size() == 1,
"Wrong number of terms for "
1245 "penalized contact with rigid obstacle brick");
1247 mesh_region rg(region);
1248 mf_u.linked_mesh().intersect_with_mpi_region(rg);
1250 if (version & model::BUILD_MATRIX) {
1251 GMM_TRACE2(
"Penalized contact with rigid obstacle tangent term");
1254 asm_penalized_contact_rigid_obstacle_tangent_matrix
1255 (matl[0], mim, mf_u, u, mf_obs, obs, pmf_lambda, lambda,
1258 asm_penalized_contact_rigid_obstacle_tangent_matrix
1259 (matl[0], mim, mf_u, u, mf_obs, obs, pmf_lambda, lambda,
1260 pmf_coeff, f_coeffs, vr[0], alpha, WT, rg, option);
1263 if (version & model::BUILD_RHS) {
1266 asm_penalized_contact_rigid_obstacle_rhs
1267 (vecl[0], mim, mf_u, u, mf_obs, obs, pmf_lambda, lambda,
1270 asm_penalized_contact_rigid_obstacle_rhs
1271 (vecl[0], mim, mf_u, u, mf_obs, obs, pmf_lambda, lambda,
1272 pmf_coeff, f_coeffs, vr[0], alpha, WT, rg, option);
1277 penalized_contact_rigid_obstacle_brick(
bool contact_only_,
int option_) {
1278 contact_only = contact_only_;
1280 set_flags(contact_only
1281 ?
"Integral penalized contact with rigid obstacle brick"
1282 :
"Integral penalized contact and friction with rigid obstacle brick",
1283 false , contact_only ,
1298 const std::string &dataname_obs,
const std::string &dataname_r,
1299 size_type region,
int option,
const std::string &dataname_n) {
1301 pbrick pbr = std::make_shared<penalized_contact_rigid_obstacle_brick>
1305 tl.push_back(model::term_description(varname_u, varname_u,
true));
1307 model::varnamelist dl(1, dataname_obs);
1308 dl.push_back(dataname_r);
1311 case 2: dl.push_back(dataname_n);
break;
1312 default: GMM_ASSERT1(
false,
"Penalized contact brick : invalid option");
1315 model::varnamelist vl(1, varname_u);
1317 return md.
add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region);
1327 const std::string &dataname_obs,
const std::string &dataname_r,
1328 const std::string &dataname_friction_coeffs,
1329 size_type region,
int option,
const std::string &dataname_lambda,
1330 const std::string &dataname_alpha,
const std::string &dataname_wt) {
1332 pbrick pbr = std::make_shared<penalized_contact_rigid_obstacle_brick>
1336 tl.push_back(model::term_description(varname_u, varname_u,
false));
1338 model::varnamelist dl(1, dataname_obs);
1339 dl.push_back(dataname_r);
1342 case 2:
case 3: dl.push_back(dataname_lambda);
break;
1343 default: GMM_ASSERT1(
false,
"Penalized contact brick : invalid option");
1345 dl.push_back(dataname_friction_coeffs);
1346 if (dataname_alpha.size() > 0) {
1347 dl.push_back(dataname_alpha);
1348 if (dataname_wt.size() > 0) dl.push_back(dataname_wt);
1351 model::varnamelist vl(1, varname_u);
1353 return md.
add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region);
1363 template<
typename MAT,
typename VEC>
1364 void asm_Alart_Curnier_contact_nonmatching_meshes_tangent_matrix
1365 (MAT &Ku1l, MAT &Klu1, MAT &Ku2l, MAT &Klu2, MAT &Kll,
1366 MAT &Ku1u1, MAT &Ku2u2, MAT &Ku1u2,
1371 scalar_type r,
const mesh_region &rg,
int option = 1) {
1373 size_type subterm1 = (option == 3) ? K_UL_V2 : K_UL_V1;
1374 size_type subterm2 = (option == 3) ? K_UL_V1 : K_UL_V3;
1375 size_type subterm3 = (option == 3) ? K_LL_V2 : K_LL_V1;
1376 size_type subterm4 = (option == 2) ? K_UU_V2 : K_UU_V1;
1378 contact_nonmatching_meshes_nonlinear_term
1379 nterm1(subterm1, r, mf_u1, U1, mf_u2, U2, &mf_lambda, &lambda),
1380 nterm2(subterm2, r, mf_u1, U1, mf_u2, U2, &mf_lambda, &lambda),
1381 nterm3(subterm3, r, mf_u1, U1, mf_u2, U2, &mf_lambda, &lambda),
1382 nterm4(subterm4, r, mf_u1, U1, mf_u2, U2, &mf_lambda, &lambda);
1388 (
"M$1(#1,#3)+=comp(NonLin$1(#1,#1,#2,#3).vBase(#1).Base(#3))(i,:,i,:); "
1389 "M$2(#3,#1)+=comp(NonLin$2(#1,#1,#2,#3).Base(#3).vBase(#1))(i,:,:,i); "
1390 "M$3(#2,#3)+=comp(NonLin$1(#1,#1,#2,#3).vBase(#2).Base(#3))(i,:,i,:); "
1391 "M$4(#3,#2)+=comp(NonLin$2(#1,#1,#2,#3).Base(#3).vBase(#2))(i,:,:,i); "
1392 "M$5(#3,#3)+=comp(NonLin$3(#1,#1,#2,#3).Base(#3).Base(#3))(i,:,:)");
1396 (
"M$1(#1,#3)+=comp(NonLin$2(#1,#1,#2,#3).vBase(#1).Base(#3))(i,:,i,:); "
1397 "M$3(#2,#3)+=comp(NonLin$2(#1,#1,#2,#3).vBase(#2).Base(#3))(i,:,i,:); "
1398 "M$5(#3,#3)+=comp(NonLin$3(#1,#1,#2,#3).Base(#3).Base(#3))(i,:,:); "
1399 "M$6(#1,#1)+=comp(NonLin$4(#1,#1,#2,#3).vBase(#1).vBase(#1))(i,j,:,i,:,j); "
1400 "M$7(#2,#2)+=comp(NonLin$4(#1,#1,#2,#3).vBase(#2).vBase(#2))(i,j,:,i,:,j); "
1401 "M$8(#1,#2)+=comp(NonLin$4(#1,#1,#2,#3).vBase(#1).vBase(#2))(i,j,:,i,:,j)");
1422 gmm::scale(Ku2l, scalar_type(-1));
1424 gmm::scale(Klu2, scalar_type(-1));
1425 gmm::scale(Ku1u2, scalar_type(-1));
1428 template<
typename MAT,
typename VEC>
1429 void asm_Alart_Curnier_contact_nonmatching_meshes_tangent_matrix
1430 (MAT &Ku1l, MAT &Klu1, MAT &Ku2l, MAT &Klu2, MAT &Kll,
1431 MAT &Ku1u1, MAT &Ku2u2, MAT &Ku1u2, MAT &Ku2u1,
1437 scalar_type r, scalar_type
alpha,
1438 const VEC *WT1,
const VEC *WT2,
1439 const mesh_region &rg,
int option = 1) {
1444 subterm1 = K_UL_FRICT_V1; subterm2 = K_UL_FRICT_V4; subterm3 = K_LL_FRICT_V1;
1447 subterm1 = K_UL_FRICT_V3; subterm2 = K_UL_FRICT_V4; subterm3 = K_LL_FRICT_V1;
1450 subterm1 = K_UL_FRICT_V2; subterm2 = K_UL_FRICT_V5; subterm3 = K_LL_FRICT_V2;
1453 subterm1 = K_UL_FRICT_V7; subterm2 = K_UL_FRICT_V8; subterm3 = K_LL_FRICT_V4;
1455 default : GMM_ASSERT1(
false,
"Incorrect option");
1460 contact_nonmatching_meshes_nonlinear_term
1461 nterm1(subterm1, r, mf_u1, U1, mf_u2, U2, &mf_lambda, &lambda,
1462 pmf_coeff, f_coeffs, alpha, WT1, WT2),
1463 nterm2(subterm2, r, mf_u1, U1, mf_u2, U2, &mf_lambda, &lambda,
1464 pmf_coeff, f_coeffs, alpha, WT1, WT2),
1465 nterm3(subterm3, r, mf_u1, U1, mf_u2, U2, &mf_lambda, &lambda,
1466 pmf_coeff, f_coeffs, alpha, WT1, WT2),
1467 nterm4(subterm4, r, mf_u1, U1, mf_u2, U2, &mf_lambda, &lambda,
1468 pmf_coeff, f_coeffs, alpha, WT1, WT2);
1470 const std::string aux_fems = pmf_coeff ?
"#1,#2,#3,#4" :
"#1,#2,#3";
1474 case 1:
case 3:
case 4:
1476 (
"M$1(#1,#3)+=comp(NonLin$1(#1," + aux_fems +
").vBase(#1).vBase(#3))(i,j,:,i,:,j); "
1477 "M$2(#3,#1)+=comp(NonLin$2(#1," + aux_fems +
").vBase(#3).vBase(#1))(i,j,:,j,:,i); "
1478 "M$3(#2,#3)+=comp(NonLin$1(#1," + aux_fems +
").vBase(#2).vBase(#3))(i,j,:,i,:,j); "
1479 "M$4(#3,#2)+=comp(NonLin$2(#1," + aux_fems +
").vBase(#3).vBase(#2))(i,j,:,j,:,i); "
1480 "M$5(#3,#3)+=comp(NonLin$3(#1," + aux_fems +
").vBase(#3).vBase(#3))(i,j,:,i,:,j)");
1484 (
"M$1(#1,#3)+=comp(NonLin$1(#1," + aux_fems +
").vBase(#1).vBase(#3))(i,j,:,i,:,j); "
1485 "M$2(#3,#1)+=comp(NonLin$2(#1," + aux_fems +
").vBase(#3).vBase(#1))(i,j,:,j,:,i); "
1486 "M$3(#2,#3)+=comp(NonLin$1(#1," + aux_fems +
").vBase(#2).vBase(#3))(i,j,:,i,:,j); "
1487 "M$4(#3,#2)+=comp(NonLin$2(#1," + aux_fems +
").vBase(#3).vBase(#2))(i,j,:,j,:,i); "
1488 "M$5(#3,#3)+=comp(NonLin$3(#1," + aux_fems +
").vBase(#3).vBase(#3))(i,j,:,i,:,j); "
1489 "M$6(#1,#1)+=comp(NonLin$4(#1," + aux_fems +
").vBase(#1).vBase(#1))(i,j,:,i,:,j); "
1490 "M$7(#2,#2)+=comp(NonLin$4(#1," + aux_fems +
").vBase(#2).vBase(#2))(i,j,:,i,:,j); "
1491 "M$8(#1,#2)+=comp(NonLin$4(#1," + aux_fems +
").vBase(#1).vBase(#2))(i,j,:,i,:,j); "
1492 "M$9(#2,#1)+=comp(NonLin$4(#1," + aux_fems +
").vBase(#2).vBase(#1))(i,j,:,i,:,j)");
1516 gmm::scale(Ku2l, scalar_type(-1));
1517 gmm::scale(Klu2, scalar_type(-1));
1518 gmm::scale(Ku1u2, scalar_type(-1));
1521 template<
typename VECT1>
1522 void asm_Alart_Curnier_contact_nonmatching_meshes_rhs
1523 (VECT1 &Ru1, VECT1 &Ru2, VECT1 &Rl,
1528 scalar_type r,
const mesh_region &rg,
int option = 1) {
1532 case 1 : subterm1 = RHS_U_V1;
break;
1533 case 2 : subterm1 = RHS_U_V2;
break;
1534 case 3 : subterm1 = RHS_U_V4;
break;
1535 default : GMM_ASSERT1(
false,
"Incorrect option");
1537 size_type subterm2 = (option == 3) ? RHS_L_V2 : RHS_L_V1;
1539 contact_nonmatching_meshes_nonlinear_term
1540 nterm1(subterm1, r, mf_u1, U1, mf_u2, U2, &mf_lambda, &lambda),
1541 nterm2(subterm2, r, mf_u1, U1, mf_u2, U2, &mf_lambda, &lambda);
1544 assem.set(
"V$1(#1)+=comp(NonLin$1(#1,#1,#2,#3).vBase(#1))(i,:,i); "
1545 "V$2(#2)+=comp(NonLin$1(#1,#1,#2,#3).vBase(#2))(i,:,i); "
1546 "V$3(#3)+=comp(NonLin$2(#1,#1,#2,#3).Base(#3))(i,:)");
1558 gmm::scale(Ru2, scalar_type(-1));
1561 template<
typename VECT1>
1562 void asm_Alart_Curnier_contact_nonmatching_meshes_rhs
1563 (VECT1 &Ru1, VECT1 &Ru2, VECT1 &Rl,
1569 scalar_type r, scalar_type
alpha,
1570 const VECT1 *WT1,
const VECT1 *WT2,
1571 const mesh_region &rg,
int option = 1) {
1575 case 1 : subterm1 = RHS_U_FRICT_V1; subterm2 = RHS_L_FRICT_V1;
break;
1576 case 2 : subterm1 = RHS_U_FRICT_V6; subterm2 = RHS_L_FRICT_V1;
break;
1577 case 3 : subterm1 = RHS_U_FRICT_V4; subterm2 = RHS_L_FRICT_V2;
break;
1578 case 4 : subterm1 = RHS_U_FRICT_V5; subterm2 = RHS_L_FRICT_V4;
break;
1579 default : GMM_ASSERT1(
false,
"Incorrect option");
1582 contact_nonmatching_meshes_nonlinear_term
1583 nterm1(subterm1, r, mf_u1, U1, mf_u2, U2, &mf_lambda, &lambda,
1584 pmf_coeff, f_coeffs, alpha, WT1, WT2),
1585 nterm2(subterm2, r, mf_u1, U1, mf_u2, U2, &mf_lambda, &lambda,
1586 pmf_coeff, f_coeffs, alpha, WT1, WT2);
1588 const std::string aux_fems = pmf_coeff ?
"#1,#2,#3,#4" :
"#1,#2,#3";
1591 assem.set(
"V$1(#1)+=comp(NonLin$1(#1," + aux_fems +
").vBase(#1))(i,:,i); "
1592 "V$2(#2)+=comp(NonLin$1(#1," + aux_fems +
").vBase(#2))(i,:,i); "
1593 "V$3(#3)+=comp(NonLin$2(#1," + aux_fems +
").vBase(#3))(i,:,i)");
1607 gmm::scale(Ru2, scalar_type(-1));
1610 struct integral_contact_nonmatching_meshes_brick :
public virtual_brick {
1623 virtual void asm_real_tangent_terms(
const model &md,
size_type ,
1624 const model::varnamelist &vl,
1625 const model::varnamelist &dl,
1626 const model::mimlist &mims,
1627 model::real_matlist &matl,
1628 model::real_veclist &vecl,
1629 model::real_veclist &,
1631 build_version version)
const {
1633 GMM_ASSERT1(mims.size() == 1,
1634 "Integral contact between nonmatching meshes bricks need a single mesh_im");
1635 const mesh_im &mim = *mims[0];
1640 GMM_ASSERT1(vl.size() == 3,
1641 "Integral contact between nonmatching meshes bricks need three variables");
1642 const model_real_plain_vector &u1 = md.real_variable(vl[0]);
1643 const model_real_plain_vector &u2 = md.real_variable(vl[1]);
1644 const mesh_fem &mf_u1 = md.mesh_fem_of_variable(vl[0]);
1645 const mesh_fem &mf_u2 = md.mesh_fem_of_variable(vl[1]);
1646 const model_real_plain_vector &lambda = md.real_variable(vl[2]);
1647 const mesh_fem &mf_lambda = md.mesh_fem_of_variable(vl[2]);
1648 GMM_ASSERT1(mf_lambda.get_qdim() == (contact_only ? 1 : mf_u1.get_qdim()),
1649 "The contact stress variable has not the right dimension");
1654 GMM_ASSERT1(dl.size() == 1,
1655 "Wrong number of data for integral contact between nonmatching meshes "
1656 <<
"brick, the number of data should be equal to 1 .");
1659 GMM_ASSERT1(dl.size() >= 2 && dl.size() <= 5,
1660 "Wrong number of data for integral contact between nonmatching meshes "
1661 <<
"brick, it should be between 2 and 5 instead of " << dl.size() <<
" .");
1663 const model_real_plain_vector &vr = md.real_variable(dl[0]);
1664 GMM_ASSERT1(gmm::vect_size(vr) == 1,
"Parameter r should be a scalar");
1666 const model_real_plain_vector *f_coeffs = 0, *WT1 = 0, *WT2 = 0;
1667 const mesh_fem *pmf_coeff = 0;
1668 scalar_type
alpha = 1;
1669 if (!contact_only) {
1670 f_coeffs = &(md.real_variable(dl[1]));
1671 pmf_coeff = md.pmesh_fem_of_variable(dl[1]);
1673 size_type sl = gmm::vect_size(*f_coeffs);
1674 if (pmf_coeff) { sl *= pmf_coeff->get_qdim(); sl /= pmf_coeff->nb_dof(); }
1675 GMM_ASSERT1(sl == 1 || sl == 2 || sl ==3,
1676 "the data corresponding to the friction coefficient "
1677 "has not the right format");
1679 if (dl.size() >= 3) {
1680 alpha = md.real_variable(dl[2])[0];
1681 GMM_ASSERT1(gmm::vect_size(md.real_variable(dl[2])) == 1,
1682 "Parameter alpha should be a scalar");
1685 if (dl.size() >= 4) {
1686 if (dl[3].compare(vl[0]) != 0)
1687 WT1 = &(md.real_variable(dl[3]));
1688 else if (md.n_iter_of_variable(vl[0]) > 1)
1689 WT1 = &(md.real_variable(vl[0],1));
1692 if (dl.size() >= 5) {
1693 if (dl[4].compare(vl[1]) != 0)
1694 WT2 = &(md.real_variable(dl[4]));
1695 else if (md.n_iter_of_variable(vl[1]) > 1)
1696 WT2 = &(md.real_variable(vl[1],1));
1701 GMM_ASSERT1(matl.size() ==
size_type(3 +
1702 2 * !is_symmetric() +
1704 1 * (option == 2 && !is_symmetric())),
1705 "Wrong number of terms for "
1706 "integral contact between nonmatching meshes brick");
1708 mesh_region rg(region);
1709 mf_u1.linked_mesh().intersect_with_mpi_region(rg);
1711 size_type N = mf_u1.linked_mesh().dim();
1718 mf_u2_proj.set_finite_element(mim.linked_mesh().convex_index(), pfem_proj);
1721 size_type nbdof_lambda = mf_lambda.nb_dof();
1723 size_type nbsub = mf_u2_proj.nb_basic_dof();
1725 std::vector<size_type> ind;
1726 mf_u2_proj.get_global_dof_index(ind);
1727 gmm::unsorted_sub_index SUBI(ind);
1729 gmm::csc_matrix<scalar_type> Esub(nbsub, nbdof2);
1730 if (mf_u2.is_reduced())
1731 gmm::copy(gmm::sub_matrix(mf_u2.extension_matrix(),
1732 SUBI, gmm::sub_interval(0, nbdof2)),
1735 model_real_plain_vector u2_proj(nbsub);
1736 if (mf_u2.is_reduced())
1737 gmm::mult(Esub, u2, u2_proj);
1739 gmm::copy(gmm::sub_vector(u2, SUBI), u2_proj);
1741 model_real_plain_vector WT2_proj(0);
1744 if (mf_u2.is_reduced())
1745 gmm::mult(Esub, *WT2, WT2_proj);
1747 gmm::copy(gmm::sub_vector(*WT2, SUBI), WT2_proj);
1760 if (version & model::BUILD_MATRIX) {
1761 GMM_TRACE2(
"Integral contact between nonmatching meshes "
1763 for (
size_type i = 0; i < matl.size(); i++) gmm::clear(matl[i]);
1765 model_real_sparse_matrix dummy_mat(0, 0);
1766 model_real_sparse_matrix &Klu1 = (LU1 ==
size_type(-1)) ? dummy_mat : matl[LU1];
1767 model_real_sparse_matrix &Ku1u1 = (U1U1 ==
size_type(-1)) ? dummy_mat : matl[U1U1];
1769 model_real_sparse_matrix Ku2l(nbsub, nbdof_lambda);
1770 model_real_sparse_matrix Klu2(nbdof_lambda, nbsub);
1771 model_real_sparse_matrix Ku2u2(nbsub, nbsub);
1772 model_real_sparse_matrix Ku1u2(nbdof1, nbsub);
1773 model_real_sparse_matrix Ku2u1(nbsub, nbdof1);
1776 asm_Alart_Curnier_contact_nonmatching_meshes_tangent_matrix
1777 (matl[U1L], Klu1, Ku2l, Klu2, matl[LL], Ku1u1, Ku2u2, Ku1u2,
1778 mim, mf_u1, u1, mf_u2_proj, u2_proj, mf_lambda, lambda,
1781 asm_Alart_Curnier_contact_nonmatching_meshes_tangent_matrix
1782 (matl[U1L], Klu1, Ku2l, Klu2, matl[LL], Ku1u1, Ku2u2, Ku1u2, Ku2u1,
1783 mim, mf_u1, u1, mf_u2_proj, u2_proj, mf_lambda, lambda,
1784 pmf_coeff, f_coeffs, vr[0], alpha, WT1, &WT2_proj, rg, option);
1786 if (mf_u2.is_reduced()) {
1787 gmm::mult(gmm::transposed(Esub), Ku2l, matl[U2L]);
1788 if (LU2 !=
size_type(-1)) gmm::mult(Klu2, Esub, matl[LU2]);
1790 model_real_sparse_matrix tmp(nbsub, nbdof2);
1791 gmm::mult(Ku2u2, Esub, tmp);
1792 gmm::mult(gmm::transposed(Esub), tmp, matl[U2U2]);
1794 if (U1U2 !=
size_type(-1)) gmm::mult(Ku1u2, Esub, matl[U1U2]);
1795 if (U2U1 !=
size_type(-1)) gmm::mult(gmm::transposed(Esub), Ku2u1, matl[U2U1]);
1798 gmm::copy(Ku2l, gmm::sub_matrix(matl[U2L], SUBI, gmm::sub_interval(0, nbdof_lambda)));
1800 gmm::copy(Klu2, gmm::sub_matrix(matl[LU2], gmm::sub_interval(0, nbdof_lambda), SUBI));
1802 gmm::copy(Ku2u2, gmm::sub_matrix(matl[U2U2], SUBI));
1804 gmm::copy(Ku1u2, gmm::sub_matrix(matl[U1U2], gmm::sub_interval(0, nbdof1), SUBI));
1806 gmm::copy(Ku2u1, gmm::sub_matrix(matl[U2U1], SUBI, gmm::sub_interval(0, nbdof1)));
1810 if (version & model::BUILD_RHS) {
1811 for (
size_type i = 0; i < matl.size(); i++) gmm::clear(vecl[i]);
1813 model_real_plain_vector Ru2(nbsub);
1816 asm_Alart_Curnier_contact_nonmatching_meshes_rhs
1817 (vecl[U1L], Ru2, vecl[LL],
1818 mim, mf_u1, u1, mf_u2_proj, u2_proj, mf_lambda, lambda,
1821 asm_Alart_Curnier_contact_nonmatching_meshes_rhs
1822 (vecl[U1L], Ru2, vecl[LL],
1823 mim, mf_u1, u1, mf_u2_proj, u2_proj, mf_lambda, lambda,
1824 pmf_coeff, f_coeffs, vr[0], alpha, WT1, &WT2_proj, rg, option);
1826 if (mf_u2.is_reduced())
1827 gmm::mult(gmm::transposed(Esub), Ru2, vecl[U2L]);
1829 gmm::copy(Ru2, gmm::sub_vector(vecl[U2L], SUBI));
1834 bool contact_only_,
int option_)
1835 : rg1(rg1_), rg2(rg2_), pfem_proj(0),
1836 contact_only(contact_only_), option(option_)
1838 set_flags(contact_only
1839 ?
"Integral contact between nonmatching meshes brick"
1840 :
"Integral contact and friction between nonmatching "
1843 (option==2) && contact_only ,
1848 ~integral_contact_nonmatching_meshes_brick()
1861 const std::string &varname_u2,
const std::string &multname_n,
1862 const std::string &dataname_r,
1865 pbrick pbr = std::make_shared<integral_contact_nonmatching_meshes_brick>
1866 (region1, region2,
true , option);
1872 tl.push_back(model::term_description(varname_u1, multname_n,
false));
1873 tl.push_back(model::term_description(multname_n, varname_u1,
false));
1874 tl.push_back(model::term_description(varname_u2, multname_n,
false));
1875 tl.push_back(model::term_description(multname_n, varname_u2,
false));
1876 tl.push_back(model::term_description(multname_n, multname_n,
true));
1879 tl.push_back(model::term_description(varname_u1, multname_n,
true));
1880 tl.push_back(model::term_description(varname_u2, multname_n,
true));
1881 tl.push_back(model::term_description(multname_n, multname_n,
true));
1882 tl.push_back(model::term_description(varname_u1, varname_u1,
true));
1883 tl.push_back(model::term_description(varname_u2, varname_u2,
true));
1884 tl.push_back(model::term_description(varname_u1, varname_u2,
true));
1886 default : GMM_ASSERT1(
false,
1887 "Incorrect option for integral contact brick");
1890 model::varnamelist dl(1, dataname_r);
1892 model::varnamelist vl(1, varname_u1);
1893 vl.push_back(varname_u2);
1894 vl.push_back(multname_n);
1896 return md.
add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region1);
1907 const std::string &varname_u2,
const std::string &multname,
1908 const std::string &dataname_r,
const std::string &dataname_friction_coeffs,
1910 const std::string &dataname_alpha,
1911 const std::string &dataname_wt1,
const std::string &dataname_wt2) {
1913 pbrick pbr = std::make_shared<integral_contact_nonmatching_meshes_brick>
1914 (region1, region2,
false , option);
1919 case 1 :
case 3 :
case 4 :
1920 tl.push_back(model::term_description(varname_u1, multname,
false));
1921 tl.push_back(model::term_description(multname, varname_u1,
false));
1922 tl.push_back(model::term_description(varname_u2, multname,
false));
1923 tl.push_back(model::term_description(multname, varname_u2,
false));
1924 tl.push_back(model::term_description(multname, multname,
true));
1927 tl.push_back(model::term_description(varname_u1, multname,
false));
1928 tl.push_back(model::term_description(multname, varname_u1,
false));
1929 tl.push_back(model::term_description(varname_u2, multname,
false));
1930 tl.push_back(model::term_description(multname, varname_u2,
false));
1931 tl.push_back(model::term_description(multname, multname,
true));
1932 tl.push_back(model::term_description(varname_u1, varname_u1,
true));
1933 tl.push_back(model::term_description(varname_u2, varname_u2,
true));
1934 tl.push_back(model::term_description(varname_u1, varname_u2,
true));
1935 tl.push_back(model::term_description(varname_u2, varname_u1,
true));
1937 default : GMM_ASSERT1(
false,
1938 "Incorrect option for integral contact brick");
1941 model::varnamelist dl(1, dataname_r);
1942 dl.push_back(dataname_friction_coeffs);
1943 if (dataname_alpha.size()) {
1944 dl.push_back(dataname_alpha);
1945 if (dataname_wt1.size()) {
1946 dl.push_back(dataname_wt1);
1947 if (dataname_wt2.size()) {
1948 dl.push_back(dataname_wt2);
1954 model::varnamelist vl(1, varname_u1);
1955 vl.push_back(varname_u2);
1956 vl.push_back(multname);
1958 return md.
add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region1);
1968 template<
typename MAT,
typename VECT1>
1969 void asm_penalized_contact_nonmatching_meshes_tangent_matrix
1970 (MAT &Ku1u1, MAT &Ku2u2, MAT &Ku1u2,
1975 const scalar_type r,
const mesh_region &rg,
int option = 1) {
1977 contact_nonmatching_meshes_nonlinear_term
1978 nterm((option == 1) ? K_UU_V1 : K_UU_V2, r,
1979 mf_u1, U1, mf_u2, U2, pmf_lambda, lambda);
1981 const std::string aux_fems = pmf_lambda ?
"#1,#2,#3" :
"#1,#2";
1984 assem.set(
"M$1(#1,#1)+=comp(NonLin(#1," + aux_fems +
").vBase(#1).vBase(#1))(i,j,:,i,:,j); "
1985 "M$2(#2,#2)+=comp(NonLin(#1," + aux_fems +
").vBase(#2).vBase(#2))(i,j,:,i,:,j); "
1986 "M$3(#1,#2)+=comp(NonLin(#1," + aux_fems +
").vBase(#1).vBase(#2))(i,j,:,i,:,j)");
1998 gmm::scale(Ku1u2, scalar_type(-1));
2001 template<
typename VECT1>
2002 void asm_penalized_contact_nonmatching_meshes_rhs
2003 (VECT1 &Ru1, VECT1 &Ru2,
2008 scalar_type r,
const mesh_region &rg,
int option = 1) {
2010 contact_nonmatching_meshes_nonlinear_term
2011 nterm((option == 1) ? RHS_U_V5 : RHS_U_V2, r,
2012 mf_u1, U1, mf_u2, U2, pmf_lambda, lambda);
2014 const std::string aux_fems = pmf_lambda ?
"#1,#2,#3":
"#1,#2";
2016 assem.set(
"V$1(#1)+=comp(NonLin$1(#1," + aux_fems +
").vBase(#1))(i,:,i); "
2017 "V$2(#2)+=comp(NonLin$1(#1," + aux_fems +
").vBase(#2))(i,:,i)");
2028 gmm::scale(Ru2, scalar_type(-1));
2032 template<
typename MAT,
typename VECT1>
2033 void asm_penalized_contact_nonmatching_meshes_tangent_matrix
2034 (MAT &Ku1u1, MAT &Ku2u2, MAT &Ku1u2, MAT &Ku2u1,
2040 scalar_type
alpha,
const VECT1 *WT1,
const VECT1 *WT2,
2041 const mesh_region &rg,
int option = 1) {
2045 case 1 : subterm = K_UU_FRICT_V4;
break;
2046 case 2 : subterm = K_UU_FRICT_V3;
break;
2047 case 3 : subterm = K_UU_FRICT_V5;
break;
2050 contact_nonmatching_meshes_nonlinear_term
2051 nterm(subterm, r, mf_u1, U1, mf_u2, U2, pmf_lambda, lambda,
2052 pmf_coeff, f_coeffs, alpha, WT1, WT2);
2054 const std::string aux_fems = pmf_coeff ?
"#1,#2,#3,#4"
2055 : (pmf_lambda ?
"#1,#2,#3":
"#1,#2");
2058 assem.set(
"M$1(#1,#1)+=comp(NonLin(#1," + aux_fems +
").vBase(#1).vBase(#1))(i,j,:,i,:,j); "
2059 "M$2(#2,#2)+=comp(NonLin(#1," + aux_fems +
").vBase(#2).vBase(#2))(i,j,:,i,:,j); "
2060 "M$3(#1,#2)+=comp(NonLin(#1," + aux_fems +
").vBase(#1).vBase(#2))(i,j,:,i,:,j); "
2061 "M$4(#2,#1)+=comp(NonLin(#1," + aux_fems +
").vBase(#2).vBase(#1))(i,j,:,i,:,j)");
2081 gmm::scale(Ku1u2, scalar_type(-1));
2082 gmm::scale(Ku2u1, scalar_type(-1));
2086 template<
typename VECT1>
2087 void asm_penalized_contact_nonmatching_meshes_rhs
2088 (VECT1 &Ru1, VECT1 &Ru2,
2094 scalar_type
alpha,
const VECT1 *WT1,
const VECT1 *WT2,
2095 const mesh_region &rg,
int option = 1) {
2099 case 1 : subterm = RHS_U_FRICT_V7;
break;
2100 case 2 : subterm = RHS_U_FRICT_V6;
break;
2101 case 3 : subterm = RHS_U_FRICT_V8;
break;
2104 contact_nonmatching_meshes_nonlinear_term
2105 nterm(subterm, r, mf_u1, U1, mf_u2, U2, pmf_lambda, lambda,
2106 pmf_coeff, f_coeffs, alpha, WT1, WT2);
2108 const std::string aux_fems = pmf_coeff ?
"#1,#2,#3,#4"
2109 : (pmf_lambda ?
"#1,#2,#3":
"#1,#2");
2111 assem.set(
"V$1(#1)+=comp(NonLin$1(#1," + aux_fems +
").vBase(#1))(i,:,i); "
2112 "V$2(#2)+=comp(NonLin$1(#1," + aux_fems +
").vBase(#2))(i,:,i)");
2131 gmm::scale(Ru2, scalar_type(-1));
2135 struct penalized_contact_nonmatching_meshes_brick :
public virtual_brick {
2143 virtual void asm_real_tangent_terms(
const model &md,
size_type ,
2144 const model::varnamelist &vl,
2145 const model::varnamelist &dl,
2146 const model::mimlist &mims,
2147 model::real_matlist &matl,
2148 model::real_veclist &vecl,
2149 model::real_veclist &,
2151 build_version version)
const {
2153 GMM_ASSERT1(mims.size() == 1,
2154 "Penalized contact between nonmatching meshes bricks need a single mesh_im");
2155 const mesh_im &mim = *mims[0];
2158 GMM_ASSERT1(vl.size() == 2,
2159 "Penalized contact between nonmatching meshes bricks need two variables");
2160 const model_real_plain_vector &u1 = md.real_variable(vl[0]);
2161 const model_real_plain_vector &u2 = md.real_variable(vl[1]);
2162 const mesh_fem &mf_u1 = md.mesh_fem_of_variable(vl[0]);
2163 const mesh_fem &mf_u2 = md.mesh_fem_of_variable(vl[1]);
2165 size_type N = mf_u1.linked_mesh().dim();
2168 size_type nb_data_1 = ((option == 1) ? 1 : 2) + (contact_only ? 0 : 1);
2169 size_type nb_data_2 = nb_data_1 + (contact_only ? 0 : 3);
2170 GMM_ASSERT1(dl.size() >= nb_data_1 && dl.size() <= nb_data_2,
2171 "Wrong number of data for penalized contact between nonmatching meshes "
2172 <<
"brick, " << dl.size() <<
" should be between "
2173 << nb_data_1 <<
" and " << nb_data_2 <<
".");
2176 const model_real_plain_vector &vr = md.real_variable(dl[nd]);
2177 GMM_ASSERT1(gmm::vect_size(vr) == 1,
"Parameter r should be a scalar");
2180 const model_real_plain_vector *lambda = 0;
2181 const mesh_fem *pmf_lambda = 0;
2184 lambda = &(md.real_variable(dl[nd]));
2185 pmf_lambda = md.pmesh_fem_of_variable(dl[nd]);
2186 sl = gmm::vect_size(*lambda) * pmf_lambda->get_qdim() / pmf_lambda->nb_dof();
2187 GMM_ASSERT1(sl == (contact_only ? 1 : N),
2188 "the data corresponding to the contact stress "
2189 "has not the right format");
2192 const model_real_plain_vector *f_coeffs = 0;
2193 const mesh_fem *pmf_coeff = 0;
2194 scalar_type
alpha = 1;
2195 const model_real_plain_vector *WT1 = 0;
2196 const model_real_plain_vector *WT2 = 0;
2197 if (!contact_only) {
2199 f_coeffs = &(md.real_variable(dl[nd]));
2200 pmf_coeff = md.pmesh_fem_of_variable(dl[nd]);
2201 sl = gmm::vect_size(*f_coeffs);
2202 if (pmf_coeff) { sl *= pmf_coeff->get_qdim(); sl /= pmf_coeff->nb_dof(); }
2203 GMM_ASSERT1(sl == 1 || sl == 2 || sl == 3,
2204 "the data corresponding to the friction coefficient "
2205 "has not the right format");
2207 if (dl.size() > nd+1) {
2209 alpha = md.real_variable(dl[nd])[0];
2210 GMM_ASSERT1(gmm::vect_size(md.real_variable(dl[nd])) == 1,
2211 "Parameter alpha should be a scalar");
2214 if (dl.size() > nd+1) {
2216 if (dl[nd].compare(vl[0]) != 0)
2217 WT1 = &(md.real_variable(dl[nd]));
2218 else if (md.n_iter_of_variable(vl[0]) > 1)
2219 WT1 = &(md.real_variable(vl[0],1));
2222 if (dl.size() > nd+1) {
2224 if (dl[nd].compare(vl[1]) != 0)
2225 WT2 = &(md.real_variable(dl[nd]));
2226 else if (md.n_iter_of_variable(vl[1]) > 1)
2227 WT2 = &(md.real_variable(vl[1],1));
2231 GMM_ASSERT1(matl.size() == (contact_only ? 3 : 4),
2232 "Wrong number of terms for penalized contact "
2233 "between nonmatching meshes brick");
2235 mesh_region rg(region);
2236 mf_u1.linked_mesh().intersect_with_mpi_region(rg);
2243 mf_u2_proj.set_finite_element(mim.linked_mesh().convex_index(), pfem_proj);
2249 std::vector<size_type> ind;
2250 mf_u2_proj.get_global_dof_index(ind);
2251 gmm::unsorted_sub_index SUBI(ind);
2253 gmm::csc_matrix<scalar_type> Esub(nbsub, nbdof2);
2254 if (mf_u2.is_reduced())
2255 gmm::copy(gmm::sub_matrix(mf_u2.extension_matrix(),
2256 SUBI, gmm::sub_interval(0, nbdof2)),
2259 model_real_plain_vector u2_proj(nbsub);
2260 if (mf_u2.is_reduced())
2261 gmm::mult(Esub, u2, u2_proj);
2263 gmm::copy(gmm::sub_vector(u2, SUBI), u2_proj);
2265 model_real_plain_vector WT2_proj(0);
2268 if (mf_u2.is_reduced())
2269 gmm::mult(Esub, *WT2, WT2_proj);
2271 gmm::copy(gmm::sub_vector(*WT2, SUBI), WT2_proj);
2274 if (version & model::BUILD_MATRIX) {
2275 GMM_TRACE2(
"Penalized contact between nonmatching meshes tangent term");
2280 model_real_sparse_matrix Ku2u2(nbsub,nbsub);
2281 model_real_sparse_matrix Ku1u2(nbdof1,nbsub);
2284 asm_penalized_contact_nonmatching_meshes_tangent_matrix
2285 (matl[0], Ku2u2, Ku1u2, mim, mf_u1, u1, mf_u2_proj, u2_proj,
2286 pmf_lambda, lambda, vr[0], rg, option);
2290 model_real_sparse_matrix Ku2u1(nbsub,nbdof1);
2291 asm_penalized_contact_nonmatching_meshes_tangent_matrix
2292 (matl[0], Ku2u2, Ku1u2, Ku2u1, mim, mf_u1, u1, mf_u2_proj, u2_proj,
2293 pmf_lambda, lambda, pmf_coeff, f_coeffs, vr[0], alpha, WT1, &WT2_proj, rg, option);
2294 if (mf_u2.is_reduced())
2295 gmm::mult(gmm::transposed(Esub), Ku2u1, matl[3]);
2297 gmm::copy(Ku2u1, gmm::sub_matrix(matl[3], SUBI, gmm::sub_interval(0, nbdof1)));
2300 if (mf_u2.is_reduced()) {
2301 model_real_sparse_matrix tmp(nbsub, nbdof2);
2302 gmm::mult(Ku2u2, Esub, tmp);
2303 gmm::mult(gmm::transposed(Esub), tmp, matl[1]);
2304 gmm::mult(Ku1u2, Esub, matl[2]);
2307 gmm::copy(Ku2u2, gmm::sub_matrix(matl[1], SUBI));
2308 gmm::copy(Ku1u2, gmm::sub_matrix(matl[2], gmm::sub_interval(0, nbdof1), SUBI));
2312 if (version & model::BUILD_RHS) {
2316 model_real_plain_vector Ru2(nbsub);
2319 asm_penalized_contact_nonmatching_meshes_rhs
2320 (vecl[0], Ru2, mim, mf_u1, u1, mf_u2_proj, u2_proj, pmf_lambda, lambda,
2323 asm_penalized_contact_nonmatching_meshes_rhs
2324 (vecl[0], Ru2, mim, mf_u1, u1, mf_u2_proj, u2_proj, pmf_lambda, lambda,
2325 pmf_coeff, f_coeffs, vr[0], alpha, WT1, &WT2_proj, rg, option);
2327 if (mf_u2.is_reduced())
2328 gmm::mult(gmm::transposed(Esub), Ru2, vecl[1]);
2330 gmm::copy(Ru2, gmm::sub_vector(vecl[1], SUBI));
2335 bool contact_only_,
int option_)
2336 : rg1(rg1_), rg2(rg2_), pfem_proj(0),
2337 contact_only(contact_only_), option(option_)
2339 set_flags(contact_only
2340 ?
"Integral penalized contact between nonmatching meshes brick"
2341 :
"Integral penalized contact and friction between nonmatching "
2343 false , contact_only ,
2348 ~penalized_contact_nonmatching_meshes_brick()
2361 const std::string &varname_u2,
const std::string &dataname_r,
2363 int option,
const std::string &dataname_n) {
2365 pbrick pbr = std::make_shared<penalized_contact_nonmatching_meshes_brick>
2366 (region1, region2,
true , option);
2368 tl.push_back(model::term_description(varname_u1, varname_u1,
true));
2369 tl.push_back(model::term_description(varname_u2, varname_u2,
true));
2370 tl.push_back(model::term_description(varname_u1, varname_u2,
true));
2372 model::varnamelist dl(1, dataname_r);
2375 case 2: dl.push_back(dataname_n);
break;
2376 default: GMM_ASSERT1(
false,
"Penalized contact brick : invalid option");
2379 model::varnamelist vl(1, varname_u1);
2380 vl.push_back(varname_u2);
2382 return md.
add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region1);
2393 const std::string &varname_u2,
const std::string &dataname_r,
2394 const std::string &dataname_friction_coeffs,
2396 const std::string &dataname_lambda,
const std::string &dataname_alpha,
2397 const std::string &dataname_wt1,
const std::string &dataname_wt2) {
2399 pbrick pbr = std::make_shared<penalized_contact_nonmatching_meshes_brick>
2400 (region1, region2,
false , option);
2402 tl.push_back(model::term_description(varname_u1, varname_u1,
true));
2403 tl.push_back(model::term_description(varname_u2, varname_u2,
true));
2404 tl.push_back(model::term_description(varname_u1, varname_u2,
true));
2405 tl.push_back(model::term_description(varname_u2, varname_u1,
true));
2407 model::varnamelist dl(1, dataname_r);
2410 case 2:
case 3: dl.push_back(dataname_lambda);
break;
2411 default: GMM_ASSERT1(
false,
"Penalized contact brick : invalid option");
2413 dl.push_back(dataname_friction_coeffs);
2414 if (dataname_alpha.size() > 0) {
2415 dl.push_back(dataname_alpha);
2416 if (dataname_wt1.size() > 0) {
2417 dl.push_back(dataname_wt1);
2418 if (dataname_wt2.size() > 0)
2419 dl.push_back(dataname_wt2);
2423 model::varnamelist vl(1, varname_u1);
2424 vl.push_back(varname_u2);
2426 return md.
add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region1);
2431 void compute_integral_contact_area_and_force
2432 (model &md,
size_type indbrick, scalar_type &area,
2433 model_real_plain_vector &F) {
2435 pbrick pbr = md.brick_pointer(indbrick);
2436 const model::mimlist &ml = md.mimlist_of_brick(indbrick);
2437 const model::varnamelist &vl = md.varnamelist_of_brick(indbrick);
2438 const model::varnamelist &dl = md.datanamelist_of_brick(indbrick);
2439 size_type reg = md.region_of_brick(indbrick);
2441 GMM_ASSERT1(ml.size() == 1,
"Wrong size");
2443 if (pbr->brick_name() ==
"Integral contact with rigid obstacle brick" ||
2444 pbr->brick_name() ==
"Integral contact and friction with rigid obstacle brick") {
2445 integral_contact_rigid_obstacle_brick *p
2446 =
dynamic_cast<integral_contact_rigid_obstacle_brick *
>
2447 (
const_cast<virtual_brick *
>(pbr.get()));
2448 GMM_ASSERT1(p,
"Wrong type of brick");
2450 GMM_ASSERT1(vl.size() >= 2,
"Wrong size");
2451 const model_real_plain_vector &u = md.real_variable(vl[0]);
2452 const mesh_fem &mf_u = md.mesh_fem_of_variable(vl[0]);
2453 const model_real_plain_vector &lambda = md.real_variable(vl[1]);
2454 const mesh_fem &mf_lambda = md.mesh_fem_of_variable(vl[1]);
2455 GMM_ASSERT1(dl.size() >= 1,
"Wrong size");
2456 const model_real_plain_vector &obs = md.real_variable(dl[0]);
2457 const mesh_fem &mf_obs = md.mesh_fem_of_variable(dl[0]);
2460 area = asm_level_set_contact_area(*ml[0], mf_u, u, mf_obs, obs, reg, -1e-3,
2461 &mf_lambda, &lambda, 1e-1);
2463 gmm::resize(F, mf_u.nb_dof());
2465 (F, *ml[0], mf_u, mf_obs, obs, mf_lambda, lambda, reg);
2467 else if (pbr->brick_name() ==
"Integral penalized contact with rigid obstacle brick" ||
2468 pbr->brick_name() ==
"Integral penalized contact and friction with rigid "
2470 penalized_contact_rigid_obstacle_brick *p
2471 =
dynamic_cast<penalized_contact_rigid_obstacle_brick *
>
2472 (
const_cast<virtual_brick *
>(pbr.get()));
2473 GMM_ASSERT1(p,
"Wrong type of brick");
2474 GMM_ASSERT1(
false,
"Not implemented yet");
2476 else if (pbr->brick_name() ==
"Integral contact between nonmatching meshes brick" ||
2477 pbr->brick_name() ==
"Integral contact and friction between nonmatching "
2479 integral_contact_nonmatching_meshes_brick *p
2480 =
dynamic_cast<integral_contact_nonmatching_meshes_brick *
>
2481 (
const_cast<virtual_brick *
>(pbr.get()));
2482 GMM_ASSERT1(p,
"Wrong type of brick");
2484 GMM_ASSERT1(vl.size() == 3,
"Wrong size");
2485 const model_real_plain_vector &u1 = md.real_variable(vl[0]);
2486 const model_real_plain_vector &u2 = md.real_variable(vl[1]);
2487 const mesh_fem &mf_u1 = md.mesh_fem_of_variable(vl[0]);
2488 const mesh_fem &mf_u2 = md.mesh_fem_of_variable(vl[1]);
2489 const model_real_plain_vector &lambda = md.real_variable(vl[2]);
2490 const mesh_fem &mf_lambda = md.mesh_fem_of_variable(vl[2]);
2493 getfem::mesh_fem mf_u2_proj(mf_u1.linked_mesh(), mf_u1.linked_mesh().dim());
2494 mf_u2_proj.set_finite_element(mf_u1.linked_mesh().convex_index(), pfem_proj);
2496 std::vector<size_type> ind;
2497 mf_u2_proj.get_global_dof_index(ind);
2498 gmm::unsorted_sub_index SUBI(ind);
2501 size_type nbsub = mf_u2_proj.nb_basic_dof();
2502 model_real_plain_vector u2_proj(nbsub);
2504 if (mf_u2.is_reduced()) {
2505 gmm::csc_matrix<scalar_type> Esub(nbsub, nbdof2);
2506 gmm::copy(gmm::sub_matrix(mf_u2.extension_matrix(),
2507 SUBI, gmm::sub_interval(0, nbdof2)),
2509 gmm::mult(Esub, u2, u2_proj);
2512 gmm::copy(gmm::sub_vector(u2, SUBI), u2_proj);
2515 area = asm_nonmatching_meshes_contact_area
2516 (*ml[0], mf_u1, u1, mf_u2_proj, u2_proj, reg, -1e-3,
2517 &mf_lambda, &lambda, 1e-1);
2520 asm_nonmatching_meshes_normal_source_term
2521 (F, *ml[0], mf_u1, mf_u2_proj, mf_lambda, lambda, reg);
2525 else if (pbr->brick_name() ==
"Integral penalized contact between nonmatching meshes brick" ||
2526 pbr->brick_name() ==
"Integral penalized contact and friction between nonmatching "
2528 penalized_contact_nonmatching_meshes_brick *p
2529 =
dynamic_cast<penalized_contact_nonmatching_meshes_brick *
>
2530 (
const_cast<virtual_brick *
>(pbr.get()));
2531 GMM_ASSERT1(p,
"Wrong type of brick");
2532 GMM_ASSERT1(
false,
"Not implemented yet");
2545 const std::string &Neumannterm,
2546 const std::string &obs,
const std::string &dataname_gamma0,
2548 std::string dataname_friction_coeff,
2549 const std::string &dataname_alpha,
2550 const std::string &dataname_wt,
2553 std::string theta = std::to_string(theta_);
2554 ga_workspace workspace(md, ga_workspace::inherit::ALL);
2555 size_type order = workspace.add_expression(Neumannterm, mim, region, 1);
2556 GMM_ASSERT1(order == 0,
"Wrong expression of the Neumann term");
2560 std::string gamma =
"(("+dataname_gamma0+
")/element_size)";
2561 std::string thetagamma =
"("+theta+
"/"+gamma+
")";
2562 std::string contact_normal =
"(-Normalized(Grad_"+obs+
"))";
2563 std::string gap =
"("+obs+
"-"+varname_u+
"."+contact_normal+
")";
2564 std::string Vs =
"("+varname_u +
2565 (dataname_wt.size() ?
"-("+dataname_wt+
"))" :
")");
2566 if (dataname_alpha.size()) Vs =
"(("+dataname_alpha+
")*"+Vs;
2567 if (dataname_friction_coeff.size() == 0)
2568 dataname_friction_coeff = std::string(
"0");
2570 std::string expr =
"Coulomb_friction_coupled_projection("+Neumannterm
2571 +
", "+contact_normal+
", "+Vs+
", "+gap+
", "+dataname_friction_coeff
2574 if (theta_ != scalar_type(0)) {
2575 std::string derivative_Neumann=workspace.extract_order1_term(varname_u);
2576 expr =
"-"+thetagamma+
"*("+Neumannterm+
").("+derivative_Neumann
2577 +
") + "+expr+thetagamma+
"*("+derivative_Neumann+
")";
2579 expr +=
"-Test_"+varname_u+
")";
2581 return add_nonlinear_generic_assembly_brick
2582 (md, mim, expr, region,
false,
false,
2583 "Nitsche contact with rigid obstacle");
2586 #ifdef EXPERIMENTAL_PURPOSE_ONLY
2596 size_type add_Nitsche_contact_with_rigid_obstacle_brick_modified_midpoint
2597 (model &md,
const mesh_im &mim,
const std::string &varname_u,
2598 const std::string &Neumannterm,
2599 const std::string &Neumannterm_wt,
2600 const std::string &obs,
const std::string &dataname_gamma0,
2602 std::string dataname_friction_coeff,
2603 const std::string &,
2604 const std::string &dataname_wt,
2607 std::string theta = std::to_string(theta_);
2608 ga_workspace workspace(md, ga_workspace::inherit::ALL);
2609 size_type order = workspace.add_expression(Neumannterm, mim, region, 1);
2610 GMM_ASSERT1(order == 0,
"Wrong expression of the Neumann term");
2612 std::string gamma =
"((1/("+dataname_gamma0+
"))*element_size)";
2613 std::string thetagamma =
"("+theta+
"*"+gamma+
")";
2614 std::string contact_normal =
"(-Normalized(Grad_"+obs+
"))";
2615 std::string gap =
"("+obs+
"-"+varname_u+
"."+contact_normal+
")";
2616 std::string gap_wt =
"("+obs+
"-"+dataname_wt+
"."+contact_normal+
")";
2617 std::string Vs =
"("+varname_u +
2618 (dataname_wt.size() ?
"-("+dataname_wt+
"))" :
")");
2619 std::string Vs_wt = Vs;
2620 if (dataname_friction_coeff.size() == 0)
2621 dataname_friction_coeff = std::string(
"0");
2623 std::string Pg_wt =
"(-"+gamma+
"*("+Neumannterm_wt+
")."+contact_normal+
2627 =
"((Heaviside("+Pg_wt+
")*Coulomb_friction_coupled_projection("
2628 +Neumannterm+
", "+contact_normal+
", "+Vs+
", "+gap+
", "
2629 +dataname_friction_coeff+
",1/"+gamma+
"))+"
2630 +
"((1-Heaviside("+Pg_wt+
"))*(Coulomb_friction_coupled_projection("
2631 +Neumannterm_wt+
", "+contact_normal+
", "+Vs_wt+
", "+gap_wt+
", "
2632 +dataname_friction_coeff+
",1/"+gamma+
")*0.5+"
2633 "Coulomb_friction_coupled_projection(2*("
2634 +Neumannterm+
")-("+Neumannterm_wt+
"), "+contact_normal
2635 +
", 2*"+Vs+
"-"+Vs_wt+
", 2*"+gap+
"-"+gap_wt+
", "
2636 +dataname_friction_coeff+
",1/"+gamma+
")*0.5))).(";
2638 if (theta_ != scalar_type(0)) {
2639 std::string derivative_Neumann=workspace.extract_order1_term(varname_u);
2640 expr =
"-"+thetagamma+
"*("+Neumannterm+
").("+derivative_Neumann
2641 +
") + "+expr+thetagamma+
"*("+derivative_Neumann+
")";
2643 expr +=
"-Test_"+varname_u+
")";
2645 return add_nonlinear_generic_assembly_brick
2646 (md, mim, expr, region,
false,
false,
2647 "Nitsche contact with rigid obstacle");