@@ -164,7 +164,7 @@ Eigen::VectorXd FrictionPotential::smooth_contact_force(
164164
165165    tbb::enumerable_thread_specific<Eigen::VectorXd> storage (
166166        Eigen::VectorXd::Zero (velocities.size ()));
167-      
167+ 
168168    tbb::parallel_for (
169169        tbb::blocked_range<size_t >(size_t (0 ), collisions.size ()),
170170        [&](const  tbb::blocked_range<size_t >& r) {
@@ -176,8 +176,8 @@ Eigen::VectorXd FrictionPotential::smooth_contact_force(
176176                    local_force = smooth_contact_force (
177177                        collision, collision.dof (rest_positions, edges, faces),
178178                        collision.dof (lagged_displacements, edges, faces),
179-                         collision.dof (velocities, edges, faces),  // 
180-                         dmin,  no_mu);
179+                         collision.dof (velocities, edges, faces),
180+                         no_mu);
181181
182182                const  std::array<long , 4 > vis =
183183                    collision.vertex_ids (mesh.edges (), mesh.faces ());
@@ -197,7 +197,7 @@ Eigen::SparseMatrix<double> FrictionPotential::smooth_contact_force_jacobian(
197197    const  Eigen::MatrixXd& rest_positions,
198198    const  Eigen::MatrixXd& lagged_displacements,
199199    const  Eigen::MatrixXd& velocities,
200-     const  ParameterType & params,
200+     const  ParameterType&  params,
201201    const  DiffWRT wrt,
202202    const  double  dmin) const 
203203{
@@ -213,6 +213,8 @@ Eigen::SparseMatrix<double> FrictionPotential::smooth_contact_force_jacobian(
213213    tbb::enumerable_thread_specific<std::vector<Eigen::Triplet<double >>>
214214        storage;
215215
216+     const  Eigen::MatrixXd lagged_positions = rest_positions + lagged_displacements;
217+ 
216218    tbb::parallel_for (
217219        tbb::blocked_range<size_t >(size_t (0 ), collisions.size ()),
218220        [&](const  tbb::blocked_range<size_t >& r) {
@@ -221,15 +223,22 @@ Eigen::SparseMatrix<double> FrictionPotential::smooth_contact_force_jacobian(
221223            for  (size_t  i = r.begin (); i < r.end (); i++) {
222224                const  FrictionCollision& collision = collisions[i];
223225
224-                 //  This jacobian doesn't include the derivatives of normal contact force
226+                 //  This jacobian doesn't include the derivatives of normal
227+                 //  contact force
225228                const  MatrixMax<
226229                    double , FrictionPotential::element_size,
227230                    FrictionPotential::element_size>
228-                     local_force_jacobian = smooth_contact_force_jacobian (
229-                         collision, collision.dof (rest_positions, edges, faces),
230-                         collision.dof (lagged_displacements, edges, faces),
231-                         collision.dof (velocities, edges, faces), // 
232-                         wrt, dmin);
231+                     local_force_jacobian =
232+                         collision.normal_force_magnitude 
233+                     * force_jacobian_unit (
234+                             collision,
235+                             collision.dof (lagged_positions, edges, faces),
236+                             collision.dof (velocities, edges, faces), wrt);
237+                 //  smooth_contact_force_jacobian(
238+                 //      collision, collision.dof(rest_positions, edges, faces),
239+                 //      collision.dof(lagged_displacements, edges, faces),
240+                 //      collision.dof(velocities, edges, faces), //
241+                 //      wrt);
233242
234243                const  std::array<long , 4 > vis =
235244                    collision.vertex_ids (mesh.edges (), mesh.faces ());
@@ -245,35 +254,42 @@ Eigen::SparseMatrix<double> FrictionPotential::smooth_contact_force_jacobian(
245254                    local_force = smooth_contact_force (
246255                        collision, collision.dof (rest_positions, edges, faces),
247256                        collision.dof (lagged_displacements, edges, faces),
248-                         collision.dof (velocities, edges, faces), // 
249-                         dmin, false );
250-                 
251-                 std::cout << " local fric force " transpose () << " \n\n " 
257+                         collision.dof (velocities, edges, faces),
258+                         false , true );
252259
260+                 //  normal_force_grad is the gradient of contact force norm
253261                Eigen::VectorXd normal_force_grad;
254262                std::vector<long > cc_vert_ids;
255-                 Eigen::MatrixXd Xt = rest_positions + lagged_displacements;
256-                 if  (dim == 2 )
257-                 {
258-                     auto  cc = collision.smooth_collision_2d ;
259-                     const  Eigen::VectorXd contact_grad = cc->gradient (cc->dof (Xt, edges, faces), params);
260-                     const  Eigen::MatrixXd contact_hess = cc->hessian (cc->dof (Xt, edges, faces), params);
261-                     normal_force_grad = (1  / contact_grad.squaredNorm ()) * (contact_hess * contact_grad);
262-                     auto  tmp_ids = cc->vertex_ids (edges, faces);
263-                     cc_vert_ids = std::vector (tmp_ids.begin (), tmp_ids.end ());
264-                 }
265-                 else  if  (dim == 3 )
266263                {
267-                     auto  cc = collision.smooth_collision_3d ;
268-                     const  Eigen::VectorXd contact_grad = cc->gradient (cc->dof (Xt, edges, faces), params);
269-                     const  Eigen::MatrixXd contact_hess = cc->hessian (cc->dof (Xt, edges, faces), params);
270-                     normal_force_grad = (1  / contact_grad.squaredNorm ()) * (contact_hess * contact_grad);
271-                     auto  tmp_ids = cc->vertex_ids (edges, faces);
272-                     cc_vert_ids = std::vector (tmp_ids.begin (), tmp_ids.end ());
264+                     Eigen::MatrixXd Xt = rest_positions + lagged_displacements;
265+                     if  (dim == 2 ) {
266+                         auto  cc = collision.smooth_collision_2d ;
267+                         const  Eigen::VectorXd contact_grad =
268+                             cc->gradient (cc->dof (Xt, edges, faces), params);
269+                         const  Eigen::MatrixXd contact_hess =
270+                             cc->hessian (cc->dof (Xt, edges, faces), params);
271+                         normal_force_grad = (1  / contact_grad.norm ())
272+                             * (contact_hess * contact_grad);
273+                         auto  tmp_ids = cc->vertex_ids (edges, faces);
274+                         cc_vert_ids =
275+                             std::vector (tmp_ids.begin (), tmp_ids.end ());
276+                     } else  if  (dim == 3 ) {
277+                         auto  cc = collision.smooth_collision_3d ;
278+                         const  Eigen::VectorXd contact_grad =
279+                             cc->gradient (cc->dof (Xt, edges, faces), params);
280+                         const  Eigen::MatrixXd contact_hess =
281+                             cc->hessian (cc->dof (Xt, edges, faces), params);
282+                         normal_force_grad = (1  / contact_grad.norm ())
283+                             * (contact_hess * contact_grad);
284+                         auto  tmp_ids = cc->vertex_ids (edges, faces);
285+                         cc_vert_ids =
286+                             std::vector (tmp_ids.begin (), tmp_ids.end ());
287+                     }
273288                }
274289
275290                local_jacobian_to_global_triplets (
276-                     local_force * normal_force_grad.transpose (), vis, cc_vert_ids, dim, jac_triplets);
291+                     local_force * normal_force_grad.transpose (), vis,
292+                     cc_vert_ids, dim, jac_triplets);
277293            }
278294        });
279295
@@ -291,10 +307,12 @@ Eigen::SparseMatrix<double> FrictionPotential::smooth_contact_force_jacobian(
291307    //  if (wrt == DiffWRT::REST_POSITIONS) {
292308    //      for (int i = 0; i < collisions.size(); i++) {
293309    //          const FrictionCollision& collision = collisions[i];
294-     //          assert(collision.weight_gradient.size() == rest_positions.size());
295-     //          if (collision.weight_gradient.size() != rest_positions.size()) {
310+     //          assert(collision.weight_gradient.size() ==
311+     //          rest_positions.size()); if (collision.weight_gradient.size() !=
312+     //          rest_positions.size()) {
296313    //              throw std::runtime_error(
297-     //                  "Shape derivative is not computed for friction collision!");
314+     //                  "Shape derivative is not computed for friction
315+     //                  collision!");
298316    //          }
299317
300318    //          Vector<double, -1, FrictionPotential::element_size> local_force =
@@ -564,6 +582,87 @@ FrictionPotential::force_jacobian(
564582    //  Compute β
565583    const  VectorMax2d beta = collision.compute_closest_point (lagged_positions);
566584
585+     //  Compute Γ
586+     const  MatrixMax<double , 3 , FrictionPotential::element_size> Gamma =
587+         collision.relative_velocity_matrix (beta);
588+ 
589+     //  Compute T = ΓᵀP
590+     const  MatrixMax<double , FrictionPotential::element_size, 2 > T =
591+         Gamma.transpose () * P;
592+ 
593+     //  Compute τ = PᵀΓv
594+     const  VectorMax2d tau = P.transpose () * Gamma * velocities;
595+ 
596+     //  Compute f₁(‖τ‖)/‖τ‖
597+     const  double  tau_norm = tau.norm ();
598+     const  double  f1_over_norm_tau = f1_SF_over_x (tau_norm, epsv ());
599+ 
600+     //  Premultiplied values
601+     const  Vector<double , -1 , FrictionPotential::element_size> T_times_tau =
602+         T * tau;
603+ 
604+     //  ------------------------------------------------------------------------
605+     //  Compute J = ∇F = ∇(-μ N f₁(‖τ‖)/‖τ‖ T τ)
606+     MatrixMax<
607+         double , FrictionPotential::element_size,
608+         FrictionPotential::element_size>
609+         J = MatrixMax<
610+             double , FrictionPotential::element_size,
611+             FrictionPotential::element_size>::Zero (n, n);
612+ 
613+     //  = -μ f₁(‖τ‖)/‖τ‖ (T τ) [∇N]ᵀ
614+     if  (need_jac_N_or_T) {
615+         J = f1_over_norm_tau * T_times_tau * grad_N.transpose ();
616+     }
617+ 
618+     //  NOTE: ∇ₓw(x) is not local to the collision pair (i.e., it involves more
619+     //  than the 4 collisioning vertices), so we do not have enough information
620+     //  here to compute the gradient. Instead this should be handled outside of
621+     //  the function. For a simple multiplicitive model (∑ᵢ wᵢ Fᵢ) this can be
622+     //  done easily.
623+     J *= -collision.weight  * collision.mu ;
624+ 
625+     J += N
626+         * force_jacobian_unit (
627+              collision, lagged_positions, velocities, wrt);
628+ 
629+     return  J;
630+ }
631+ 
632+ MatrixMax<
633+     double ,
634+     FrictionPotential::element_size,
635+     FrictionPotential::element_size>
636+ FrictionPotential::force_jacobian_unit (
637+     const  FrictionCollision& collision,
638+     const  Vector<double , -1 , FrictionPotential::element_size>&
639+         lagged_positions, //  = x + u^t
640+     const  Vector<double , -1 , FrictionPotential::element_size>&
641+         velocities, //  = v
642+     const  DiffWRT wrt) const 
643+ {
644+     //  x is the rest position
645+     //  u is the displacment at the begginging of the lagged solve
646+     //  v is the current velocity
647+     // 
648+     //  τ = T(x + u)ᵀv is the tangential sliding velocity
649+     //  F(x, u, v) = -μ f₁(‖τ‖)/‖τ‖ T(x + u) τ
650+     // 
651+     //  Compute ∇F
652+     assert (lagged_positions.size () == velocities.size ());
653+     const  int  n = lagged_positions.size ();
654+     const  int  dim = n / collision.num_vertices ();
655+     assert (n % collision.num_vertices () == 0 );
656+ 
657+     const  bool  need_jac_N_or_T = wrt != DiffWRT::VELOCITIES;
658+ 
659+     //  Compute P
660+     const  MatrixMax<double , 3 , 2 > P =
661+         collision.compute_tangent_basis (lagged_positions);
662+ 
663+     //  Compute β
664+     const  VectorMax2d beta = collision.compute_closest_point (lagged_positions);
665+ 
567666    //  Compute Γ
568667    const  MatrixMax<double , 3 , FrictionPotential::element_size> Gamma =
569668        collision.relative_velocity_matrix (beta);
@@ -653,25 +752,20 @@ FrictionPotential::force_jacobian(
653752            double , FrictionPotential::element_size,
654753            FrictionPotential::element_size>::Zero (n, n);
655754
656-     //  = -μ f₁(‖τ‖)/‖τ‖ (T τ) [∇N]ᵀ
657-     if  (need_jac_N_or_T) {
658-         J = f1_over_norm_tau * T_times_tau * grad_N.transpose ();
659-     }
660- 
661755    //  + -μ N T τ [∇(f₁(‖τ‖)/‖τ‖)]
662-     J += N *  T_times_tau * grad_f1_over_norm_tau.transpose ();
756+     J += T_times_tau * grad_f1_over_norm_tau.transpose ();
663757
664758    //  + -μ N f₁(‖τ‖)/‖τ‖ [∇T] τ
665759    if  (need_jac_N_or_T) {
666-         const  VectorMax2d scaled_tau = N *  f1_over_norm_tau * tau;
760+         const  VectorMax2d scaled_tau = f1_over_norm_tau * tau;
667761        for  (int  i = 0 ; i < n; i++) {
668762            //  ∂J/∂xᵢ = ∂T/∂xᵢ * τ
669763            J.col (i) += jac_T.middleRows (i * n, n) * scaled_tau;
670764        }
671765    }
672766
673767    //  + -μ N f₁(‖τ‖)/‖τ‖ T [∇τ]
674-     J += N *  f1_over_norm_tau * T * jac_tau;
768+     J += f1_over_norm_tau * T * jac_tau;
675769
676770    //  NOTE: ∇ₓw(x) is not local to the collision pair (i.e., it involves more
677771    //  than the 4 collisioning vertices), so we do not have enough information
@@ -683,16 +777,17 @@ FrictionPotential::force_jacobian(
683777    return  J;
684778}
685779
686- Vector<double , -1 , FrictionPotential::element_size> FrictionPotential::smooth_contact_force (
780+ Vector<double , -1 , FrictionPotential::element_size>
781+ FrictionPotential::smooth_contact_force (
687782    const  FrictionCollision& collision,
688783    const  Vector<double , -1 , FrictionPotential::element_size>&
689784        rest_positions, //  = x
690785    const  Vector<double , -1 , FrictionPotential::element_size>&
691786        lagged_displacements, //  = u
692787    const  Vector<double , -1 , FrictionPotential::element_size>&
693788        velocities, //  = v
694-     const  double  dmin ,
695-     const  bool  no_mu ) const 
789+     const  bool  no_mu ,
790+     const  bool  no_contact_force_multiplier ) const 
696791{
697792    //  x is the rest position
698793    //  u is the displacment at the begginging of the lagged solve
@@ -739,21 +834,19 @@ Vector<double, -1, FrictionPotential::element_size> FrictionPotential::smooth_co
739834
740835    //  F = -μ N f₁(‖τ‖)/‖τ‖ T τ
741836    //  NOTE: no_mu -> leave mu out of this function (i.e., assuming mu = 1)
742-     return  -collision.weight  * (no_mu ? 1.0  : collision.mu ) * N 
743-         * f1_over_norm_tau * T * tau;
837+     return  -collision.weight  * (no_mu ? 1.0  : collision.mu )
838+         * (no_contact_force_multiplier ?  1.0  : N) *  f1_over_norm_tau * T * tau;
744839}
745840
746- Eigen::MatrixXd
747- FrictionPotential::smooth_contact_force_jacobian (
841+ Eigen::MatrixXd FrictionPotential::smooth_contact_force_jacobian (
748842    const  FrictionCollision& collision,
749843    const  Vector<double , -1 , FrictionPotential::element_size>&
750844        rest_positions, //  = x
751845    const  Vector<double , -1 , FrictionPotential::element_size>&
752846        lagged_displacements, //  = u
753847    const  Vector<double , -1 , FrictionPotential::element_size>&
754848        velocities, //  = v
755-     const  DiffWRT wrt,
756-     const  double  dmin) const 
849+     const  DiffWRT wrt) const 
757850{
758851    //  x is the rest position
759852    //  u is the displacment at the begginging of the lagged solve
@@ -779,7 +872,7 @@ FrictionPotential::smooth_contact_force_jacobian(
779872        rest_positions + lagged_displacements; //  = x + u
780873    const  bool  need_jac_N_or_T = wrt != DiffWRT::VELOCITIES;
781874
782-     //  Compute ∇N
875+     //  Compute ∇N -- commented, compute it outside 
783876    //  Vector<double, -1, FrictionPotential::element_size> grad_N;
784877    //  if (need_jac_N_or_T) {
785878    //      // ∇ₓN = ∇ᵤN
0 commit comments