47 #ifndef GETFEM_LEVEL_SET_CONTACT_H__
48 #define GETFEM_LEVEL_SET_CONTACT_H__
56 namespace level_set_contact {
63 using getfem::scalar_type;
64 using getfem::model_real_plain_vector;
65 typedef getfem::model_real_plain_vector plain_vector;
66 typedef getfem::model_real_sparse_matrix sparse_matrix;
82 getfem::model_real_plain_vector RHS(mf.
nb_dof());
85 getfem::base_node Pmin(
mesh.dim()),Pmax(
mesh.dim()),range(
mesh.dim());
87 gmm::add(Pmax,gmm::scaled(Pmin,-1.0),range);
88 getfem::scalar_type mesh_size = *(std::max_element(range.begin(),range.end()));
89 gmm::fill(RHS,mesh_size*5.0);
106 GMM_TRACE2(
"building scalar level set with laplace equation..");
114 GMM_TRACE2(
"..done");
121 const std::string var_name;
133 inline std::string get_var_name()
const {
return var_name;}
134 inline mesh& get_mesh() {
return own_mesh;}
135 inline const mesh& get_mesh()
const {
return own_mesh;}
136 inline const mesh_fem& get_mesh_fem()
const {
return own_mesh_fem;}
137 inline const model& get_model()
const {
return md;}
138 inline bool is_mesh_deformed()
const {
return is_deformed;}
159 std::string _ls_name);
160 inline std::string get_ls_name()
const {
return ls_name;}
161 inline const plain_vector& ls_values()
const
163 inline plain_vector& ls_values()
166 template<
class VECTOR>
void set_level_set(
const VECTOR& ls)
183 const std::string mult_name;
187 dal::bit_vector old_contact_elm_list;
188 dal::bit_vector pre_old_ct_list;
190 mutable std::shared_ptr<mesh_im> pmim_contact;
192 mutable std::shared_ptr<mesh_fem> pinterpolated_fem;
193 mutable std::shared_ptr<mesh_fem> pinterpolated_fem_U;
194 mutable std::shared_ptr<gmm::unsorted_sub_index> slave_ls_dofs;
195 mutable std::shared_ptr<gmm::unsorted_sub_index> slave_U_dofs;
199 mutable bool members_are_computed;
200 mutable bool init_cont_detect_done;
204 inline const mesh_fem& slave_scalar_fem()
const {
205 if (dependecies_changed())
update();
206 return *pinterpolated_fem;
208 inline const mesh_fem& slave_vector_fem()
const {
209 if (dependecies_changed())
update();
210 return *pinterpolated_fem_U;
212 inline const gmm::unsorted_sub_index& slave_scalar_dofs()
const {
213 if (dependecies_changed())
update();
214 return *slave_ls_dofs;
216 inline const gmm::unsorted_sub_index& slave_vector_dofs()
const {
217 if (dependecies_changed())
update();
218 return *slave_U_dofs;
220 inline const mesh_im& contact_mesh_im()
const {
221 if (dependecies_changed())
update();
222 return *pmim_contact;
226 {
return ACTIVE_CONTACT_REGION;}
228 inline const std::string& get_mult_name()
const
231 inline size_type num_of_integr_elems()
const {
return n_integrated_elems;}
233 inline bool dependecies_changed()
const
234 {
return !members_are_computed;}
235 inline void force_update()
const
236 {members_are_computed=
false;}
291 const std::string mult_int_method;
292 size_type BOUNDARY_ELEMENTS, VOLUME_ELEMENTS;
293 std::vector<size_type> face_to_belem_ind;
294 static std::vector<master_contact_body*> masters;
295 std::map<std::string, std::shared_ptr<contact_pair_info> > contact_table;
296 std::map<size_type,face_type> border_faces;
308 enum contact_integration{PER_ELEMENT=1,REGULARIZED_LEVEL_SET=2};
340 const std::string& _var_name,
351 const std::string& _var_name,
353 const std::string& _mult_int_method,
354 contact_integration _integration = PER_ELEMENT,
355 scalar_type _regularized_tollerance = 1e-6,
356 scalar_type _small_weight_multiplier = 0.001,
357 scalar_type _max_contact_angle = 45);
368 GMM_ASSERT1(mult_mim_order!=
size_type(-1),
369 "master body was not created with "
370 "order of integration for contact area");
371 return mult_mim_order;
379 GMM_ASSERT1(mult_mim_order==
size_type(-1),
380 "master body was not created with integration "
381 "method for contact area");
387 {
return VOLUME_ELEMENTS;}
392 {
return BOUNDARY_ELEMENTS;}
415 inline void update_for_slave(std::string slave_var_name)
416 { contact_table[slave_var_name]->update(); }
433 enum update_depth{DEFORM_MESHES_ONLY,FULL_UPDATE};
438 std::shared_ptr<getfem::temporary_mesh_deformator<> > def_master;
439 std::shared_ptr<getfem::temporary_mesh_deformator<> > def_slave;
445 update_depth ud = FULL_UPDATE);
490 const model::varnamelist &vl,
491 const model::varnamelist &dl,
492 const model::mimlist &mims,
493 model::real_matlist &matl,
494 model::real_veclist &vecl,
495 model::real_veclist &,
497 build_version version)
const;
514 bgeot::multi_index sizes_;
524 dim(_mcb.get_mesh().dim()) {
526 GMM_ASSERT1(dim==2 || dim==3,
"NormalTerm: wrong space dimension ");
527 GMM_ASSERT1(version==1 || version==2,
"NormalTerm:: wrong version ");
544 const bgeot::multi_index &sizes(
size_type)
const {
return sizes_;};
560 const plain_vector &LS_U;
561 scalar_type m_Epsilon;
563 bgeot::multi_index sizes_;
569 const plain_vector &LS_U_,
570 scalar_type epsilon=1e-9,
571 scalar_type small_h_=0);
572 const bgeot::multi_index &sizes(
size_type)
const;
575 scalar_type hRegularized(scalar_type x, scalar_type epsion, scalar_type small);
583 bgeot::multi_index sizes_;
587 const bgeot::multi_index &sizes(
size_type)
const;
594 template<
typename MAT,
typename VECT>
595 void asm_level_set_contact_tangent_matrix(
596 std::vector<MAT>& matl,
597 const master_contact_body& mcb,
598 const slave_contact_body& scb,
610 const std::string& mult_name =
611 mcb.get_pair_info(scb.get_var_name()).get_mult_name();
612 const std::string ls_name =
"ls_on"+mcb.get_var_name()+
"_from_"+scb.get_var_name();
615 const mesh_fem& mf_U_line = mcb.get_mesh_fem();
616 const mesh_fem& mf_lambda = mcb.get_model().mesh_fem_of_variable(mult_name);
617 const mesh_fem& mf_interpolate =
618 mcb.get_pair_info(scb.get_var_name()).slave_scalar_fem();
619 const mesh_fem& mf_U_interpolate =
620 mcb.get_pair_info(scb.get_var_name()).slave_vector_fem();
621 const mesh_fem& mf_master_ls = mcb.get_model().mesh_fem_of_variable(ls_name);
622 const mesh_im& mim_line =
623 mcb.get_pair_info(scb.get_var_name()).contact_mesh_im();
626 plain_vector LS_small(mf_interpolate.nb_dof());
627 gmm::copy(gmm::sub_vector(scb.ls_values(),
628 mcb.get_pair_info(scb.get_var_name()).slave_scalar_dofs()),LS_small);
631 NormalTerm R_matrix(mcb,2);
634 std::shared_ptr<getfem::nonlinear_elem_term> integration;
635 if (mcb.integration==master_contact_body::REGULARIZED_LEVEL_SET) {
636 integration = std::make_shared<HFunction>
637 (mf_master_ls,mcb.get_model().real_variable(ls_name),
638 mcb.regularized_tollerance,mcb.small_weight_multiplier);
639 }
else { integration = std::make_shared<Unity>(mf_master_ls); }
643 sparse_matrix Kms_small(mf_U_interpolate.nb_dof(), mf_U_line.nb_dof());
644 sparse_matrix Kss_small(mf_U_interpolate.nb_dof(),mf_U_interpolate.nb_dof());
645 sparse_matrix Ksl_small(mf_U_interpolate.nb_dof(),mf_lambda.nb_dof());
653 "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);"
654 "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);"
655 "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);"
656 "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);"
657 "M$1(#2,#2)+= sym(Kmm1+Kmm2+Kmm3+Kmm4);"
658 "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);"
659 "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);"
660 "M$2(#4,#2)+= Ksm1+Ksm2;"
661 "Kml1=comp(Base(#3).NonLin$1(#2).vGrad(#2).Base(#1).NonLin$2(#5))(i,m,n,:,n,m,:,1).F(i);"
662 "Kml2=comp(Grad(#3).vBase(#2).Base(#1).NonLin$2(#5))(i,j,:,j,:,1).F(i);"
663 "M$3(#2,#1)+= Kml1+Kml2;"
664 "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);"
665 "M$4(#4,#4)+=sym(Kss_part{1,2}+Kss_part{2,1});"
666 "M$5(#4,#1)+=(-1.0)*comp(Grad(#3).vBase(#4).Base(#1).NonLin$2(#5))(i,k,:,k,:,1).F(i);"
670 assem_boundary.
push_mi(mim_line);
671 assem_boundary.
push_mf(mf_lambda);
672 assem_boundary.
push_mf(mf_U_line);
673 assem_boundary.
push_mf(mf_interpolate);
674 assem_boundary.
push_mf(mf_U_interpolate);
675 assem_boundary.
push_mf(mf_master_ls);
685 assem_boundary.
assembly(contact_region);
688 const gmm::sub_interval& Um_dof = gmm::sub_interval(0,mf_U_line.nb_dof());
689 const gmm::unsorted_sub_index& Us_dof =
690 mcb.get_pair_info(scb.get_var_name()).slave_vector_dofs();
691 const gmm::sub_interval& LM_dof = gmm::sub_interval(0,mf_lambda.nb_dof());
692 gmm::copy(gmm::transposed(Kms_small),gmm::sub_matrix(Kms,Um_dof,Us_dof));
693 gmm::copy(Kss_small,gmm::sub_matrix(Kss,Us_dof,Us_dof));
694 gmm::copy(Ksl_small,gmm::sub_matrix(Ksl,Us_dof,LM_dof));
698 template<
typename VECT0,
typename VECT1>
699 void asm_level_set_contact_rhs(
700 std::vector<VECT0>& vecl,
701 const master_contact_body& mcb,
702 const slave_contact_body& scb,
707 VECT0& RHS_Um = vecl[0];
708 VECT0& RHS_Us = vecl[1];
709 VECT0& RHS_LM = vecl[2];
713 const std::string& mult_name =
714 mcb.get_pair_info(scb.get_var_name()).get_mult_name();
715 const std::string ls_name =
"ls_on"+mcb.get_var_name()+
"_from_"+scb.get_var_name();
718 const mesh_fem& mf_U_line = mcb.get_mesh_fem();
719 const mesh_fem& mf_lambda =
720 mcb.get_model().mesh_fem_of_variable(mult_name);
721 const mesh_fem& mf_interpolate =
722 mcb.get_pair_info(scb.get_var_name()).slave_scalar_fem();
723 const mesh_fem& mf_U_interpolate =
724 mcb.get_pair_info(scb.get_var_name()).slave_vector_fem();
725 const mesh_fem& mf_master_ls = mcb.get_model().mesh_fem_of_variable(ls_name);
726 const mesh_im& mim_line =
727 mcb.get_pair_info(scb.get_var_name()).contact_mesh_im();
730 plain_vector LS_small(mf_interpolate.nb_dof());
731 gmm::copy(gmm::sub_vector(scb.ls_values(),
732 mcb.get_pair_info(scb.get_var_name()).slave_scalar_dofs()),LS_small);
735 NormalTerm R_matrix(mcb,2);
738 std::shared_ptr<getfem::nonlinear_elem_term> integration;
739 if (mcb.integration==master_contact_body::REGULARIZED_LEVEL_SET) {
740 integration = std::make_shared<HFunction>
741 (mf_master_ls,mcb.get_model().real_variable(ls_name),
742 mcb.regularized_tollerance,mcb.small_weight_multiplier);
743 }
else { integration = std::make_shared<Unity>(mf_master_ls); }
746 plain_vector RHS_Us_small(mf_U_interpolate.nb_dof());
752 "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);"
753 "RHS_L_Us_2=comp(Base(#1).Grad(#3).vBase(#2).NonLin$2(#5))(i,j,k,:,k,1).L(i).F(j);"
754 "V$1(#2)+=RHS_L_Us_1+RHS_L_Us_2;"
755 "V$2(#4)+=(-1.0)*comp(Base(#1).Grad(#3).vBase(#4).NonLin$2(#5))(i,j,k,:,k,1).L(i).F(j);"
756 "V$3(#1)+=comp(Base(#1).Base(#3).NonLin$2(#5))(:,i,1).F(i);"
758 assem_boundary.
push_mi(mim_line);
759 assem_boundary.
push_mf(mf_lambda);
760 assem_boundary.
push_mf(mf_U_line);
761 assem_boundary.
push_mf(mf_interpolate);
762 assem_boundary.
push_mf(mf_U_interpolate);
763 assem_boundary.
push_mf(mf_master_ls);
769 assem_boundary.
push_vec(RHS_Us_small);
771 assem_boundary.
assembly(contact_region);
774 const gmm::unsorted_sub_index& Us_dof =
775 mcb.get_pair_info(scb.get_var_name()).slave_vector_dofs();
776 gmm::copy(RHS_Us_small, gmm::sub_vector(RHS_Us,Us_dof));
782 typedef void(*SOLVE_FUNCTION)(
785 getfem::rmodel_plsolver_type solver,
786 getfem::abstract_newton_line_search &ls);
804 const std::string& lsolver,
805 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.