31 level_set_contact::contact_body::contact_body(model& _md, std::string _var_name):
34 own_mesh(const_cast<mesh&>(_md.mesh_fem_of_variable(_var_name).
36 own_mesh_fem(_md.mesh_fem_of_variable(_var_name)),
45 ls_name(
"ls_on_"+_var_name),
46 ls_mesh_fem(_md.mesh_fem_of_variable(_var_name)),
51 model_real_plain_vector LS(ls_mesh_fem.
nb_dof());
59 getfem::model& _md, std::string _var_name, std::string _ls_name):
67 for(
size_type i=0;i<ls_values().size();i++)
73 const std::string& _var_name,
78 mult_mim_order(_mult_mim_order),
80 mult_mf_order(_mult_order),
81 integration(PER_ELEMENT),
82 regularized_tollerance(0),
83 small_weight_multiplier(0),
89 get_mesh().
region(VOLUME_ELEMENTS).add(get_mesh().convex_index());
94 get_mesh().
region(BOUNDARY_ELEMENTS).clear();
96 masters.push_back(
this);
101 const std::string& _var_name,
103 const std::string& _mult_mim_method,
104 contact_integration _integration,
105 scalar_type _regularized_tollerance,
106 scalar_type _small_weight_multiplier,
107 scalar_type _max_contact_angle):
111 mult_int_method(_mult_mim_method),
112 mult_mf_order(_mult_order),
113 integration(_integration),
114 regularized_tollerance(_regularized_tollerance),
115 small_weight_multiplier(_small_weight_multiplier),
116 max_contact_angle(_max_contact_angle)
121 get_mesh().
region(VOLUME_ELEMENTS).add(get_mesh().convex_index());
126 get_mesh().
region(BOUNDARY_ELEMENTS).clear();
127 masters.push_back(
this);
133 const std::string& slave_var_name)
const
135 auto it = contact_table.find(slave_var_name);
136 if (it!=contact_table.end())
return *(it->second);
137 GMM_ASSERT1(
false,
"did not find info on slave contact body, \
138 defined on variable "+slave_var_name);
143 const std::string& slave_var_name)
145 auto it = contact_table.find(slave_var_name);
146 if (it!=contact_table.end())
return *(it->second);
147 GMM_ASSERT1(
false,
"did not find info on slave contact body, \
148 defined on variable "+slave_var_name);
155 auto it = border_faces.find(i);
156 if (it!=border_faces.end())
return it->second;
157 GMM_ASSERT1(
false,
"did not find a face, corresponding to element "<<i);
165 GMM_ASSERT1(&md==&scb.get_model(),
166 "Model objects of master and slave are not the same");
167 if (assumed_contact_region!=
size_type(-1))
168 GMM_ASSERT1(get_mesh().region(assumed_contact_region).is_boundary(),
169 "Assumed_contact_region must be on the boundary");
175 std::shared_ptr<getfem::mr_visitor> i;
180 if (assumed_contact_region==
size_type(-1)){
181 i = std::make_shared<getfem::mr_visitor>(outer_faces);
186 region(assumed_contact_region);
187 i = std::make_shared<getfem::mr_visitor>(assumed_region);
190 for (; !i->finished(); ++(*i)){
192 get_mesh().add_convex(
194 get_mesh().trans_of_convex(i->cv())),
195 get_mesh().ind_points_of_face_of_convex(
196 i->cv(), i->f()).begin());
199 border_faces[new_elem] = face_type(*i);
200 contact_elems.add(new_elem);
201 boundary_elems.add(new_elem);
204 GMM_ASSERT1(get_mesh().region(BOUNDARY_ELEMENTS).index().card()!=0,
205 "No boundary elements added !!!");
207 GMM_ASSERT1(get_mesh().region(assumed_contact_elems).index().card()!=0,
208 "No contact elements added !!!");
211 std::string mult_name = md.new_name(
"mult_on_"+get_var_name()+
212 "_and_"+scb.get_var_name());
215 bgeot::dim_type(mult_mf_order), bgeot::dim_type(1));
216 md.add_multiplier(mult_name,mf_mult,get_var_name());
221 plain_vector LS(mf_ls.
nb_dof());
222 md.add_initialized_fem_data(
"ls_on"+get_var_name()+
223 "_from_"+scb.get_var_name(),mf_ls,LS);
226 contact_table[scb.get_var_name()] =
227 std::make_shared<contact_pair_info>(*
this,scb,mult_name,assumed_contact_elems);
231 std::vector<level_set_contact::master_contact_body*>
232 level_set_contact::master_contact_body::masters;
237 if (masters.size()==0) GMM_WARNING3(
"Running contact detection, while no \
238 contact bodies are registered");
239 bool contact_surfaces_changed =
false;
241 if (masters[i]->master_contact_changed())
242 contact_surfaces_changed=
true;
244 return contact_surfaces_changed;
249 if (masters.size()==0) GMM_WARNING3(
"Clearing contact lists, while no \
250 contact bodies are registered");
252 masters[i]->clear_contact_history();
257 std::map<std::string, std::shared_ptr<contact_pair_info> >::
258 iterator it = contact_table.begin();
259 for(;it!=contact_table.end();it++)
260 it->second->clear_contact_history();
265 bool contact_surfaces_changed =
false;
266 std::map<std::string, std::shared_ptr<contact_pair_info> >::
267 iterator it = contact_table.begin();
268 for(;it!=contact_table.end();it++)
269 if (it->second->contact_changed())
270 contact_surfaces_changed=
true;
272 return contact_surfaces_changed;
279 std::shared_ptr<getfem::mesh_im> pmim_contact;
281 pmim_contact = std::make_shared<mesh_im>(get_mesh());
283 pmim_contact->set_integration_method
284 (get_mesh().region(region_id).index(),
285 bgeot::dim_type(contact_mim_order()));
289 pmim_contact->set_integration_method
290 (get_mesh().region(region_id).index(), contact_int_method());
297 level_set_contact::contact_pair_update::contact_pair_update(
305 GMM_ASSERT1(!mcb.is_mesh_deformed(),
"Trying to deform \
306 already deformed Master Contact Body");
307 GMM_ASSERT1(!scb.is_mesh_deformed(),
"Trying to deform \
308 already deformed Slave Contact Body");
310 const model_real_plain_vector&
311 Umaster=mcb.get_model().real_variable(mcb.get_var_name());
314 def_master = std::make_shared<getfem::temporary_mesh_deformator<>>
315 (mcb.get_mesh_fem(),Umaster);
316 mcb.is_deformed=
true;
317 if (&mcb.get_mesh()!=&scb.get_mesh()){
319 const model_real_plain_vector&
320 Uslave=scb.get_model().real_variable(scb.get_var_name());
321 def_slave = std::make_shared<getfem::temporary_mesh_deformator<>>
322 (scb.get_mesh_fem(),Uslave);
323 scb.is_deformed=
true;
325 if (ud == FULL_UPDATE) mcb.update_for_slave(scb.get_var_name());
328 level_set_contact::contact_pair_update::~contact_pair_update(){
329 mcb.is_deformed=
false;
330 scb.is_deformed=
false;
335 level_set_contact::contact_pair_info::contact_pair_info(
336 master_contact_body& underformed_mcb,
337 slave_contact_body& underformed_scb,
338 const std::string& _mult_name,
341 master_cb(underformed_mcb),
342 slave_cb(underformed_scb),
343 mult_name(_mult_name),
344 GIVEN_CONTACT_REGION(_GIVEN_CONTACT_REGION),
346 ACTIVE_CONTACT_REGION(
getfem::mesh_region::free_region_id(master_cb.get_mesh())),
347 members_are_computed(false),
348 init_cont_detect_done(false)
354 GMM_ASSERT1(master_cb.get_mesh().
355 region(GIVEN_CONTACT_REGION).index().card()!=0,
356 "provided contact region for contact_pair_info class is empty!!!");
361 old_contact_elm_list.clear();
362 pre_old_ct_list.clear();
369 temp_mesh_deformation(master_cb,slave_cb,DEFORM_MESHES_ONLY);
372 mesh_fem mf_scalar(master_cb.get_mesh());
381 model_real_plain_vector LS_on_contour(mf_boundary.
nb_dof());
383 slave_cb.ls_values(), LS_on_contour);
384 model_real_plain_vector LS(mf_scalar.
nb_dof());
385 mf_boundary.extend_vector(LS_on_contour,LS);
386 gmm::copy(LS,master_cb.get_model().set_real_variable
387 (
"ls_on"+master_cb.get_var_name()+
"_from_"+slave_cb.get_var_name()));
391 mesh_fem mf_gradient_ls(slave_cb.get_mesh());
393 mesh_fem mf_gradient_ls_vect(mf_gradient_ls);
394 mf_gradient_ls_vect.
set_qdim(slave_cb.get_mesh().dim());
395 plain_vector GradLS(mf_gradient_ls.
nb_dof()*slave_cb.get_mesh().dim());
398 mf_boundary_vect.
adapt(master_cb.get_mesh_fem().dof_on_region(GIVEN_CONTACT_REGION));
399 plain_vector GradLS_boundary(mf_boundary.
nb_dof()*slave_cb.get_mesh().dim());
402 size_type dim = slave_cb.get_mesh().dim();
403 const scalar_type TINY = 1e-15;
406 for(
size_type j=0;j<dim;j++) ls_node[j]=GradLS_boundary[dim*i+j];
407 ls_node/= (gmm::vect_norm2(ls_node)+TINY);
408 for(
size_type j=0;j<dim;j++) GradLS_boundary[dim*i+j]=ls_node[j];
410 plain_vector normLS_master(master_cb.get_mesh_fem().nb_dof());
411 mf_boundary_vect.extend_vector(GradLS_boundary,normLS_master);
416 master_cb.get_model().mesh_fem_of_variable(mult_name);
417 const model_real_plain_vector& lambda =
418 master_cb.get_model().real_variable(mult_name);
419 model_real_plain_vector lambda_full(mf_mult.
nb_basic_dof());
420 if (lambda.size()>0) mf_mult.extend_vector(lambda,lambda_full);
422 dal::bit_vector cc = master_cb.get_mesh().
423 region(GIVEN_CONTACT_REGION).index();
424 master_cb.get_mesh().region(ACTIVE_CONTACT_REGION).clear();
425 master_cb.get_mesh().region(ACTIVE_CONTACT_REGION).add(cc);
432 face_type face = master_cb.ext_face_of_elem(o);
434 master_cb.get_mesh().normal_of_face_of_convex(face.cv,face.f);
435 unit_face_normal/=gmm::vect_norm2(unit_face_normal);
436 scalar_type cosine_alpha = 0;
437 for (
size_type j = 0; j < dof_ls.size(); j++){
440 ls_grad_node[k]=normLS_master[dim*dof_ls[j]+k];
441 cosine_alpha += gmm::vect_sp(ls_grad_node,unit_face_normal);
443 cosine_alpha /= scalar_type(dof_ls.size());
444 scalar_type alpha = acos(cosine_alpha)*360/(2*M_PI);
447 scalar_type LS_extreeme = LS[dof_ls[0]];
448 if (master_cb.integration==master_contact_body::PER_ELEMENT)
449 for (
size_type j = 0; j < dof_ls.size(); j++)
450 LS_extreeme=std::min(LS[dof_ls[j]],LS_extreeme);
452 for (
size_type j = 0; j < dof_ls.size(); j++)
453 LS_extreeme=std::max(LS[dof_ls[j]],LS_extreeme);
455 scalar_type LM_sum = 0;
456 for (
size_type j = 0; j < dof_lm.size(); j++)
457 LM_sum+=lambda_full[dof_lm[j]];
459 const scalar_type TINY_2 = 1e-9;
461 if (LS_extreeme+LM_sum < TINY_2 || alpha > master_cb.max_contact_angle)
462 master_cb.get_mesh().region(ACTIVE_CONTACT_REGION).sup(o);
466 bool contact_surface_changed;
467 const dal::bit_vector& current_contact_elm_list =
468 master_cb.get_mesh().region(ACTIVE_CONTACT_REGION).index();
469 GMM_TRACE2(
"Current contact elements: "<< current_contact_elm_list);
470 GMM_TRACE2(
"Old contact elements: "<< old_contact_elm_list);
471 GMM_TRACE2(
"Pre-old contact elements: "<< pre_old_ct_list);
473 if (current_contact_elm_list == old_contact_elm_list &&
474 current_contact_elm_list.card() == old_contact_elm_list.card()) {
475 contact_surface_changed =
false;
476 GMM_TRACE2(
" the contact area has not changed");
478 if (current_contact_elm_list == pre_old_ct_list &&
479 current_contact_elm_list.card() == pre_old_ct_list.card()) {
480 contact_surface_changed =
false;
481 GMM_TRACE2(
" the contact area has changed, but cycling, \
482 so exiting active set search");
484 contact_surface_changed =
true;
485 GMM_TRACE2(
" the contact area has changed");
486 pre_old_ct_list = old_contact_elm_list;
487 old_contact_elm_list = current_contact_elm_list;
491 init_cont_detect_done =
true;
496 pmim_contact = master_cb.build_mesh_im_on_boundary(ACTIVE_CONTACT_REGION);
497 n_integrated_elems = pmim_contact->convex_index().card();
498 GMM_ASSERT1(n_integrated_elems==current_contact_elm_list.card(),
499 "Failure in integration method: The number of integrated elements "
500 "does not correspond to the number of contact elements");
502 return contact_surface_changed;
510 GMM_ASSERT1(master_cb.is_mesh_deformed(),
"Master mesh is not deformed, \
511 cannot calucalte contact info");
513 GMM_ASSERT1(slave_cb.is_mesh_deformed(),
"Slave mesh is not deformed, \
514 cannot calucalte contact info");
516 GMM_ASSERT1(master_cb.get_mesh().region(ACTIVE_CONTACT_REGION).index().card()>0,
517 "Internal error: Contact area is empty");
520 pinterpolated_fem = std::make_shared<mesh_fem>(master_cb.get_mesh());
522 pinterpolated_fem_U = std::shared_ptr<mesh_fem>();
527 *pmim_contact, 0, dal::bit_vector(),
false);
528 pinterpolated_fem->set_finite_element(
529 master_cb.get_mesh().region(ACTIVE_CONTACT_REGION).index(),ifem_srf);
530 pinterpolated_fem->set_qdim(1);
534 pinterpolated_fem_U = std::make_shared<mesh_fem>(master_cb.get_mesh());
535 pinterpolated_fem_U->set_finite_element(master_cb.get_mesh().
536 region(ACTIVE_CONTACT_REGION).index(),ifem_srf);
537 pinterpolated_fem_U->set_qdim(master_cb.get_mesh().dim());
540 std::vector<size_type> index(pinterpolated_fem->nb_dof());
542 master_cb.get_mesh().region(ACTIVE_CONTACT_REGION).index();
543 for (dal::bv_visitor icv(cc); !icv.finished(); ++icv){
544 for (
size_type j = 0; j < pinterpolated_fem->nb_basic_dof_of_element(icv);
546 {index[pinterpolated_fem->ind_basic_dof_of_element(icv)[j]]
547 = ifem_srf->index_of_global_dof(icv, j);}
550 slave_ls_dofs = std::make_shared<gmm::unsorted_sub_index>(index);
553 std::vector<size_type> indexU(pinterpolated_fem_U->nb_dof());
554 size_type dim = pinterpolated_fem_U->get_qdim();
556 for(
size_type i=0;i<pinterpolated_fem->nb_dof();i++)
557 indexU[dim*i+d] = dim*index[i]+d;
558 slave_U_dofs = std::make_shared<gmm::unsorted_sub_index>(indexU);
560 members_are_computed=
true;
571 getfem::pbrick pbr = std::make_shared<level_set_contact_brick>(md,mcb,scb,rg);
574 const std::string& name_Um = mcb.get_var_name();
575 const std::string& name_Us = scb.get_var_name();
576 const std::string& name_LM = mcb.
get_pair_info(name_Us).get_mult_name();
577 model::termlist terms;
578 terms.push_back(model::term_description(name_Um,name_Um,
false));
579 terms.push_back(model::term_description(name_Us,name_Us,
false));
580 terms.push_back(model::term_description(name_LM,name_LM,
false));
581 terms.push_back(model::term_description(name_Um,name_Us,
true));
582 terms.push_back(model::term_description(name_Um,name_LM,
true));
583 terms.push_back(model::term_description(name_Us,name_LM,
true));
586 model::varnamelist variables;
587 variables.push_back(name_Um);
588 variables.push_back(name_Us);
589 variables.push_back(name_LM);
594 model::varnamelist datalist;
595 model::mimlist mimlist;
598 return md.
add_brick(pbr,variables,datalist,terms,mimlist,rg);
602 level_set_contact::level_set_contact_brick::
603 level_set_contact_brick(
605 master_contact_body& _mcb,
606 slave_contact_body& _scb,
608 md(_md),mcb(_mcb),scb(_scb), given_contact_id(rg)
610 GMM_ASSERT1(&md == &mcb.get_model(),
611 "Master body is defined on a different model then the input");
614 mcb.add_slave(scb,given_contact_id);
617 contact_region_id = mcb.get_pair_info(scb.get_var_name()).contact_region();
619 mcb.get_mesh().intersect_with_mpi_region(contact_region_);
620 contact_region_id = contact_region_.id();
623 set_flags(
"Level set contact brick",
634 const model::varnamelist &vl,
635 const model::varnamelist &,
636 const model::mimlist &,
637 model::real_matlist &matl,
638 model::real_veclist &vecl,
639 model::real_veclist &,
641 build_version version)
const {
643 GMM_ASSERT1(vl.size() == 3,
644 "Level set contact brick needs three variables");
645 GMM_ASSERT1(matl.size() == 6,
646 "Level set contact brick needs six matrices");
647 GMM_ASSERT1(vecl.size() == 6,
648 "Level set contact brick assembles size RHSs");
649 GMM_ASSERT1(region==given_contact_id,
650 "Assumed contact region has changed!!! \
651 This implementation does not handle this \
652 for efficiency reasons!!");
654 if (version & model::BUILD_MATRIX )
655 for(
size_type i=0;i<matl.size();i++) gmm::clear(matl[i]);
656 if (version & model::BUILD_RHS )
657 for(
size_type i=0;i<vecl.size();i++) gmm::clear(vecl[i]);
660 mcb.get_mesh().
region(contact_region_id);
661 if (active_contact_region.
index().card()==0)
return;
670 if (version & model::BUILD_MATRIX ) {
671 GMM_TRACE2(
"Level set contact brick stiffness matrix assembly on "
672 << mcb.
get_pair_info(scb.get_var_name()).num_of_integr_elems()
674 asm_level_set_contact_tangent_matrix(matl,mcb,scb,LM,active_contact_region);
678 if (version & model::BUILD_RHS ) {
679 GMM_TRACE2(
"Level set contact brick RHS assembly on "
680 << mcb.
get_pair_info(scb.get_var_name()).num_of_integr_elems()
682 asm_level_set_contact_rhs(vecl,mcb,scb,LM,active_contact_region);
684 gmm::scale(vecl[i], scalar_type(-1));
689 void level_set_contact::NormalTerm::compute(
691 bgeot::base_tensor &t)
694 size_type cv_volume = mcb.ext_face_of_elem(cv).cv;
698 un /= gmm::vect_norm2(un);
701 for (
size_type i = 0; i < dim; i++) t[i] = un[i];
705 if (i == j) t(i, j) = 1.0 - un[i] * un[j];
706 else t(i, j) =-un[i] * un[j];
711 level_set_contact::HFunction::HFunction(
712 const mesh_fem &lsmf_,
713 const plain_vector &LS_U_,
715 scalar_type small_h_):
724 const bgeot::multi_index& level_set_contact::HFunction::
727 void level_set_contact::HFunction::
731 bgeot::base_tensor &t)
738 plain_vector ls_interpolated(1);
739 ctx.
pf()->interpolation(ctx,U,ls_interpolated,1);
740 t[0] = hRegularized(ls_interpolated[0],m_Epsilon,small_h);
743 bgeot::scalar_type level_set_contact::HFunction::
744 hRegularized(scalar_type f, scalar_type epsilon, scalar_type small_h_)
746 if (f>epsilon)
return 1.0;
747 if (f<(-epsilon))
return small_h_;
748 return 0.5+0.125*(9.0*f/(epsilon)-5.0*pow(f/(epsilon),scalar_type(3)));
752 level_set_contact::Unity::Unity(
const mesh_fem &mf_):mf(mf_),sizes_(1)
754 const bgeot::multi_index& level_set_contact::Unity::sizes(
size_type)
const {
return sizes_;}
755 void level_set_contact::Unity::
757 void level_set_contact::Unity::
761 void level_set_contact::
767 const std::string& lsolver_name,
768 getfem::abstract_newton_line_search &ls)
770 bool active_set_converged =
false;
771 it_staggered.set_iteration(0);
776 it_newton.set_iteration(0);
777 getfem::rmodel_plsolver_type plsolver=getfem::select_linear_solver<sparse_matrix,plain_vector>(md,lsolver_name);
778 (*sf)(md,it_newton,plsolver,ls);
779 GMM_TRACE2(
"Newton converged? - "<<it_newton.converged());
780 GMM_TRACE2(
"active set converged? - "<<active_set_converged);
781 GMM_ASSERT1(it_newton.converged(),
"Newton method did not converge");
784 }
while(!active_set_converged &&
785 !it_staggered.finished(it_staggered.get_resmax()+1.0));
787 if (active_set_converged && it_newton.converged()) it_staggered.enforce_converged();
795 std::stringstream fname;
796 fname<<name.substr(0,5);
797 GMM_ASSERT1((fname.str()==
"GT_QK" || fname.str()==
"GT_PK"),
798 "Cannot handle other transformations but QK or PK,\
799 Sorry, to be implemented" );
800 std::stringstream str1(name.substr(6,1));
804 std::istringstream str2(name.substr(8,1));
808 fname<<
"("<<dim-1<<
","<<order<<
")";