38 #ifndef GETFEM_CONTACT_AND_FRICTION_COMMON_H__
39 #define GETFEM_CONTACT_AND_FRICTION_COMMON_H__
55 template<
typename VEC>
void ball_projection(
const VEC &x,
57 if (radius <= scalar_type(0))
61 if (a > radius) gmm::scale(
const_cast<VEC&
>(x), radius/a);
65 template<
typename VEC,
typename VECR>
66 void ball_projection_grad_r(
const VEC &x, scalar_type radius,
68 if (radius > scalar_type(0)) {
71 gmm::copy(x, g); gmm::scale(g, scalar_type(1)/a);
78 template <
typename VEC,
typename MAT>
79 void ball_projection_grad(
const VEC &x, scalar_type radius, MAT &g) {
80 if (radius <= scalar_type(0)) {
gmm::clear(g);
return; }
81 gmm::copy(gmm::identity_matrix(), g);
84 gmm::scale(g, radius/a);
88 g(i,j) -= radius*x[i]*x[j] / (a*a*a);
92 template <
typename VEC,
typename VECR>
93 void coupled_projection(
const VEC &x,
const VEC &n,
94 scalar_type f, VECR &g) {
95 scalar_type xn = gmm::vect_sp(x, n);
96 scalar_type xnm = gmm::neg(xn);
97 scalar_type th = f * xnm;
98 scalar_type xtn = gmm::sqrt(gmm::vect_norm2_sqr(x) - xn*xn);
100 gmm::copy(gmm::scaled(n, -xnm), g);
101 if (th > scalar_type(0)) {
104 gmm::add(gmm::scaled(n, -xn), g);
106 gmm::add(gmm::scaled(x, f*xnm/xtn), g);
107 gmm::add(gmm::scaled(n, -f*xnm*xn/xtn), g);
113 template <
typename VEC,
typename MAT>
114 void coupled_projection_grad(
const VEC &x,
const VEC &n,
115 scalar_type f, MAT &g) {
116 scalar_type xn = gmm::vect_sp(x, n);
117 scalar_type xnm = gmm::neg(xn);
118 scalar_type th = f * xnm;
119 scalar_type xtn = gmm::sqrt(gmm::vect_norm2_sqr(x) - xn*xn);
123 if (th > scalar_type(0)) {
125 gmm::copy(gmm::identity_matrix(), g);
126 gmm::rank_one_update(g, gmm::scaled(n, -scalar_type(1)), n);
127 }
else if (xn < scalar_type(0)) {
129 gmm::add(x, gmm::scaled(n, -xn), t);
130 gmm::scale(t, scalar_type(1)/xtn);
132 gmm::copy(gmm::identity_matrix(), g);
133 gmm::rank_one_update(g, gmm::scaled(t, -scalar_type(1)), t);
134 gmm::rank_one_update(g, gmm::scaled(n, -scalar_type(1)), n);
135 gmm::scale(g, -xn*th/xtn);
137 gmm::rank_one_update(g, gmm::scaled(t, -f), n);
141 if (xn < scalar_type(0)) gmm::rank_one_update(g, n, n);
151 template<
typename VEC>
152 void De_Saxce_projection(
const VEC &x,
const VEC &n_, scalar_type f) {
153 static base_small_vector n;
156 gmm::copy(gmm::scaled(n_, scalar_type(1)/gmm::vect_norm2(n_)), n);
157 scalar_type xn = gmm::vect_sp(x, n);
158 scalar_type nxt = sqrt(gmm::abs(gmm::vect_norm2_sqr(x) - xn*xn));
159 if (xn >= scalar_type(0) && f * nxt <= xn) {
161 }
else if (xn > scalar_type(0) || nxt > -f*xn) {
162 gmm::add(gmm::scaled(n, -xn),
const_cast<VEC&
>(x));
163 gmm::scale(
const_cast<VEC&
>(x), -f / nxt);
164 gmm::add(n,
const_cast<VEC&
>(x));
165 gmm::scale(
const_cast<VEC&
>(x), (xn - f * nxt) / (f*f+scalar_type(1)));
169 template<
typename VEC,
typename MAT>
170 void De_Saxce_projection_grad(
const VEC &x,
const VEC &n_,
171 scalar_type f, MAT &g) {
172 static base_small_vector n;
175 gmm::copy(gmm::scaled(n_, scalar_type(1)/gmm::vect_norm2(n_)), n);
176 scalar_type xn = gmm::vect_sp(x, n);
177 scalar_type nxt = sqrt(gmm::abs(gmm::vect_norm2_sqr(x) - xn*xn));
180 if (xn > scalar_type(0) && f * nxt <= xn) {
182 }
else if (xn > scalar_type(0) || nxt > -f*xn) {
183 static base_small_vector xt;
185 gmm::add(x, gmm::scaled(n, -xn), xt);
186 gmm::scale(xt, scalar_type(1)/nxt);
189 gmm::copy(gmm::identity_matrix(), g);
190 gmm::rank_one_update(g, gmm::scaled(n, -scalar_type(1)), n);
191 gmm::rank_one_update(g, gmm::scaled(xt, -scalar_type(1)), xt);
192 gmm::scale(g, f*(f - xn/nxt));
197 gmm::scale(xt, -f); gmm::add(n, xt);
198 gmm::rank_one_update(g, xt, xt);
199 gmm::scale(g, scalar_type(1) / (f*f+scalar_type(1)));
201 gmm::copy(gmm::identity_matrix(), g);
206 template<
typename VEC,
typename MAT>
207 static void De_Saxce_projection_gradn(
const VEC &x,
const VEC &n_,
208 scalar_type f, MAT &g) {
209 static base_small_vector n;
213 gmm::copy(gmm::scaled(n_, scalar_type(1)/nn), n);
214 scalar_type xn = gmm::vect_sp(x, n);
215 scalar_type nxt = sqrt(gmm::abs(gmm::vect_norm2_sqr(x) - xn*xn));
218 if (!(xn > scalar_type(0) && f * nxt <= xn)
219 && (xn > scalar_type(0) || nxt > -f*xn)) {
220 static base_small_vector xt, aux;
222 gmm::add(x, gmm::scaled(n, -xn), xt);
223 gmm::scale(xt, scalar_type(1)/nxt);
225 scalar_type c = (scalar_type(1) + f*xn/nxt)/nn;
226 for (
size_type i = 0; i < N; ++i) g(i,i) = c;
227 gmm::rank_one_update(g, gmm::scaled(n, -c), n);
228 gmm::rank_one_update(g, gmm::scaled(n, f/nn), xt);
229 gmm::rank_one_update(g, gmm::scaled(xt, -f*xn/(nn*nxt)), xt);
230 gmm::scale(g, xn - f*nxt);
232 gmm::add(gmm::scaled(xt, -f), n, aux);
233 gmm::rank_one_update(g, aux, gmm::scaled(xt, (nxt+f*xn)/nn));
235 gmm::scale(g, scalar_type(1) / (f*f+scalar_type(1)));
245 template <
typename MAT1,
typename MAT2>
246 void mat_elem_assembly(
const MAT1 &M_,
const MAT2 &Melem,
249 MAT1 &M =
const_cast<MAT1 &
>(M_);
250 typedef typename gmm::linalg_traits<MAT1>::value_type T;
252 mesh_fem::ind_dof_ct cvdof1 = mf1.ind_basic_dof_of_element(cv1);
253 mesh_fem::ind_dof_ct cvdof2 = mf2.ind_basic_dof_of_element(cv2);
255 GMM_ASSERT1(cvdof1.size() == gmm::mat_nrows(Melem)
256 && cvdof2.size() == gmm::mat_ncols(Melem),
257 "Dimensions mismatch");
259 if (mf1.is_reduced()) {
260 if (mf2.is_reduced()) {
261 for (
size_type i = 0; i < cvdof1.size(); ++i)
262 for (
size_type j = 0; j < cvdof2.size(); ++j)
263 if ((val = Melem(i,j)) != T(0))
265 (M, gmm::mat_row(mf1.extension_matrix(), cvdof1[i]),
266 gmm::mat_row(mf2.extension_matrix(), cvdof2[j]), val);
268 for (
size_type i = 0; i < cvdof1.size(); ++i)
269 for (
size_type j = 0; j < cvdof2.size(); ++j)
270 if ((val = Melem(i,j)) != T(0))
272 (M, gmm::mat_row(mf1.extension_matrix(), cvdof1[i]),
276 if (mf2.is_reduced()) {
277 for (
size_type i = 0; i < cvdof1.size(); ++i)
278 for (
size_type j = 0; j < cvdof2.size(); ++j)
279 if ((val = Melem(i,j)) != T(0))
282 gmm::mat_row(mf2.extension_matrix(), cvdof2[j]), val);
284 for (
size_type i = 0; i < cvdof1.size(); ++i)
285 for (
size_type j = 0; j < cvdof2.size(); ++j)
286 if ((val = Melem(i,j)) != T(0))
287 M(cvdof1[i], cvdof2[j]) += val;
293 template <
typename VEC1,
typename VEC2>
294 void vec_elem_assembly(
const VEC1 &V_,
const VEC2 &Velem,
296 VEC1 &V =
const_cast<VEC1 &
>(V_);
297 typedef typename gmm::linalg_traits<VEC1>::value_type T;
298 std::vector<size_type> cvdof(mf.ind_basic_dof_of_element(cv).begin(),
299 mf.ind_basic_dof_of_element(cv).end());
301 GMM_ASSERT1(cvdof.size() == gmm::vect_size(Velem),
"Dimensions mismatch");
303 if (mf.is_reduced()) {
305 for (
size_type i = 0; i < cvdof.size(); ++i)
306 if ((val = Velem[i]) != T(0))
307 gmm::add(gmm::scaled(gmm::mat_row(mf.extension_matrix(), cvdof[i]),
310 for (
size_type i = 0; i < cvdof.size(); ++i) V[cvdof[i]] += Velem[i];
314 template <
typename MAT1,
typename MAT2>
315 void mat_elem_assembly(
const MAT1 &M_,
const gmm::sub_interval &I1,
316 const gmm::sub_interval &I2,
320 MAT1 &M =
const_cast<MAT1 &
>(M_);
321 typedef typename gmm::linalg_traits<MAT1>::value_type T;
324 mesh_fem::ind_dof_ct cvdof1 = mf1.ind_basic_dof_of_element(cv1);
325 mesh_fem::ind_dof_ct cvdof2 = mf2.ind_basic_dof_of_element(cv2);
327 GMM_ASSERT1(cvdof1.size() == gmm::mat_nrows(Melem)
328 && cvdof2.size() == gmm::mat_ncols(Melem),
329 "Dimensions mismatch");
331 if (mf1.is_reduced()) {
332 if (mf2.is_reduced()) {
333 for (
size_type i = 0; i < cvdof1.size(); ++i)
334 for (
size_type j = 0; j < cvdof2.size(); ++j)
335 if ((val = Melem(i,j)) != T(0))
337 (gmm::sub_matrix(M, I1, I2),
338 gmm::mat_row(mf1.extension_matrix(), cvdof1[i]),
339 gmm::mat_row(mf2.extension_matrix(), cvdof2[j]), val);
341 for (
size_type i = 0; i < cvdof1.size(); ++i)
342 for (
size_type j = 0; j < cvdof2.size(); ++j)
343 if ((val = Melem(i,j)) != T(0))
345 (gmm::sub_matrix(M, I1, I2),
346 gmm::mat_row(mf1.extension_matrix(), cvdof1[i]),
350 if (mf2.is_reduced()) {
351 for (
size_type i = 0; i < cvdof1.size(); ++i)
352 for (
size_type j = 0; j < cvdof2.size(); ++j)
353 if ((val = Melem(i,j)) != T(0))
355 (gmm::sub_matrix(M, I1, I2), cvdof1[i],
356 gmm::mat_row(mf2.extension_matrix(), cvdof2[j]), val);
358 for (
size_type i = 0; i < cvdof1.size(); ++i)
359 for (
size_type j = 0; j < cvdof2.size(); ++j)
360 if ((val = Melem(i,j)) != T(0))
361 M(cvdof1[i]+I1.first(), cvdof2[j]+I2.first()) += val;
366 template <
typename VEC1,
typename VEC2>
367 void vec_elem_assembly(
const VEC1 &V_,
const gmm::sub_interval &I,
368 const VEC2 &Velem,
const mesh_fem &mf,
size_type cv) {
369 VEC1 &V =
const_cast<VEC1 &
>(V_);
370 typedef typename gmm::linalg_traits<VEC1>::value_type T;
371 std::vector<size_type> cvdof(mf.ind_basic_dof_of_element(cv).begin(),
372 mf.ind_basic_dof_of_element(cv).end());
374 GMM_ASSERT1(cvdof.size() == gmm::vect_size(Velem),
"Dimensions mismatch");
376 if (mf.is_reduced()) {
378 for (
size_type i = 0; i < cvdof.size(); ++i)
379 if ((val = Velem[i]) != T(0))
380 gmm::add(gmm::scaled(gmm::mat_row(mf.extension_matrix(), cvdof[i]),
381 val), gmm::sub_vector(V, I));
383 for (
size_type i = 0; i < cvdof.size(); ++i)
384 V[I.first()+cvdof[i]] += Velem[i];
390 bool in_reference_conf,
const model_real_plain_vector &coeff,
391 base_node &n0, base_node &n, base_matrix &grad);
403 class multi_contact_frame {
406 struct contact_boundary {
411 std::string multname;
416 contact_boundary(
void) {}
417 contact_boundary(
size_type r,
const mesh_fem *mf,
418 const mesh_im &mi,
size_type i_U,
const mesh_fem *mfl,
420 : region(r), mfu(mf), mflambda(mfl), mim(&mi),
421 ind_U(i_U), ind_lambda(i_l), slave(false) {}
438 scalar_type release_distance;
443 scalar_type cut_angle;
448 typedef model_real_plain_vector VECTOR;
449 std::vector<const VECTOR *> Us;
450 std::vector<const VECTOR *> Ws;
451 std::vector<std::string> Unames;
452 std::vector<std::string> Wnames;
453 std::vector<VECTOR> ext_Us;
454 std::vector<VECTOR> ext_Ws;
455 std::vector<const VECTOR *> lambdas;
456 std::vector<std::string> lambdanames;
457 std::vector<VECTOR> ext_lambdas;
459 std::vector<contact_boundary> contact_boundaries;
461 std::vector<std::string> coordinates;
462 model_real_plain_vector pt, ptx, pty, ptz, ptw;
463 std::list<ga_workspace> obstacles_gw;
464 std::vector<ga_function> obstacles_f;
465 std::vector<std::string> obstacles;
466 std::vector<std::string> obstacles_velocities;
469 struct normal_cone :
public std::vector<base_small_vector> {
471 void add_normal(
const base_small_vector &n)
472 { std::vector<base_small_vector>::push_back(n);}
474 normal_cone(
const base_small_vector &n)
475 : std::vector<base_small_vector>(1, n) { }
481 struct influence_box {
485 base_small_vector mean_normal;
486 influence_box(
void) {}
489 : ind_boundary(ib), ind_element(ie), ind_face(iff), mean_normal(n) {}
493 std::vector<influence_box> element_boxes_info;
499 struct boundary_point {
507 boundary_point(
void) {}
510 : ref_point(rp), ind_boundary(ib), ind_element(ie), ind_face(iff),
511 ind_pt(id), normals(n) {}
514 std::vector<base_node> boundary_points;
515 std::vector<boundary_point> boundary_points_info;
518 size_type add_U(
const model_real_plain_vector *U,
const std::string &name,
519 const model_real_plain_vector *w,
const std::string &wname);
520 size_type add_lambda(
const model_real_plain_vector *lambda,
521 const std::string &name);
523 void extend_vectors(
void);
525 void normal_cone_simplification(
void);
527 bool test_normal_cones_compatibility(
const normal_cone &nc1,
528 const normal_cone &nc2);
530 bool test_normal_cones_compatibility(
const base_small_vector &n,
531 const normal_cone &nc2);
533 dal::bit_vector aux_dof_cv;
549 : ind_boundary(ib), ind_element(ie), ind_face(iff) {}
554 std::vector<std::vector<face_info> > potential_pairs;
561 struct contact_pair {
563 base_node slave_point;
564 base_small_vector slave_n;
571 base_node master_point_ref;
572 base_node master_point;
573 base_small_vector master_n;
578 scalar_type signed_dist;
582 contact_pair(
void) {}
583 contact_pair(
const base_node &spt,
const base_small_vector &nx,
584 const boundary_point &bp,
585 const base_node &mptr,
const base_node &mpt,
586 const base_small_vector &ny,
587 const face_info &mfi, scalar_type sd)
588 : slave_point(spt), slave_n(nx),
589 slave_ind_boundary(bp.ind_boundary), slave_ind_element(bp.ind_element),
590 slave_ind_face(bp.ind_face), slave_ind_pt(bp.ind_pt),
591 master_point_ref(mptr), master_point(mpt), master_n(ny),
592 master_ind_boundary(mfi.ind_boundary), master_ind_element(mfi.ind_element),
593 master_ind_face(mfi.ind_face),
594 signed_dist(sd), irigid_obstacle(
size_type(-1)) {}
595 contact_pair(
const base_node &spt,
const base_small_vector &nx,
596 const boundary_point &bp,
597 const base_node &mpt,
const base_small_vector &ny,
599 : slave_point(spt), slave_n(nx), slave_ind_boundary(bp.ind_boundary),
600 slave_ind_element(bp.ind_element), slave_ind_face(bp.ind_face),
601 slave_ind_pt(bp.ind_pt), master_point(mpt), master_n(ny),
603 irigid_obstacle(ir) {}
611 void compute_influence_boxes(
void);
621 void compute_boundary_points(
bool slave_only =
false);
622 void compute_potential_contact_pairs_delaunay(
void);
623 void compute_potential_contact_pairs_influence_boxes(
void);
627 std::vector<contact_pair> contact_pairs;
629 void clear_aux_info(
void);
634 const std::vector<contact_pair> &ct_pairs(
void)
const
635 {
return contact_pairs; }
639 {
return *(contact_boundaries[n].mfu); }
641 {
return *(contact_boundaries[n].mflambda); }
643 {
return *(contact_boundaries[n].mim); }
644 size_type nb_variables(
void)
const {
return Us.size(); }
645 size_type nb_multipliers(
void)
const {
return lambdas.size(); }
646 const std::string &varname(
size_type i)
const {
return Unames[i]; }
647 const std::string &multname(
size_type i)
const {
return lambdanames[i]; }
648 const model_real_plain_vector &disp_of_boundary(
size_type n)
const
649 {
return ext_Us[contact_boundaries[n].ind_U]; }
650 const model_real_plain_vector &disp0_of_boundary(
size_type n)
const
651 {
return ext_Ws[contact_boundaries[n].ind_U]; }
652 const model_real_plain_vector &mult_of_boundary(
size_type n)
const
653 {
return ext_lambdas[contact_boundaries[n].ind_lambda]; }
655 {
return contact_boundaries[n].region; }
656 const std::string &varname_of_boundary(
size_type n)
const
657 {
return Unames[contact_boundaries[n].ind_U]; }
659 {
return contact_boundaries[n].ind_U; }
660 const std::string &multname_of_boundary(
size_type n)
const {
661 static const std::string vname;
662 size_type ind = contact_boundaries[n].ind_lambda;
663 return (ind ==
size_type(-1)) ? vname : lambdanames[ind];
666 {
return contact_boundaries[n].ind_lambda; }
667 size_type nb_boundaries(
void)
const {
return contact_boundaries.size(); }
668 bool is_self_contact(
void)
const {
return self_contact; }
669 bool is_slave_boundary(
size_type n)
const {
return contact_boundaries[n].slave; }
670 void set_raytrace(
bool b) { raytrace = b; }
671 void set_nodes_mode(
int m) { nodes_mode = m; }
672 size_type nb_contact_pairs(
void)
const {
return contact_pairs.size(); }
673 const contact_pair &get_contact_pair(
size_type i)
674 {
return contact_pairs[i]; }
676 multi_contact_frame(
size_type NN, scalar_type r_dist,
677 bool dela =
true,
bool selfc =
true,
678 scalar_type cut_a = 0.3,
bool rayt =
false,
679 int fem_nodes = 0,
bool refc =
false);
680 multi_contact_frame(
const model &md,
size_type NN, scalar_type r_dist,
681 bool dela =
true,
bool selfc =
true,
682 scalar_type cut_a = 0.3,
bool rayt =
false,
683 int fem_nodes = 0,
bool refc =
false);
685 size_type add_obstacle(
const std::string &obs);
689 const model_real_plain_vector *U,
692 const model_real_plain_vector *lambda = 0,
693 const model_real_plain_vector *w = 0,
694 const std::string &varname = std::string(),
695 const std::string &multname = std::string(),
696 const std::string &wname = std::string());
699 const std::string &varname,
700 const std::string &multname = std::string(),
701 const std::string &wname = std::string());
706 const model_real_plain_vector *U,
709 const model_real_plain_vector *lambda = 0,
710 const model_real_plain_vector *w = 0,
711 const std::string &varname = std::string(),
712 const std::string &multname = std::string(),
713 const std::string &wname = std::string());
716 const std::string &varname,
717 const std::string &multname = std::string(),
718 const std::string &wname = std::string());
728 void compute_contact_pairs(
void);
744 (model &md,
const std::string &transname, scalar_type release_distance);
750 (ga_workspace &workspace,
const std::string &transname,
751 scalar_type release_distance);
758 (model &md,
const std::string &transname,
const mesh &m,
759 const std::string &dispname,
size_type region);
766 (model &md,
const std::string &transname,
const mesh &m,
767 const std::string &dispname,
size_type region);
774 (ga_workspace &workspace,
const std::string &transname,
const mesh &m,
775 const std::string &dispname,
size_type region);
782 (ga_workspace &workspace,
const std::string &transname,
const mesh &m,
783 const std::string &dispname,
size_type region);
793 (model &md,
const std::string &transname,
801 (ga_workspace &workspace,
const std::string &transname,
814 (model &md,
const std::string &transname, scalar_type release_distance);
820 (ga_workspace &workspace,
const std::string &transname,
821 scalar_type release_distance);
828 (model &md,
const std::string &transname,
const mesh &m,
829 const std::string &dispname,
size_type region);
835 (ga_workspace &workspace,
const std::string &transname,
const mesh &m,
836 const std::string &dispname,
size_type region);
843 (model &md,
const std::string &transname,
const mesh &m,
844 const std::string &dispname,
size_type region);
851 (ga_workspace &workspace,
const std::string &transname,
const mesh &m,
852 const std::string &dispname,
size_type region);
862 (model &md,
const std::string &transname,
870 (ga_workspace &workspace,
const std::string &transname,