46 #ifndef GETFEM_LEVEL_SET_CONTACT_H__
47 #define GETFEM_LEVEL_SET_CONTACT_H__
55 namespace level_set_contact {
62 using getfem::scalar_type;
63 using getfem::model_real_plain_vector;
64 typedef getfem::model_real_plain_vector plain_vector;
65 typedef getfem::model_real_sparse_matrix sparse_matrix;
81 getfem::model_real_plain_vector RHS(mf.
nb_dof());
84 getfem::base_node Pmin(
mesh.dim()),Pmax(
mesh.dim()),range(
mesh.dim());
86 gmm::add(Pmax,gmm::scaled(Pmin,-1.0),range);
87 getfem::scalar_type mesh_size = *(std::max_element(range.begin(),range.end()));
88 gmm::fill(RHS,mesh_size*5.0);
105 GMM_TRACE2(
"building scalar level set with laplace equation..");
113 GMM_TRACE2(
"..done");
120 const std::string var_name;
132 inline std::string get_var_name()
const {
return var_name;}
133 inline mesh& get_mesh() {
return own_mesh;}
134 inline const mesh& get_mesh()
const {
return own_mesh;}
135 inline const mesh_fem& get_mesh_fem()
const {
return own_mesh_fem;}
136 inline const model& get_model()
const {
return md;}
137 inline bool is_mesh_deformed()
const {
return is_deformed;}
158 std::string _ls_name);
159 inline std::string get_ls_name()
const {
return ls_name;}
160 inline const plain_vector& ls_values()
const
162 inline plain_vector& ls_values()
165 template<
class VECTOR>
void set_level_set(
const VECTOR& ls)
182 const std::string mult_name;
186 dal::bit_vector old_contact_elm_list;
187 dal::bit_vector pre_old_ct_list;
189 mutable std::shared_ptr<mesh_im> pmim_contact;
191 mutable std::shared_ptr<mesh_fem> pinterpolated_fem;
192 mutable std::shared_ptr<mesh_fem> pinterpolated_fem_U;
193 mutable std::shared_ptr<gmm::unsorted_sub_index> slave_ls_dofs;
194 mutable std::shared_ptr<gmm::unsorted_sub_index> slave_U_dofs;
198 mutable bool members_are_computed;
199 mutable bool init_cont_detect_done;
203 inline const mesh_fem& slave_scalar_fem()
const {
204 if (dependecies_changed())
update();
205 return *pinterpolated_fem;
207 inline const mesh_fem& slave_vector_fem()
const {
208 if (dependecies_changed())
update();
209 return *pinterpolated_fem_U;
211 inline const gmm::unsorted_sub_index& slave_scalar_dofs()
const {
212 if (dependecies_changed())
update();
213 return *slave_ls_dofs;
215 inline const gmm::unsorted_sub_index& slave_vector_dofs()
const {
216 if (dependecies_changed())
update();
217 return *slave_U_dofs;
219 inline const mesh_im& contact_mesh_im()
const {
220 if (dependecies_changed())
update();
221 return *pmim_contact;
225 {
return ACTIVE_CONTACT_REGION;}
227 inline const std::string& get_mult_name()
const
230 inline size_type num_of_integr_elems()
const {
return n_integrated_elems;}
232 inline bool dependecies_changed()
const
233 {
return !members_are_computed;}
234 inline void force_update()
const
235 {members_are_computed=
false;}
290 const std::string mult_int_method;
291 size_type BOUNDARY_ELEMENTS, VOLUME_ELEMENTS;
292 std::vector<size_type> face_to_belem_ind;
293 static std::vector<master_contact_body*> masters;
294 std::map<std::string, std::shared_ptr<contact_pair_info> > contact_table;
295 std::map<size_type,face_type> border_faces;
307 enum contact_integration{PER_ELEMENT=1,REGULARIZED_LEVEL_SET=2};
339 const std::string& _var_name,
350 const std::string& _var_name,
352 const std::string& _mult_int_method,
353 contact_integration _integration = PER_ELEMENT,
354 scalar_type _regularized_tollerance = 1e-6,
355 scalar_type _small_weight_multiplier = 0.001,
356 scalar_type _max_contact_angle = 45);
367 GMM_ASSERT1(mult_mim_order!=
size_type(-1),
368 "master body was not created with "
369 "order of integration for contact area");
370 return mult_mim_order;
378 GMM_ASSERT1(mult_mim_order==
size_type(-1),
379 "master body was not created with integration "
380 "method for contact area");
386 {
return VOLUME_ELEMENTS;}
391 {
return BOUNDARY_ELEMENTS;}
414 inline void update_for_slave(std::string slave_var_name)
415 { contact_table[slave_var_name]->update(); }
432 enum update_depth{DEFORM_MESHES_ONLY,FULL_UPDATE};
437 std::shared_ptr<getfem::temporary_mesh_deformator<> > def_master;
438 std::shared_ptr<getfem::temporary_mesh_deformator<> > def_slave;
444 update_depth ud = FULL_UPDATE);
489 const model::varnamelist &vl,
490 const model::varnamelist &dl,
491 const model::mimlist &mims,
492 model::real_matlist &matl,
493 model::real_veclist &vecl,
494 model::real_veclist &,
496 build_version version)
const;
513 bgeot::multi_index sizes_;
523 dim(_mcb.get_mesh().dim()) {
525 GMM_ASSERT1(dim==2 || dim==3,
"NormalTerm: wrong space dimension ");
526 GMM_ASSERT1(version==1 || version==2,
"NormalTerm:: wrong version ");
543 const bgeot::multi_index &sizes(
size_type)
const {
return sizes_;};
559 const plain_vector &LS_U;
560 scalar_type m_Epsilon;
562 bgeot::multi_index sizes_;
568 const plain_vector &LS_U_,
569 scalar_type epsilon=1e-9,
570 scalar_type small_h_=0);
571 const bgeot::multi_index &sizes(
size_type)
const;
574 scalar_type hRegularized(scalar_type x, scalar_type epsion, scalar_type small);
582 bgeot::multi_index sizes_;
586 const bgeot::multi_index &sizes(
size_type)
const;
593 template<
typename MAT,
typename VECT>
594 void asm_level_set_contact_tangent_matrix(
595 std::vector<MAT>& matl,
596 const master_contact_body& mcb,
597 const slave_contact_body& scb,
609 const std::string& mult_name =
610 mcb.get_pair_info(scb.get_var_name()).get_mult_name();
611 const std::string ls_name =
"ls_on"+mcb.get_var_name()+
"_from_"+scb.get_var_name();
614 const mesh_fem& mf_U_line = mcb.get_mesh_fem();
615 const mesh_fem& mf_lambda = mcb.get_model().mesh_fem_of_variable(mult_name);
616 const mesh_fem& mf_interpolate =
617 mcb.get_pair_info(scb.get_var_name()).slave_scalar_fem();
618 const mesh_fem& mf_U_interpolate =
619 mcb.get_pair_info(scb.get_var_name()).slave_vector_fem();
620 const mesh_fem& mf_master_ls = mcb.get_model().mesh_fem_of_variable(ls_name);
621 const mesh_im& mim_line =
622 mcb.get_pair_info(scb.get_var_name()).contact_mesh_im();
625 plain_vector LS_small(mf_interpolate.nb_dof());
626 gmm::copy(gmm::sub_vector(scb.ls_values(),
627 mcb.get_pair_info(scb.get_var_name()).slave_scalar_dofs()),LS_small);
630 NormalTerm R_matrix(mcb,2);
633 std::shared_ptr<getfem::nonlinear_elem_term> integration;
634 if (mcb.integration==master_contact_body::REGULARIZED_LEVEL_SET) {
635 integration = std::make_shared<HFunction>
636 (mf_master_ls,mcb.get_model().real_variable(ls_name),
637 mcb.regularized_tollerance,mcb.small_weight_multiplier);
638 }
else { integration = std::make_shared<Unity>(mf_master_ls); }
642 sparse_matrix Kms_small(mf_U_interpolate.nb_dof(), mf_U_line.nb_dof());
643 sparse_matrix Kss_small(mf_U_interpolate.nb_dof(),mf_U_interpolate.nb_dof());
644 sparse_matrix Ksl_small(mf_U_interpolate.nb_dof(),mf_lambda.nb_dof());
652 "Kmm1 = comp(Base(#1).Grad(#3).vBase(#2).NonLin$1(#2).vGrad(#2).NonLin$2(#5))(i,j,k,:,k,m,n,:,n,m,1).L(i).F(j);"
653 "Kmm2 = comp(Base(#1).NonLin$1(#2).vGrad(#2).Grad(#3).vBase(#2).NonLin$2(#5))(i,m,n,:,n,m,j,k,:,k,1).L(i).F(j);"
654 "Kmm3 = comp(Base(#1).Base(#3).NonLin$1(#2).vGrad(#2).NonLin$1(#2).vGrad(#2).NonLin$2(#5))(i,j,k,l,:,l,k,m,n,:,n,m,1).L(i).F(j);"
655 "Kmm4 = (-1.0)*comp(Base(#1).Base(#3).NonLin$1(#2).vGrad(#2).vGrad(#2).NonLin$2(#5))(i,j,m,n,:,n,l,:,l,m,1).L(i).F(j);"
656 "M$1(#2,#2)+= sym(Kmm1+Kmm2+Kmm3+Kmm4);"
657 "Ksm1=(-1.0)*comp(Base(#1).Grad(#3).vBase(#4).NonLin$1(#2).vGrad(#2).NonLin$2(#5))(i,j,k,:,k,m,n,:,n,m,1).L(i).F(j);"
658 "Ksm2=(-1.0)*comp(Base(#1).Grad(#3).vGrad(#4).vBase(#2).NonLin$2(#5))(i,j,m,:,m,n,:,n,1).L(i).F(j);"
659 "M$2(#4,#2)+= Ksm1+Ksm2;"
660 "Kml1=comp(Base(#3).NonLin$1(#2).vGrad(#2).Base(#1).NonLin$2(#5))(i,m,n,:,n,m,:,1).F(i);"
661 "Kml2=comp(Grad(#3).vBase(#2).Base(#1).NonLin$2(#5))(i,j,:,j,:,1).F(i);"
662 "M$3(#2,#1)+= Kml1+Kml2;"
663 "Kss_part = comp(Base(#1).Grad(#3).vGrad(#4).vBase(#4).NonLin$2(#5))(i,j,m,:,m,n,:,n,1).L(i).F(j);"
664 "M$4(#4,#4)+=sym(Kss_part{1,2}+Kss_part{2,1});"
665 "M$5(#4,#1)+=(-1.0)*comp(Grad(#3).vBase(#4).Base(#1).NonLin$2(#5))(i,k,:,k,:,1).F(i);"
669 assem_boundary.
push_mi(mim_line);
670 assem_boundary.
push_mf(mf_lambda);
671 assem_boundary.
push_mf(mf_U_line);
672 assem_boundary.
push_mf(mf_interpolate);
673 assem_boundary.
push_mf(mf_U_interpolate);
674 assem_boundary.
push_mf(mf_master_ls);
684 assem_boundary.
assembly(contact_region);
687 const gmm::sub_interval& Um_dof = gmm::sub_interval(0,mf_U_line.nb_dof());
688 const gmm::unsorted_sub_index& Us_dof =
689 mcb.get_pair_info(scb.get_var_name()).slave_vector_dofs();
690 const gmm::sub_interval& LM_dof = gmm::sub_interval(0,mf_lambda.nb_dof());
691 gmm::copy(gmm::transposed(Kms_small),gmm::sub_matrix(Kms,Um_dof,Us_dof));
692 gmm::copy(Kss_small,gmm::sub_matrix(Kss,Us_dof,Us_dof));
693 gmm::copy(Ksl_small,gmm::sub_matrix(Ksl,Us_dof,LM_dof));
697 template<
typename VECT0,
typename VECT1>
698 void asm_level_set_contact_rhs(
699 std::vector<VECT0>& vecl,
700 const master_contact_body& mcb,
701 const slave_contact_body& scb,
706 VECT0& RHS_Um = vecl[0];
707 VECT0& RHS_Us = vecl[1];
708 VECT0& RHS_LM = vecl[2];
712 const std::string& mult_name =
713 mcb.get_pair_info(scb.get_var_name()).get_mult_name();
714 const std::string ls_name =
"ls_on"+mcb.get_var_name()+
"_from_"+scb.get_var_name();
717 const mesh_fem& mf_U_line = mcb.get_mesh_fem();
718 const mesh_fem& mf_lambda =
719 mcb.get_model().mesh_fem_of_variable(mult_name);
720 const mesh_fem& mf_interpolate =
721 mcb.get_pair_info(scb.get_var_name()).slave_scalar_fem();
722 const mesh_fem& mf_U_interpolate =
723 mcb.get_pair_info(scb.get_var_name()).slave_vector_fem();
724 const mesh_fem& mf_master_ls = mcb.get_model().mesh_fem_of_variable(ls_name);
725 const mesh_im& mim_line =
726 mcb.get_pair_info(scb.get_var_name()).contact_mesh_im();
729 plain_vector LS_small(mf_interpolate.nb_dof());
730 gmm::copy(gmm::sub_vector(scb.ls_values(),
731 mcb.get_pair_info(scb.get_var_name()).slave_scalar_dofs()),LS_small);
734 NormalTerm R_matrix(mcb,2);
737 std::shared_ptr<getfem::nonlinear_elem_term> integration;
738 if (mcb.integration==master_contact_body::REGULARIZED_LEVEL_SET) {
739 integration = std::make_shared<HFunction>
740 (mf_master_ls,mcb.get_model().real_variable(ls_name),
741 mcb.regularized_tollerance,mcb.small_weight_multiplier);
742 }
else { integration = std::make_shared<Unity>(mf_master_ls); }
745 plain_vector RHS_Us_small(mf_U_interpolate.nb_dof());
751 "RHS_L_Us_1=comp(Base(#1).Base(#3).NonLin$1(#2).vGrad(#2).NonLin$2(#5))(i,j,m,n,:,n,m,1).L(i).F(j);"
752 "RHS_L_Us_2=comp(Base(#1).Grad(#3).vBase(#2).NonLin$2(#5))(i,j,k,:,k,1).L(i).F(j);"
753 "V$1(#2)+=RHS_L_Us_1+RHS_L_Us_2;"
754 "V$2(#4)+=(-1.0)*comp(Base(#1).Grad(#3).vBase(#4).NonLin$2(#5))(i,j,k,:,k,1).L(i).F(j);"
755 "V$3(#1)+=comp(Base(#1).Base(#3).NonLin$2(#5))(:,i,1).F(i);"
757 assem_boundary.
push_mi(mim_line);
758 assem_boundary.
push_mf(mf_lambda);
759 assem_boundary.
push_mf(mf_U_line);
760 assem_boundary.
push_mf(mf_interpolate);
761 assem_boundary.
push_mf(mf_U_interpolate);
762 assem_boundary.
push_mf(mf_master_ls);
768 assem_boundary.
push_vec(RHS_Us_small);
770 assem_boundary.
assembly(contact_region);
773 const gmm::unsorted_sub_index& Us_dof =
774 mcb.get_pair_info(scb.get_var_name()).slave_vector_dofs();
775 gmm::copy(RHS_Us_small, gmm::sub_vector(RHS_Us,Us_dof));
781 typedef void(*SOLVE_FUNCTION)(
784 getfem::rmodel_plsolver_type solver,
785 getfem::abstract_newton_line_search &ls);
803 const std::string& lsolver,
804 getfem::abstract_newton_line_search &ls);
structure passed as the argument of fem interpolation functions.
Generic assembly of vectors, matrices.
void push_vec(VEC &v)
Add a new output vector.
void push_data(const VEC &d)
Add a new data (dense array)
void push_mat(const MAT &m)
Add a new output matrix (fake const version..)
void assembly(const mesh_region ®ion=mesh_region::all_convexes())
do the assembly on the specified region (boundary or set of convexes)
void push_nonlinear_term(pnonlinear_elem_term net)
Add a new non-linear term.
void push_mi(const mesh_im &im_)
Add a new mesh_im.
void push_mf(const mesh_fem &mf_)
Add a new mesh_fem.
Describe a finite element method linked to a mesh.
virtual size_type nb_dof() const
Return the total number of degrees of freedom.
Describe an integration method linked to a mesh.
"iterator" class for regions.
structure used to hold a set of convexes and/or convex faces.
static size_type free_region_id(const getfem::mesh &m)
Extract the next region number that does not yet exists in the mesh.
Describe a mesh (collection of convexes (elements) and points).
void bounding_box(base_node &Pmin, base_node &Pmax) const
Return the bounding box [Pmin - Pmax] of the mesh.
void sup_region(size_type b)
Remove the region of index b.
const mesh_region region(size_type id) const
Return the region of index 'id'.
`‘Model’' variables store the variables, the data and the description of a model.
void add_fem_variable(const std::string &name, const mesh_fem &mf, size_type niter=1)
Add a variable being the dofs of a finite element method to the model.
const mesh_fem & mesh_fem_of_variable(const std::string &name) const
Gives the access to the mesh_fem of a variable if any.
void add_initialized_fem_data(const std::string &name, const mesh_fem &mf, const VECT &v)
Add an initialized fixed size data to the model, assumed to be a vector field if the size of the vect...
model_real_plain_vector & set_real_variable(const std::string &name, size_type niter) const
Gives the write access to the vector value of a variable.
const model_real_plain_vector & real_variable(const std::string &name, size_type niter) const
Gives the access to the vector value of a variable.
abstract class for integration of non-linear terms into the mat_elem computations the nonlinear term ...
The virtual brick has to be derived to describe real model bricks.
The Iteration object calculates whether the solution has reached the desired accuracy,...
base class for the master and the slave contact bodies.
Master contact body which surface will be used to project contact stresses and stiffness terms.
const contact_pair_info & get_pair_info(const std::string &slave_var_name) const
access to a structure that contains all the info about contact pair between this master and a slave,...
const size_type mult_mf_order
approximation order for Lagrange multiplier on the contact surface
master_contact_body(model &_md, const std::string &_var_name, size_type _mult_order, size_type _mult_mim_order)
create master contact body with a model, name where masters displacements are defined,...
size_type contact_mim_order() const
order of integration of boundary contact terms
bool master_contact_changed(void)
contact detection for all slaves
static bool any_contact_change()
contact detection for all masters/slave couples
size_type volume_region() const
region of all volume elements without the boundary
const scalar_type small_weight_multiplier
in case of REGULARIZED_LEVEL_SET this value scales weight of Gauss points that have negative level se...
const scalar_type max_contact_angle
if the angle (in degrees) between contact element and level set contour exceed this value,...
std::shared_ptr< mesh_im > build_mesh_im_on_boundary(size_type region)
return a pointer to mesh_im used for contact surface calculations
void clear_contact_history(void)
clearing previous contact elem lists
void add_slave(slave_contact_body &scb, size_type slave_contact_region=-1)
associate a slave contact body with this master.
const contact_integration integration
integration approach for contact elements that are partially crossed by level sets: PER_ELEMENT - a w...
const scalar_type regularized_tollerance
width of transition for a regularazied Heaviside function in case of REGULARIZED_LEVEL_SET
face_type ext_face_of_elem(size_type cv) const
gives a face, corresponding to newly created boundary element
size_type boundary_region() const
boundary elements, added after creation of the master contact body
getfem::pintegration_method contact_int_method() const
integration method on the contact surface, use it when the master is created with a specific integrat...
static void clear_all_contact_history()
should be used in the beginning of a step to clean data structures that store previous contact elemen...
Contact body that will be projected on the boundary of the master.
void offset_level_set(scalar_type off)
adds a fixed value "off" to the level set field
slave_contact_body(model &_md, const std::string &_var_name, mesh_im *_pmim)
default constructor.
Miscelleanous assembly routines for common terms. Use the low-level generic assembly....
Standard solvers for model bricks.
Model representation in Getfem.
void copy(const L1 &l1, L2 &l2)
*/
Definition of basic exceptions.
void APIDECL outer_faces_of_mesh(const mesh &m, const dal::bit_vector &cvlst, convex_face_ct &flist)
returns a list of "exterior" faces of a mesh (i.e.
std::shared_ptr< const getfem::virtual_fem > pfem
type of pointer on a fem description
gmm::uint16_type short_type
used as the common short type integer in the library
size_t size_type
used as the common size type in the library
std::shared_ptr< const bgeot::geometric_trans > pgeometric_trans
pointer type for a geometric transformation
size_type APIDECL add_Laplacian_brick(model &md, const mesh_im &mim, const std::string &varname, size_type region=size_type(-1))
Add a Laplacian term on the variable varname (in fact with a minus : :math:-\text{div}(\nabla u)).
pintegration_method int_method_descriptor(std::string name, bool throw_if_not_found=true)
Get an integration method from its name .
size_type APIDECL add_Dirichlet_condition_with_penalization(model &md, const mesh_im &mim, const std::string &varname, scalar_type penalization_coeff, size_type region, const std::string &dataname=std::string(), const mesh_fem *mf_mult=0)
Add a Dirichlet condition on the variable varname and the mesh region region.
size_type APIDECL add_source_term_brick(model &md, const mesh_im &mim, const std::string &varname, const std::string &dataexpr, size_type region=size_type(-1), const std::string &directdataname=std::string())
Add a source term on the variable varname.
void standard_solve(model &md, gmm::iteration &iter, rmodel_plsolver_type lsolver, abstract_newton_line_search &ls)
A default solver for the model brick system.