38 #ifndef GETFEM_CONTACT_AND_FRICTION_INTEGRAL_H__
39 #define GETFEM_CONTACT_AND_FRICTION_INTEGRAL_H__
67 (model &md,
const mesh_im &mim,
const std::string &varname_u,
68 const std::string &multname_n,
const std::string &dataname_obs,
69 const std::string &dataname_r,
size_type region,
int option = 1);
103 (model &md,
const mesh_im &mim,
const std::string &varname_u,
104 const std::string &multname,
const std::string &dataname_obs,
105 const std::string &dataname_r,
const std::string &dataname_friction_coeffs,
106 size_type region,
int option = 1,
const std::string &dataname_alpha =
"",
107 const std::string &dataname_wt =
"",
108 const std::string &dataname_gamma =
"",
109 const std::string &dataname_vt =
"");
127 (model &md,
const mesh_im &mim,
const std::string &varname_u,
128 const std::string &dataname_obs,
const std::string &dataname_r,
129 size_type region,
int option = 1,
const std::string &dataname_lambda_n =
"");
155 (model &md,
const mesh_im &mim,
const std::string &varname_u,
156 const std::string &dataname_obs,
const std::string &dataname_r,
157 const std::string &dataname_friction_coeffs,
158 size_type region,
int option = 1,
const std::string &dataname_lambda =
"",
159 const std::string &dataname_alpha =
"",
160 const std::string &dataname_wt =
"");
183 (model &md,
const mesh_im &mim,
const std::string &varname_u1,
184 const std::string &varname_u2,
const std::string &multname_n,
185 const std::string &dataname_r,
219 (model &md,
const mesh_im &mim,
const std::string &varname_u1,
220 const std::string &varname_u2,
const std::string &multname,
221 const std::string &dataname_r,
const std::string &dataname_friction_coeffs,
223 const std::string &dataname_alpha =
"",
224 const std::string &dataname_wt1 =
"",
225 const std::string &dataname_wt2 =
"");
241 (model &md,
const mesh_im &mim,
const std::string &varname_u1,
242 const std::string &varname_u2,
const std::string &dataname_r,
244 int option = 1,
const std::string &dataname_lambda_n =
"");
270 (model &md,
const mesh_im &mim,
const std::string &varname_u1,
271 const std::string &varname_u2,
const std::string &dataname_r,
272 const std::string &dataname_friction_coeffs,
274 const std::string &dataname_lambda =
"",
275 const std::string &dataname_alpha =
"",
276 const std::string &dataname_wt1 =
"",
277 const std::string &dataname_wt2 =
"");
280 enum contact_nonlinear_term_version { RHS_L_V1,
305 UZAWA_PROJ_FRICT_SAXCE,
327 class contact_nonlinear_term :
public nonlinear_elem_term {
333 base_small_vector lnt, lt;
335 base_small_vector zt;
338 base_small_vector no;
343 scalar_type tresca_lim;
347 base_small_vector aux1, auxN, V;
350 void adjust_tensor_size(
void);
359 bgeot::multi_index sizes_;
361 contact_nonlinear_term(dim_type N_,
size_type option_, scalar_type r_,
362 bool contact_only_ =
true,
363 scalar_type alpha_ = scalar_type(1)) :
364 tau_adh(0), tresca_lim(gmm::default_max(scalar_type())),
365 N(N_), option(option_), r(r_), contact_only(contact_only_),
alpha(alpha_) {
367 adjust_tensor_size();
370 const bgeot::multi_index &sizes(
size_type)
const {
return sizes_; }
372 virtual void friction_law(scalar_type p, scalar_type &tau);
373 virtual void friction_law(scalar_type p, scalar_type &tau, scalar_type &tau_grad);
375 virtual void compute(fem_interpolation_context&, bgeot::base_tensor &t);
376 virtual void prepare(fem_interpolation_context& ,
size_type )
377 { GMM_ASSERT1(
false,
"the prepare method has to be reimplemented in "
378 "a derived class"); }
383 class contact_rigid_obstacle_nonlinear_term :
public contact_nonlinear_term {
386 base_small_vector vt;
392 const mesh_fem &mf_u;
393 const mesh_fem &mf_obs;
394 const mesh_fem *pmf_lambda;
395 const mesh_fem *pmf_coeff;
396 base_vector U, obs, lambda, friction_coeff, tau_adhesion, tresca_limit, WT, VT;
399 template <
typename VECT1>
400 contact_rigid_obstacle_nonlinear_term
402 const mesh_fem &mf_u_,
const VECT1 &U_,
403 const mesh_fem &mf_obs_,
const VECT1 &obs_,
404 const mesh_fem *pmf_lambda_ = 0,
const VECT1 *lambda_ = 0,
405 const mesh_fem *pmf_coeff_ = 0,
const VECT1 *f_coeffs_ = 0,
406 scalar_type alpha_ = scalar_type(1),
const VECT1 *WT_ = 0,
407 scalar_type gamma_ = scalar_type(1),
const VECT1 *VT_ = 0
409 : contact_nonlinear_term(mf_u_.linked_mesh().dim(), option_, r_,
410 (f_coeffs_ == 0), alpha_
412 mf_u(mf_u_), mf_obs(mf_obs_),
413 pmf_lambda(pmf_lambda_), pmf_coeff(pmf_coeff_),
414 U(mf_u.nb_basic_dof()), obs(mf_obs.nb_basic_dof()),
415 lambda(0), friction_coeff(0), tau_adhesion(0), tresca_limit(0),
416 WT(0), VT(0), gamma(gamma_)
419 mf_u.extend_vector(U_, U);
420 mf_obs.extend_vector(obs_, obs);
423 lambda.resize(pmf_lambda->nb_basic_dof());
424 pmf_lambda->extend_vector(*lambda_, lambda);
429 f_coeff = (*f_coeffs_)[0];
430 if (gmm::vect_size(*f_coeffs_) > 1) tau_adh = (*f_coeffs_)[1];
431 if (gmm::vect_size(*f_coeffs_) > 2) tresca_lim = (*f_coeffs_)[2];
434 size_type ncoeffs = gmm::vect_size(*f_coeffs_)/pmf_coeff->nb_dof();
435 GMM_ASSERT1(ncoeffs >= 1 && ncoeffs <= 3,
"Wrong vector dimension for friction coefficients");
436 gmm::resize(friction_coeff, pmf_coeff->nb_basic_dof());
437 pmf_coeff->extend_vector(gmm::sub_vector(*f_coeffs_, gmm::sub_slice(0,pmf_coeff->nb_dof(),ncoeffs)),
440 gmm::resize(tau_adhesion, pmf_coeff->nb_basic_dof());
441 pmf_coeff->extend_vector(gmm::sub_vector(*f_coeffs_, gmm::sub_slice(1,pmf_coeff->nb_dof(),ncoeffs)),
445 gmm::resize(tresca_limit, pmf_coeff->nb_basic_dof());
446 pmf_coeff->extend_vector(gmm::sub_vector(*f_coeffs_, gmm::sub_slice(2,pmf_coeff->nb_dof(),ncoeffs)),
451 if (WT_ && gmm::vect_size(*WT_)) {
452 WT.resize(mf_u.nb_basic_dof());
453 mf_u.extend_vector(*WT_, WT);
456 if (VT_ && gmm::vect_size(*VT_)) {
457 VT.resize(mf_u.nb_basic_dof());
458 mf_u.extend_vector(*VT_, VT);
465 GMM_ASSERT1(mf_u.get_qdim() == N,
"wrong qdim for the mesh_fem");
470 virtual void prepare(fem_interpolation_context& ctx,
size_type nb);
475 class contact_nonmatching_meshes_nonlinear_term :
public contact_nonlinear_term {
482 const mesh_fem &mf_u1;
483 const mesh_fem &mf_u2;
484 const mesh_fem *pmf_lambda;
485 const mesh_fem *pmf_coeff;
486 base_vector U1, U2, lambda, friction_coeff, tau_adhesion, tresca_limit, WT1, WT2;
488 template <
typename VECT1>
489 contact_nonmatching_meshes_nonlinear_term
491 const mesh_fem &mf_u1_,
const VECT1 &U1_,
492 const mesh_fem &mf_u2_,
const VECT1 &U2_,
493 const mesh_fem *pmf_lambda_ = 0,
const VECT1 *lambda_ = 0,
494 const mesh_fem *pmf_coeff_ = 0,
const VECT1 *f_coeffs_ = 0,
495 scalar_type alpha_ = scalar_type(1),
496 const VECT1 *WT1_ = 0,
const VECT1 *WT2_ = 0
498 : contact_nonlinear_term(mf_u1_.linked_mesh().dim(), option_, r_,
499 (f_coeffs_ == 0), alpha_
501 mf_u1(mf_u1_), mf_u2(mf_u2_),
502 pmf_lambda(pmf_lambda_), pmf_coeff(pmf_coeff_),
503 U1(mf_u1.nb_basic_dof()), U2(mf_u2.nb_basic_dof()),
504 lambda(0), friction_coeff(0), tau_adhesion(0), tresca_limit(0),
508 GMM_ASSERT1(mf_u2.linked_mesh().dim() == N,
509 "incompatible mesh dimensions for the given mesh_fem's");
511 mf_u1.extend_vector(U1_, U1);
512 mf_u2.extend_vector(U2_, U2);
515 lambda.resize(pmf_lambda->nb_basic_dof());
516 pmf_lambda->extend_vector(*lambda_, lambda);
521 f_coeff = (*f_coeffs_)[0];
522 if (gmm::vect_size(*f_coeffs_) > 1) tau_adh = (*f_coeffs_)[1];
523 if (gmm::vect_size(*f_coeffs_) > 2) tresca_lim = (*f_coeffs_)[2];
526 size_type ncoeffs = gmm::vect_size(*f_coeffs_)/pmf_coeff->nb_dof();
527 GMM_ASSERT1(ncoeffs >= 1 && ncoeffs <= 3,
"Wrong vector dimension for friction coefficients");
528 gmm::resize(friction_coeff, pmf_coeff->nb_basic_dof());
529 pmf_coeff->extend_vector(gmm::sub_vector(*f_coeffs_, gmm::sub_slice(0,pmf_coeff->nb_dof(),ncoeffs)),
532 gmm::resize(tau_adhesion, pmf_coeff->nb_basic_dof());
533 pmf_coeff->extend_vector(gmm::sub_vector(*f_coeffs_, gmm::sub_slice(1,pmf_coeff->nb_dof(),ncoeffs)),
537 gmm::resize(tresca_limit, pmf_coeff->nb_basic_dof());
538 pmf_coeff->extend_vector(gmm::sub_vector(*f_coeffs_, gmm::sub_slice(2,pmf_coeff->nb_dof(),ncoeffs)),
542 if (WT1_ && WT2_ && gmm::vect_size(*WT1_) && gmm::vect_size(*WT2_)) {
543 WT1.resize(mf_u1.nb_basic_dof());
544 mf_u1.extend_vector(*WT1_, WT1);
545 WT2.resize(mf_u2.nb_basic_dof());
546 mf_u2.extend_vector(*WT2_, WT2);
552 GMM_ASSERT1(mf_u1.get_qdim() == N,
"wrong qdim for the 1st mesh_fem");
553 GMM_ASSERT1(mf_u2.get_qdim() == N,
"wrong qdim for the 2nd mesh_fem");
558 virtual void prepare(fem_interpolation_context& ctx,
size_type nb);
566 template<
typename VECT1>
573 scalar_type r, scalar_type alpha,
const mesh_region &rg,
int option = 1) {
575 contact_rigid_obstacle_nonlinear_term
576 nterm1((option == 1) ? UZAWA_PROJ_FRICT : UZAWA_PROJ_FRICT_SAXCE, r,
577 mf_u, U, mf_obs, obs, &mf_lambda, &lambda,
578 pmf_coeff, &f_coeff, alpha, WT);
582 assem.set(
"V(#3)+=comp(NonLin$1(#1,#1,#2,#3,#4).vBase(#3))(i,:,i); ");
584 assem.set(
"V(#3)+=comp(NonLin$1(#1,#1,#2,#3).vBase(#3))(i,:,i); ");
599 template<
typename VECT1>
607 contact_rigid_obstacle_nonlinear_term
608 nterm1(UZAWA_PROJ, r, mf_u, U, mf_obs, obs, &mf_lambda, &lambda);
611 assem.set(
"V(#3)+=comp(NonLin$1(#1,#1,#2,#3).Base(#3))(i,:); ");
625 template<
typename VEC>
633 bool contact_only = (mf_lambda.
get_qdim() == 1);
636 gmm::resize(U, mf_u.
nb_dof());
637 scalar_type dummy_r(0.);
638 VEC dummy_f_coeff; gmm::resize(dummy_f_coeff,1);
639 contact_rigid_obstacle_nonlinear_term
640 nterm(RHS_U_V1, dummy_r, mf_u, U, mf_obs, obs, &mf_lambda, &lambda,
641 0, contact_only ? 0 : &dummy_f_coeff);
644 assem.set(
"V(#1)+=comp(NonLin$1(#1,#1,#2,#3).vBase(#1))(i,:,i); ");
654 template<
typename VEC>
655 scalar_type asm_level_set_contact_area
659 const mesh_region &rg, scalar_type threshold_factor=0.0,
661 scalar_type threshold_pressure_factor=0.0) {
663 if (!rg.get_parent_mesh())
664 rg.from_mesh(mim.linked_mesh());
666 mf_ca.set_classical_finite_element(rg.index(),1);
668 VEC mesh_size(mf_ca.nb_dof());
669 VEC mesh_size2(mf_ca.nb_dof());
672 assem_mesh_size.set(
"V(#1)+=comp(Base(#1))");
674 assem_mesh_size.
push_mf(mf_ca);
675 assem_mesh_size.
push_vec(mesh_size2);
677 for (dal::bv_visitor_c dof(mf_ca.basic_dof_on_region(rg));
678 !dof.finished(); ++dof)
679 mesh_size[dof] = sqrt(mesh_size2[dof]);
682 VEC threshold(mf_ca.nb_dof());
683 if (mf_lambda && lambda) {
684 VEC pressure(mf_ca.nb_dof());
685 VEC dummy_f_coeff(1);
686 bool contact_only = (mf_lambda->
get_qdim() == 1);
687 contact_rigid_obstacle_nonlinear_term
688 nterm_pressure(CONTACT_PRESSURE, 0., mf_u, U, mf_obs, obs,
689 mf_lambda, lambda, 0, contact_only ? 0 : &dummy_f_coeff);
692 assem_pressure.set(
"V(#4)+=comp(NonLin(#1,#1,#2,#3).Base(#4))(i,:)");
695 assem_pressure.
push_mf(mf_obs);
696 assem_pressure.
push_mf(*mf_lambda);
701 for (dal::bv_visitor_c dof(mf_ca.basic_dof_on_region(rg));
702 !dof.finished(); ++dof)
703 pressure[dof] /= mesh_size2[dof];
707 scalar_type threshold_pressure(threshold_pressure_factor *
708 gmm::vect_norminf(pressure));
709 gmm::copy(gmm::scaled(mesh_size, scalar_type(-1)), threshold);
711 size_type nbdof = mf_ca.nb_basic_dof_of_face_of_element(v.cv(), v.f());
712 mesh_fem::ind_dof_face_ct::const_iterator
713 itdof = mf_ca.ind_basic_dof_of_face_of_element(v.cv(), v.f()).begin();
714 bool all_positive =
true;
715 for (
size_type k=0; k < nbdof; ++k, ++itdof)
716 if (pressure[*itdof] < threshold_pressure) { all_positive =
false;
break; }
718 itdof = mf_ca.ind_basic_dof_of_face_of_element(v.cv(), v.f()).begin();
719 for (
size_type k=0; k < nbdof; ++k, ++itdof)
720 threshold[*itdof] = threshold_factor * mesh_size[*itdof];
725 gmm::copy(gmm::scaled(mesh_size, threshold_factor), threshold);
729 contact_rigid_obstacle_nonlinear_term
730 nterm(CONTACT_FLAG, 0., mf_u, U, mf_obs, obs, &mf_ca, &threshold);
733 assem.set(
"V()+=comp(NonLin(#1,#1,#2,#3))(i)");
739 std::vector<scalar_type> v(1);
746 template<
typename VEC>
747 void asm_nonmatching_meshes_normal_source_term
748 (VEC &R,
const mesh_im &mim,
752 const mesh_region &rg) {
754 bool contact_only = (mf_lambda.
get_qdim() == 1);
759 scalar_type dummy_r(0);
761 contact_nonmatching_meshes_nonlinear_term
762 nterm(RHS_U_V1, dummy_r, mf_u1, U1, mf_u2_proj, U2_proj, &mf_lambda, &lambda,
763 0, contact_only ? 0 : &dummy_f_coeff);
766 assem.set(
"V(#1)+=comp(NonLin(#1,#1,#2,#3).vBase(#1))(i,:,i)");
776 template<
typename VEC>
777 scalar_type asm_nonmatching_meshes_contact_area
781 const mesh_region &rg, scalar_type threshold_factor=0.0,
783 scalar_type threshold_pressure_factor=0.0) {
785 if (!rg.get_parent_mesh())
786 rg.from_mesh(mim.linked_mesh());
788 mf_ca.set_classical_finite_element(rg.index(),1);
790 VEC mesh_size(mf_ca.nb_dof());
791 VEC mesh_size2(mf_ca.nb_dof());
794 assem_mesh_size.set(
"V(#1)+=comp(Base(#1))");
796 assem_mesh_size.
push_mf(mf_ca);
797 assem_mesh_size.
push_vec(mesh_size2);
799 for (dal::bv_visitor_c dof(mf_ca.basic_dof_on_region(rg));
800 !dof.finished(); ++dof)
801 mesh_size[dof] = sqrt(mesh_size2[dof]);
804 VEC threshold(mf_ca.nb_dof());
805 if (mf_lambda && lambda) {
806 VEC pressure(mf_ca.nb_dof());
807 VEC dummy_f_coeff(1);
808 bool contact_only = (mf_lambda->
get_qdim() == 1);
809 contact_nonmatching_meshes_nonlinear_term
810 nterm_pressure(CONTACT_PRESSURE, 0., mf_u1, U1, mf_u2_proj, U2_proj,
811 mf_lambda, lambda, 0, contact_only ? 0 : &dummy_f_coeff);
814 assem_pressure.set(
"V(#4)+=comp(NonLin(#1,#1,#2,#3).Base(#4))(i,:)");
817 assem_pressure.
push_mf(mf_u2_proj);
818 assem_pressure.
push_mf(*mf_lambda);
823 for (dal::bv_visitor_c dof(mf_ca.basic_dof_on_region(rg));
824 !dof.finished(); ++dof)
825 pressure[dof] /= mesh_size2[dof];
829 scalar_type threshold_pressure(threshold_pressure_factor *
830 gmm::vect_norminf(pressure));
831 gmm::copy(gmm::scaled(mesh_size, scalar_type(-1)), threshold);
833 size_type nbdof = mf_ca.nb_basic_dof_of_face_of_element(v.cv(), v.f());
834 mesh_fem::ind_dof_face_ct::const_iterator
835 itdof = mf_ca.ind_basic_dof_of_face_of_element(v.cv(), v.f()).begin();
836 bool all_positive =
true;
837 for (
size_type k=0; k < nbdof; ++k, ++itdof)
838 if (pressure[*itdof] < threshold_pressure) { all_positive =
false;
break; }
840 itdof = mf_ca.ind_basic_dof_of_face_of_element(v.cv(), v.f()).begin();
841 for (
size_type k=0; k < nbdof; ++k, ++itdof)
842 threshold[*itdof] = threshold_factor * mesh_size[*itdof];
847 gmm::copy(gmm::scaled(mesh_size, threshold_factor), threshold);
852 contact_nonmatching_meshes_nonlinear_term
853 nterm(CONTACT_FLAG, 0., mf_u1, U1, mf_u2_proj, U2_proj, &mf_ca, &threshold);
856 assem.set(
"V()+=comp(NonLin(#1,#1,#2,#3))(i)");
862 std::vector<scalar_type> v(1);
869 void compute_integral_contact_area_and_force
871 scalar_type &area, model_real_plain_vector &Forces);
897 (model &md,
const mesh_im &mim,
const std::string &varname_u,
898 const std::string &Neumannterm,
899 const std::string &expr_obs,
const std::string &dataname_gamma0,
901 std::string dataexpr_friction_coeff,
902 const std::string &dataname_alpha,
903 const std::string &dataname_wt,
906 #ifdef EXPERIMENTAL_PURPOSE_ONLY
925 size_type add_Nitsche_contact_with_rigid_obstacle_brick_modified_midpoint
926 (model &md,
const mesh_im &mim,
const std::string &varname_u,
927 const std::string &Neumannterm,
const std::string &Neumannterm_wt,
928 const std::string &obs,
const std::string &dataname_gamma0,
930 std::string dataname_friction_coeff,
931 const std::string &dataname_alpha,
932 const std::string &dataname_wt,
963 (model &md,
const mesh_im &mim,
const std::string &varname_u1,
964 const std::string &varname_u2,
const std::string &dataname_d1,
965 const std::string &dataname_d2,
const std::string &dataname_gamma0,
967 const std::string &dataname_friction_coeff,
968 const std::string &dataname_alpha,
969 const std::string &dataname_wt1,
const std::string &dataname_wt2);