66
77#include  < ipc/ipc.hpp> 
88#include  < ipc/friction/friction_collisions.hpp> 
9+ #include  < ipc/smooth_contact/smooth_contact_potential.hpp> 
910#include  < ipc/potentials/friction_potential.hpp> 
1011
1112#include  < finitediff.hpp> 
@@ -388,12 +389,12 @@ void check_smooth_friction_force_jacobian(
388389            friction_collisions, mesh, fd::unflatten (v, velocities.cols ()));
389390    };
390391    Eigen::MatrixXd fd_hessian;
391-     fd::finite_jacobian (fd::flatten (velocities), grad, fd_hessian);
392+     fd::finite_jacobian (fd::flatten (velocities), grad, fd_hessian, fd::AccuracyOrder::FOURTH,  1e-6  * dhat );
392393    //  CHECK(fd::compare_jacobian(hess_D, fd_hessian));
393394    //  if (!fd::compare_jacobian(hess_D, fd_hessian)) {
394395    //      tests::print_compare_nonzero(hess_D, fd_hessian);
395396    //  }
396-     CHECK ((hess_D  - fd_hessian).norm () <= 1e-7  * hess_D.norm ());
397+     CHECK ((hess_D. norm () ==  0  || (hess_D  - fd_hessian).norm () <= 1e-7  * hess_D.norm () ));
397398
398399    // /////////////////////////////////////////////////////////////////////////
399400
@@ -443,60 +444,34 @@ void check_smooth_friction_force_jacobian(
443444    // /////////////////////////////////////////////////////////////////////////
444445
445446    //  test contact force norm derivative
446-     if  constexpr  (dim == 3 ) {
447-         const  Eigen::MatrixXd lagged_disp = X + Ut;
448-         Eigen::MatrixXd normal_force_jacobian = Eigen::MatrixXd::Zero (friction_collisions.size (), X.size ());
449-         for  (int  i = 0 ; i < friction_collisions.size (); i++)
447+     {
448+         const  Eigen::MatrixXd lagged_positions = X + Ut;
449+         Eigen::VectorXd normal_force_jacobian = Eigen::VectorXd::Zero (X.size ());
450450        {
451-             const  FrictionCollision& collision = friction_collisions[i];
452-             auto  cc = collision.smooth_collision_3d ;
453-             auto  tmp_ids = cc->vertex_ids (mesh.edges (), mesh.faces ());
454- 
455-             //  analytic
456-             const  Eigen::VectorXd contact_grad = cc->gradient (cc->dof (lagged_disp, mesh.edges (), mesh.faces ()), params);
457-             const  Eigen::MatrixXd contact_hess = cc->hessian (cc->dof (lagged_disp, mesh.edges (), mesh.faces ()), params);
458-             Eigen::VectorXd normal_force_grad = (contact_hess * contact_grad) / contact_grad.norm ();
459-             for  (int  j = 0 ; j < cc->num_vertices (); j++)
460-                 for  (int  d = 0 ; d < 3 ; d++)
461-                     normal_force_jacobian (i, tmp_ids[j] * 3  + d) = normal_force_grad (j * 3  + d);
451+             auto  cc = create_smooth_collision (mesh, lagged_positions);
452+             SmoothContactPotential<SmoothCollisions<dim>> potential (params);
453+             Eigen::VectorXd g = potential.gradient (cc, mesh, lagged_positions);
454+             Eigen::SparseMatrix<double > h = potential.hessian (cc, mesh, lagged_positions);
455+             normal_force_jacobian = (h * g) / g.norm ();
462456        }
463457
464458        //  finite difference
465459        auto  F_X = [&](const  Eigen::VectorXd& x) {
466-             Eigen::MatrixXd fd_X = fd::unflatten (x, 3 );
460+             Eigen::MatrixXd fd_X = fd::unflatten (x, dim );
467461            const  Eigen::MatrixXd fd_lagged_positions = fd_X + Ut;
468462
469463            CollisionMesh fd_mesh (fd_X, mesh.edges (), mesh.faces ());
464+             auto  fd_cc = create_smooth_collision (fd_mesh, fd_lagged_positions);
470465
471-             Eigen::VectorXd fd_normal_force = Eigen::VectorXd::Zero (friction_collisions.size ());
472-             for  (int  i = 0 ; i < friction_collisions.size (); i++)
473-             {
474-                 const  FrictionCollision& collision = friction_collisions[i];
475-                 auto  cc = collision.smooth_collision_3d ;
476- 
477-                 std::unique_ptr<SmoothCollision<max_vert_3d>> fd_cc;
478-                 if  (cc->type () == CollisionType::EdgeEdge)
479-                     fd_cc = std::make_unique<SmoothCollisionTemplate<max_vert_3d, Edge3, Edge3>>((*cc)[0 ], (*cc)[1 ], PrimitiveDistType<Edge3, Edge3>::type::AUTO, fd_mesh, params, dhat, fd_lagged_positions);
480-                 else  if  (cc->type () == CollisionType::EdgeVertex)
481-                     fd_cc = std::make_unique<SmoothCollisionTemplate<max_vert_3d, Edge3, Point3>>((*cc)[0 ], (*cc)[1 ], PrimitiveDistType<Edge3, Point3>::type::AUTO, fd_mesh, params, dhat, fd_lagged_positions);
482-                 else  if  (cc->type () == CollisionType::VertexVertex)
483-                     fd_cc = std::make_unique<SmoothCollisionTemplate<max_vert_3d, Point3, Point3>>((*cc)[0 ], (*cc)[1 ], PrimitiveDistType<Point3, Point3>::type::AUTO, fd_mesh, params, dhat, fd_lagged_positions);
484-                 else  if  (cc->type () == CollisionType::FaceVertex)
485-                     fd_cc = std::make_unique<SmoothCollisionTemplate<max_vert_3d, Face, Point3>>((*cc)[0 ], (*cc)[1 ], PrimitiveDistType<Face, Point3>::type::AUTO, fd_mesh, params, dhat, fd_lagged_positions);
486- 
487-                 const  Eigen::VectorXd fd_contact_grad = fd_cc->gradient (fd_cc->dof (fd_lagged_positions, fd_mesh.edges (), fd_mesh.faces ()), params);
488- 
489-                 fd_normal_force (i) = fd_contact_grad.norm ();
490-             }
491- 
492-             return  fd_normal_force;
466+             SmoothContactPotential<SmoothCollisions<dim>> potential (params);
467+             return  potential.gradient (fd_cc, fd_mesh, fd_lagged_positions).norm ();
493468        };
494-         Eigen::MatrixXd fd_normal_force_jacobian;
495-         fd::finite_jacobian (fd::flatten (X), F_X, fd_normal_force_jacobian);
469+ 
470+         Eigen::VectorXd fd_normal_force_jacobian;
471+         fd::finite_gradient (fd::flatten (X), F_X, fd_normal_force_jacobian);
496472        CHECK ((normal_force_jacobian - fd_normal_force_jacobian).norm () <= 1e-7  * normal_force_jacobian.norm ());
497473    }
498474
499- 
500475    // /////////////////////////////////////////////////////////////////////////
501476
502477    Eigen::MatrixXd JF_wrt_X = D.smooth_contact_force_jacobian (
@@ -519,7 +494,7 @@ void check_smooth_friction_force_jacobian(
519494            fd_friction_collisions, fd_mesh, fd_X, Ut, velocities);
520495    };
521496    Eigen::MatrixXd fd_JF_wrt_X;
522-     fd::finite_jacobian (fd::flatten (X), F_X, fd_JF_wrt_X, fd::AccuracyOrder::FOURTH, 1e-6 );
497+     fd::finite_jacobian (fd::flatten (X), F_X, fd_JF_wrt_X, fd::AccuracyOrder::FOURTH, 1e-6  * dhat );
523498    //  CHECK(fd::compare_jacobian(JF_wrt_X, fd_JF_wrt_X));
524499    //  if (!fd::compare_jacobian(JF_wrt_X, fd_JF_wrt_X)) {
525500    //      tests::print_compare_nonzero(JF_wrt_X, fd_JF_wrt_X);
@@ -546,7 +521,7 @@ void check_smooth_friction_force_jacobian(
546521            fd_friction_collisions, mesh, X, fd_Ut, velocities);
547522    };
548523    Eigen::MatrixXd fd_JF_wrt_Ut;
549-     fd::finite_jacobian (fd::flatten (Ut), F_Ut, fd_JF_wrt_Ut, fd::AccuracyOrder::FOURTH, 1e-6 );
524+     fd::finite_jacobian (fd::flatten (Ut), F_Ut, fd_JF_wrt_Ut, fd::AccuracyOrder::FOURTH, 1e-6  * dhat );
550525    //  CHECK(fd::compare_jacobian(JF_wrt_Ut, fd_JF_wrt_Ut));
551526    //  if (!fd::compare_jacobian(JF_wrt_Ut, fd_JF_wrt_Ut)) {
552527    //      tests::print_compare_nonzero(JF_wrt_Ut, fd_JF_wrt_Ut);
@@ -565,8 +540,8 @@ void check_smooth_friction_force_jacobian(
565540            fd::unflatten (v, velocities.cols ()));
566541    };
567542    Eigen::MatrixXd fd_JF_wrt_V;
568-     fd::finite_jacobian (fd::flatten (velocities), F_V, fd_JF_wrt_V);
569-     CHECK ((fd_JF_wrt_V - JF_wrt_V).norm () <= 1e-7  * JF_wrt_V.norm ());
543+     fd::finite_jacobian (fd::flatten (velocities), F_V, fd_JF_wrt_V, fd::AccuracyOrder::FOURTH,  1e-6  * dhat );
544+     CHECK ((JF_wrt_V. norm () ==  0  || ( fd_JF_wrt_V - JF_wrt_V).norm () <= 1e-7  * JF_wrt_V.norm () ));
570545}
571546
572547TEST_CASE (" Smooth friction force jacobian 2D" " [friction-smooth][force-jacobian]" 
0 commit comments