37 #ifndef GETFEM_CONTACT_AND_FRICTION_COMMON_H__
38 #define GETFEM_CONTACT_AND_FRICTION_COMMON_H__
54 template<
typename VEC>
void ball_projection(
const VEC &x,
56 if (radius <= scalar_type(0))
60 if (a > radius) gmm::scale(
const_cast<VEC&
>(x), radius/a);
64 template<
typename VEC,
typename VECR>
65 void ball_projection_grad_r(
const VEC &x, scalar_type radius,
67 if (radius > scalar_type(0)) {
70 gmm::copy(x, g); gmm::scale(g, scalar_type(1)/a);
77 template <
typename VEC,
typename MAT>
78 void ball_projection_grad(
const VEC &x, scalar_type radius, MAT &g) {
79 if (radius <= scalar_type(0)) {
gmm::clear(g);
return; }
83 gmm::scale(g, radius/a);
87 g(i,j) -= radius*x[i]*x[j] / (a*a*a);
91 template <
typename VEC,
typename VECR>
92 void coupled_projection(
const VEC &x,
const VEC &n,
93 scalar_type f, VECR &g) {
95 scalar_type xnm = gmm::neg(xn);
96 scalar_type th = f * xnm;
97 scalar_type xtn = gmm::sqrt(gmm::vect_norm2_sqr(x) - xn*xn);
100 if (th > scalar_type(0)) {
105 gmm::add(gmm::scaled(x, f*xnm/xtn), g);
106 gmm::add(gmm::scaled(n, -f*xnm*xn/xtn), g);
112 template <
typename VEC,
typename MAT>
113 void coupled_projection_grad(
const VEC &x,
const VEC &n,
114 scalar_type f, MAT &g) {
116 scalar_type xnm = gmm::neg(xn);
117 scalar_type th = f * xnm;
118 scalar_type xtn = gmm::sqrt(gmm::vect_norm2_sqr(x) - xn*xn);
122 if (th > scalar_type(0)) {
125 gmm::rank_one_update(g, gmm::scaled(n, -scalar_type(1)), n);
126 }
else if (xn < scalar_type(0)) {
128 gmm::add(x, gmm::scaled(n, -xn), t);
129 gmm::scale(t, scalar_type(1)/xtn);
132 gmm::rank_one_update(g, gmm::scaled(t, -scalar_type(1)), t);
133 gmm::rank_one_update(g, gmm::scaled(n, -scalar_type(1)), n);
134 gmm::scale(g, -xn*th/xtn);
136 gmm::rank_one_update(g, gmm::scaled(t, -f), n);
140 if (xn < scalar_type(0)) gmm::rank_one_update(g, n, n);
150 template<
typename VEC>
151 void De_Saxce_projection(
const VEC &x,
const VEC &n_, scalar_type f) {
152 static base_small_vector n;
155 gmm::copy(gmm::scaled(n_, scalar_type(1)/gmm::vect_norm2(n_)), n);
157 scalar_type nxt = sqrt(gmm::abs(gmm::vect_norm2_sqr(x) - xn*xn));
158 if (xn >= scalar_type(0) && f * nxt <= xn) {
160 }
else if (xn > scalar_type(0) || nxt > -f*xn) {
161 gmm::add(gmm::scaled(n, -xn),
const_cast<VEC&
>(x));
162 gmm::scale(
const_cast<VEC&
>(x), -f / nxt);
164 gmm::scale(
const_cast<VEC&
>(x), (xn - f * nxt) / (f*f+scalar_type(1)));
168 template<
typename VEC,
typename MAT>
169 void De_Saxce_projection_grad(
const VEC &x,
const VEC &n_,
170 scalar_type f, MAT &g) {
171 static base_small_vector n;
174 gmm::copy(gmm::scaled(n_, scalar_type(1)/gmm::vect_norm2(n_)), n);
176 scalar_type nxt = sqrt(gmm::abs(gmm::vect_norm2_sqr(x) - xn*xn));
179 if (xn > scalar_type(0) && f * nxt <= xn) {
181 }
else if (xn > scalar_type(0) || nxt > -f*xn) {
182 static base_small_vector xt;
184 gmm::add(x, gmm::scaled(n, -xn), xt);
185 gmm::scale(xt, scalar_type(1)/nxt);
189 gmm::rank_one_update(g, gmm::scaled(n, -scalar_type(1)), n);
190 gmm::rank_one_update(g, gmm::scaled(xt, -scalar_type(1)), xt);
191 gmm::scale(g, f*(f - xn/nxt));
196 gmm::scale(xt, -f);
gmm::add(n, xt);
197 gmm::rank_one_update(g, xt, xt);
198 gmm::scale(g, scalar_type(1) / (f*f+scalar_type(1)));
205 template<
typename VEC,
typename MAT>
206 static void De_Saxce_projection_gradn(
const VEC &x,
const VEC &n_,
207 scalar_type f, MAT &g) {
208 static base_small_vector n;
212 gmm::copy(gmm::scaled(n_, scalar_type(1)/nn), n);
214 scalar_type nxt = sqrt(gmm::abs(gmm::vect_norm2_sqr(x) - xn*xn));
217 if (!(xn > scalar_type(0) && f * nxt <= xn)
218 && (xn > scalar_type(0) || nxt > -f*xn)) {
219 static base_small_vector xt, aux;
221 gmm::add(x, gmm::scaled(n, -xn), xt);
222 gmm::scale(xt, scalar_type(1)/nxt);
224 scalar_type c = (scalar_type(1) + f*xn/nxt)/nn;
225 for (
size_type i = 0; i < N; ++i) g(i,i) = c;
226 gmm::rank_one_update(g, gmm::scaled(n, -c), n);
227 gmm::rank_one_update(g, gmm::scaled(n, f/nn), xt);
228 gmm::rank_one_update(g, gmm::scaled(xt, -f*xn/(nn*nxt)), xt);
229 gmm::scale(g, xn - f*nxt);
231 gmm::add(gmm::scaled(xt, -f), n, aux);
232 gmm::rank_one_update(g, aux, gmm::scaled(xt, (nxt+f*xn)/nn));
234 gmm::scale(g, scalar_type(1) / (f*f+scalar_type(1)));
244 template <
typename MAT1,
typename MAT2>
245 void mat_elem_assembly(
const MAT1 &M_,
const MAT2 &Melem,
248 MAT1 &M =
const_cast<MAT1 &
>(M_);
249 typedef typename gmm::linalg_traits<MAT1>::value_type T;
251 mesh_fem::ind_dof_ct cvdof1 = mf1.ind_basic_dof_of_element(cv1);
252 mesh_fem::ind_dof_ct cvdof2 = mf2.ind_basic_dof_of_element(cv2);
254 GMM_ASSERT1(cvdof1.size() == gmm::mat_nrows(Melem)
255 && cvdof2.size() == gmm::mat_ncols(Melem),
256 "Dimensions mismatch");
258 if (mf1.is_reduced()) {
259 if (mf2.is_reduced()) {
260 for (
size_type i = 0; i < cvdof1.size(); ++i)
261 for (
size_type j = 0; j < cvdof2.size(); ++j)
262 if ((val = Melem(i,j)) != T(0))
264 (M, gmm::mat_row(mf1.extension_matrix(), cvdof1[i]),
265 gmm::mat_row(mf2.extension_matrix(), cvdof2[j]), val);
267 for (
size_type i = 0; i < cvdof1.size(); ++i)
268 for (
size_type j = 0; j < cvdof2.size(); ++j)
269 if ((val = Melem(i,j)) != T(0))
271 (M, gmm::mat_row(mf1.extension_matrix(), cvdof1[i]),
275 if (mf2.is_reduced()) {
276 for (
size_type i = 0; i < cvdof1.size(); ++i)
277 for (
size_type j = 0; j < cvdof2.size(); ++j)
278 if ((val = Melem(i,j)) != T(0))
281 gmm::mat_row(mf2.extension_matrix(), cvdof2[j]), val);
283 for (
size_type i = 0; i < cvdof1.size(); ++i)
284 for (
size_type j = 0; j < cvdof2.size(); ++j)
285 if ((val = Melem(i,j)) != T(0))
286 M(cvdof1[i], cvdof2[j]) += val;
292 template <
typename VEC1,
typename VEC2>
293 void vec_elem_assembly(
const VEC1 &V_,
const VEC2 &Velem,
295 VEC1 &V =
const_cast<VEC1 &
>(V_);
296 typedef typename gmm::linalg_traits<VEC1>::value_type T;
297 std::vector<size_type> cvdof(mf.ind_basic_dof_of_element(cv).begin(),
298 mf.ind_basic_dof_of_element(cv).end());
300 GMM_ASSERT1(cvdof.size() == gmm::vect_size(Velem),
"Dimensions mismatch");
302 if (mf.is_reduced()) {
304 for (
size_type i = 0; i < cvdof.size(); ++i)
305 if ((val = Velem[i]) != T(0))
306 gmm::add(gmm::scaled(gmm::mat_row(mf.extension_matrix(), cvdof[i]),
309 for (
size_type i = 0; i < cvdof.size(); ++i) V[cvdof[i]] += Velem[i];
313 template <
typename MAT1,
typename MAT2>
314 void mat_elem_assembly(
const MAT1 &M_,
const gmm::sub_interval &I1,
315 const gmm::sub_interval &I2,
319 MAT1 &M =
const_cast<MAT1 &
>(M_);
320 typedef typename gmm::linalg_traits<MAT1>::value_type T;
323 mesh_fem::ind_dof_ct cvdof1 = mf1.ind_basic_dof_of_element(cv1);
324 mesh_fem::ind_dof_ct cvdof2 = mf2.ind_basic_dof_of_element(cv2);
326 GMM_ASSERT1(cvdof1.size() == gmm::mat_nrows(Melem)
327 && cvdof2.size() == gmm::mat_ncols(Melem),
328 "Dimensions mismatch");
330 if (mf1.is_reduced()) {
331 if (mf2.is_reduced()) {
332 for (
size_type i = 0; i < cvdof1.size(); ++i)
333 for (
size_type j = 0; j < cvdof2.size(); ++j)
334 if ((val = Melem(i,j)) != T(0))
336 (gmm::sub_matrix(M, I1, I2),
337 gmm::mat_row(mf1.extension_matrix(), cvdof1[i]),
338 gmm::mat_row(mf2.extension_matrix(), cvdof2[j]), val);
340 for (
size_type i = 0; i < cvdof1.size(); ++i)
341 for (
size_type j = 0; j < cvdof2.size(); ++j)
342 if ((val = Melem(i,j)) != T(0))
344 (gmm::sub_matrix(M, I1, I2),
345 gmm::mat_row(mf1.extension_matrix(), cvdof1[i]),
349 if (mf2.is_reduced()) {
350 for (
size_type i = 0; i < cvdof1.size(); ++i)
351 for (
size_type j = 0; j < cvdof2.size(); ++j)
352 if ((val = Melem(i,j)) != T(0))
354 (gmm::sub_matrix(M, I1, I2), cvdof1[i],
355 gmm::mat_row(mf2.extension_matrix(), cvdof2[j]), val);
357 for (
size_type i = 0; i < cvdof1.size(); ++i)
358 for (
size_type j = 0; j < cvdof2.size(); ++j)
359 if ((val = Melem(i,j)) != T(0))
360 M(cvdof1[i]+I1.first(), cvdof2[j]+I2.first()) += val;
365 template <
typename VEC1,
typename VEC2>
366 void vec_elem_assembly(
const VEC1 &V_,
const gmm::sub_interval &I,
367 const VEC2 &Velem,
const mesh_fem &mf,
size_type cv) {
368 VEC1 &V =
const_cast<VEC1 &
>(V_);
369 typedef typename gmm::linalg_traits<VEC1>::value_type T;
370 std::vector<size_type> cvdof(mf.ind_basic_dof_of_element(cv).begin(),
371 mf.ind_basic_dof_of_element(cv).end());
373 GMM_ASSERT1(cvdof.size() == gmm::vect_size(Velem),
"Dimensions mismatch");
375 if (mf.is_reduced()) {
377 for (
size_type i = 0; i < cvdof.size(); ++i)
378 if ((val = Velem[i]) != T(0))
379 gmm::add(gmm::scaled(gmm::mat_row(mf.extension_matrix(), cvdof[i]),
380 val), gmm::sub_vector(V, I));
382 for (
size_type i = 0; i < cvdof.size(); ++i)
383 V[I.first()+cvdof[i]] += Velem[i];
389 bool in_reference_conf,
const model_real_plain_vector &coeff,
390 base_node &n0, base_node &n, base_matrix &grad);
402 class multi_contact_frame {
405 struct contact_boundary {
410 std::string multname;
415 contact_boundary(
void) {}
416 contact_boundary(
size_type r,
const mesh_fem *mf,
417 const mesh_im &mi,
size_type i_U,
const mesh_fem *mfl,
419 : region(r), mfu(mf), mflambda(mfl), mim(&mi),
420 ind_U(i_U), ind_lambda(i_l), slave(false) {}
437 scalar_type release_distance;
442 scalar_type cut_angle;
447 typedef model_real_plain_vector VECTOR;
448 std::vector<const VECTOR *> Us;
449 std::vector<const VECTOR *> Ws;
450 std::vector<std::string> Unames;
451 std::vector<std::string> Wnames;
452 std::vector<VECTOR> ext_Us;
453 std::vector<VECTOR> ext_Ws;
454 std::vector<const VECTOR *> lambdas;
455 std::vector<std::string> lambdanames;
456 std::vector<VECTOR> ext_lambdas;
458 std::vector<contact_boundary> contact_boundaries;
460 std::vector<std::string> coordinates;
461 model_real_plain_vector pt, ptx, pty, ptz, ptw;
462 std::list<ga_workspace> obstacles_gw;
463 std::vector<ga_function> obstacles_f;
464 std::vector<std::string> obstacles;
465 std::vector<std::string> obstacles_velocities;
468 struct normal_cone :
public std::vector<base_small_vector> {
470 void add_normal(
const base_small_vector &n)
471 { std::vector<base_small_vector>::push_back(n);}
473 normal_cone(
const base_small_vector &n)
474 : std::vector<base_small_vector>(1, n) { }
480 struct influence_box {
484 base_small_vector mean_normal;
485 influence_box(
void) {}
488 : ind_boundary(ib), ind_element(ie), ind_face(iff), mean_normal(n) {}
492 std::vector<influence_box> element_boxes_info;
498 struct boundary_point {
506 boundary_point(
void) {}
509 : ref_point(rp), ind_boundary(ib), ind_element(ie), ind_face(iff),
510 ind_pt(id), normals(n) {}
513 std::vector<base_node> boundary_points;
514 std::vector<boundary_point> boundary_points_info;
517 size_type add_U(
const model_real_plain_vector *U,
const std::string &name,
518 const model_real_plain_vector *w,
const std::string &wname);
519 size_type add_lambda(
const model_real_plain_vector *lambda,
520 const std::string &name);
522 void extend_vectors(
void);
524 void normal_cone_simplification(
void);
526 bool test_normal_cones_compatibility(
const normal_cone &nc1,
527 const normal_cone &nc2);
529 bool test_normal_cones_compatibility(
const base_small_vector &n,
530 const normal_cone &nc2);
532 dal::bit_vector aux_dof_cv;
548 : ind_boundary(ib), ind_element(ie), ind_face(iff) {}
553 std::vector<std::vector<face_info> > potential_pairs;
560 struct contact_pair {
562 base_node slave_point;
563 base_small_vector slave_n;
570 base_node master_point_ref;
571 base_node master_point;
572 base_small_vector master_n;
577 scalar_type signed_dist;
581 contact_pair(
void) {}
582 contact_pair(
const base_node &spt,
const base_small_vector &nx,
583 const boundary_point &bp,
584 const base_node &mptr,
const base_node &mpt,
585 const base_small_vector &ny,
586 const face_info &mfi, scalar_type sd)
587 : slave_point(spt), slave_n(nx),
588 slave_ind_boundary(bp.ind_boundary), slave_ind_element(bp.ind_element),
589 slave_ind_face(bp.ind_face), slave_ind_pt(bp.ind_pt),
590 master_point_ref(mptr), master_point(mpt), master_n(ny),
591 master_ind_boundary(mfi.ind_boundary), master_ind_element(mfi.ind_element),
592 master_ind_face(mfi.ind_face),
593 signed_dist(sd), irigid_obstacle(
size_type(-1)) {}
594 contact_pair(
const base_node &spt,
const base_small_vector &nx,
595 const boundary_point &bp,
596 const base_node &mpt,
const base_small_vector &ny,
598 : slave_point(spt), slave_n(nx), slave_ind_boundary(bp.ind_boundary),
599 slave_ind_element(bp.ind_element), slave_ind_face(bp.ind_face),
600 slave_ind_pt(bp.ind_pt), master_point(mpt), master_n(ny),
602 irigid_obstacle(ir) {}
610 void compute_influence_boxes(
void);
620 void compute_boundary_points(
bool slave_only =
false);
621 void compute_potential_contact_pairs_delaunay(
void);
622 void compute_potential_contact_pairs_influence_boxes(
void);
626 std::vector<contact_pair> contact_pairs;
628 void clear_aux_info(
void);
633 const std::vector<contact_pair> &ct_pairs(
void)
const
634 {
return contact_pairs; }
638 {
return *(contact_boundaries[n].mfu); }
640 {
return *(contact_boundaries[n].mflambda); }
642 {
return *(contact_boundaries[n].mim); }
643 size_type nb_variables(
void)
const {
return Us.size(); }
644 size_type nb_multipliers(
void)
const {
return lambdas.size(); }
645 const std::string &varname(
size_type i)
const {
return Unames[i]; }
646 const std::string &multname(
size_type i)
const {
return lambdanames[i]; }
647 const model_real_plain_vector &disp_of_boundary(
size_type n)
const
648 {
return ext_Us[contact_boundaries[n].ind_U]; }
649 const model_real_plain_vector &disp0_of_boundary(
size_type n)
const
650 {
return ext_Ws[contact_boundaries[n].ind_U]; }
651 const model_real_plain_vector &mult_of_boundary(
size_type n)
const
652 {
return ext_lambdas[contact_boundaries[n].ind_lambda]; }
654 {
return contact_boundaries[n].region; }
655 const std::string &varname_of_boundary(
size_type n)
const
656 {
return Unames[contact_boundaries[n].ind_U]; }
658 {
return contact_boundaries[n].ind_U; }
659 const std::string &multname_of_boundary(
size_type n)
const {
660 static const std::string vname;
661 size_type ind = contact_boundaries[n].ind_lambda;
662 return (ind ==
size_type(-1)) ? vname : lambdanames[ind];
665 {
return contact_boundaries[n].ind_lambda; }
666 size_type nb_boundaries(
void)
const {
return contact_boundaries.size(); }
667 bool is_self_contact(
void)
const {
return self_contact; }
668 bool is_slave_boundary(
size_type n)
const {
return contact_boundaries[n].slave; }
669 void set_raytrace(
bool b) { raytrace = b; }
670 void set_nodes_mode(
int m) { nodes_mode = m; }
671 size_type nb_contact_pairs(
void)
const {
return contact_pairs.size(); }
672 const contact_pair &get_contact_pair(
size_type i)
673 {
return contact_pairs[i]; }
675 multi_contact_frame(
size_type NN, scalar_type r_dist,
676 bool dela =
true,
bool selfc =
true,
677 scalar_type cut_a = 0.3,
bool rayt =
false,
678 int fem_nodes = 0,
bool refc =
false);
679 multi_contact_frame(
const model &md,
size_type NN, scalar_type r_dist,
680 bool dela =
true,
bool selfc =
true,
681 scalar_type cut_a = 0.3,
bool rayt =
false,
682 int fem_nodes = 0,
bool refc =
false);
684 size_type add_obstacle(
const std::string &obs);
688 const model_real_plain_vector *U,
691 const model_real_plain_vector *lambda = 0,
692 const model_real_plain_vector *w = 0,
693 const std::string &varname = std::string(),
694 const std::string &multname = std::string(),
695 const std::string &wname = std::string());
698 const std::string &varname,
699 const std::string &multname = std::string(),
700 const std::string &wname = std::string());
705 const model_real_plain_vector *U,
708 const model_real_plain_vector *lambda = 0,
709 const model_real_plain_vector *w = 0,
710 const std::string &varname = std::string(),
711 const std::string &multname = std::string(),
712 const std::string &wname = std::string());
715 const std::string &varname,
716 const std::string &multname = std::string(),
717 const std::string &wname = std::string());
727 void compute_contact_pairs(
void);
743 (model &md,
const std::string &transname, scalar_type release_distance);
749 (ga_workspace &workspace,
const std::string &transname,
750 scalar_type release_distance);
757 (model &md,
const std::string &transname,
const mesh &m,
758 const std::string &dispname,
size_type region);
765 (model &md,
const std::string &transname,
const mesh &m,
766 const std::string &dispname,
size_type region);
773 (ga_workspace &workspace,
const std::string &transname,
const mesh &m,
774 const std::string &dispname,
size_type region);
781 (ga_workspace &workspace,
const std::string &transname,
const mesh &m,
782 const std::string &dispname,
size_type region);
792 (model &md,
const std::string &transname,
800 (ga_workspace &workspace,
const std::string &transname,
813 (model &md,
const std::string &transname, scalar_type release_distance);
819 (ga_workspace &workspace,
const std::string &transname,
820 scalar_type release_distance);
827 (model &md,
const std::string &transname,
const mesh &m,
828 const std::string &dispname,
size_type region);
834 (ga_workspace &workspace,
const std::string &transname,
const mesh &m,
835 const std::string &dispname,
size_type region);
842 (model &md,
const std::string &transname,
const mesh &m,
843 const std::string &dispname,
size_type region);
850 (ga_workspace &workspace,
const std::string &transname,
const mesh &m,
851 const std::string &dispname,
size_type region);
861 (model &md,
const std::string &transname,
869 (ga_workspace &workspace,
const std::string &transname,
region-tree for window/point search on a set of rectangles.
Balanced tree of n-dimensional rectangles.
Describe a finite element method linked to a mesh.
Describe an integration method linked to a mesh.
Generic assembly implementation.
Model representation in Getfem.
void copy(const L1 &l1, L2 &l2)
*/
number_traits< typename linalg_traits< V >::value_type >::magnitude_type vect_norm2(const V &v)
Euclidean norm of a vector.
void clear(L &l)
clear (fill with zeros) a vector or matrix.
void resize(V &v, size_type n)
*/
strongest_value_type< V1, V2 >::value_type vect_sp(const V1 &v1, const V2 &v2)
*/
void add(const L1 &l1, L2 &l2)
*/
gmm::uint16_type short_type
used as the common short type integer in the library
base_small_vector compute_normal(const geotrans_interpolation_context &c, size_type face)
norm of returned vector is the ratio between the face surface on the real element and the face surfac...
size_t size_type
used as the common size type in the library
GEneric Tool for Finite Element Methods.
void add_rigid_obstacle_to_raytracing_transformation(model &md, const std::string &transname, const std::string &expr, size_type N)
Add a rigid obstacle whose geometry corresponds to the zero level-set of the high-level generic assem...
void add_master_contact_boundary_to_projection_transformation(model &md, const std::string &transname, const mesh &m, const std::string &dispname, size_type region)
Add a master boundary with corresponding displacement variable 'dispname' on a specific boundary 'reg...
void add_raytracing_transformation(model &md, const std::string &transname, scalar_type release_distance)
Add a raytracing interpolate transformation called 'transname' to a model to be used by the generic a...
void add_rigid_obstacle_to_projection_transformation(model &md, const std::string &transname, const std::string &expr, size_type N)
Add a rigid obstacle whose geometry corresponds to the zero level-set of the high-level generic assem...
void add_master_contact_boundary_to_raytracing_transformation(model &md, const std::string &transname, const mesh &m, const std::string &dispname, size_type region)
Add a master boundary with corresponding displacement variable 'dispname' on a specific boundary 'reg...
void add_projection_transformation(model &md, const std::string &transname, scalar_type release_distance)
Add a projection interpolate transformation called 'transname' to a model to be used by the generic a...
void add_slave_contact_boundary_to_projection_transformation(model &md, const std::string &transname, const mesh &m, const std::string &dispname, size_type region)
Add a slave boundary with corresponding displacement variable 'dispname' on a specific boundary 'regi...
void add_slave_contact_boundary_to_raytracing_transformation(model &md, const std::string &transname, const mesh &m, const std::string &dispname, size_type region)
Add a slave boundary with corresponding displacement variable 'dispname' on a specific boundary 'regi...