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