18 const Eigen::SparseMatrix<double> &M,
19 const Eigen::SparseMatrix<double> &A,
20 const Eigen::Ref<const Eigen::MatrixXd> &
y)
23 std::unique_ptr<polysolve::linear::Solver> solver;
24#ifdef POLYSOLVE_WITH_MKL
25 solver = polysolve::linear::Solver::create(
"Eigen::PardisoLDLT",
"");
26#elif defined(POLYSOLVE_WITH_CHOLMOD)
27 solver = polysolve::linear::Solver::create(
"Eigen::CholmodSimplicialLDLT",
"");
29 solver = polysolve::linear::Solver::create(
"Eigen::SimplicialLDLT",
"");
32 solver->analyze_pattern(M, 0);
35 const Eigen::MatrixXd rhs = A *
y;
36 Eigen::MatrixXd
x(rhs.rows(), rhs.cols());
37 for (
int i = 0; i <
x.cols(); ++i)
38 solver->solve(rhs.col(i),
x.col(i));
40 double residual_error = (M *
x - rhs).norm();
41 logger().debug(
"residual error in L2 projection: {}", residual_error);
42 assert(residual_error < std::max(1e-12 * rhs.norm(), 1e-12));
48 const Eigen::MatrixXd &M,
49 const Eigen::MatrixXd &A,
50 const Eigen::Ref<const Eigen::MatrixXd> &
y,
51 const std::vector<int> &boundary_nodes,
52 Eigen::Ref<Eigen::MatrixXd>
x)
54 std::vector<int> free_nodes;
55 for (
int i = 0, j = 0; i <
y.rows(); ++i)
57 if (boundary_nodes[j] == i)
60 free_nodes.push_back(i);
63 const Eigen::MatrixXd H = M(free_nodes, free_nodes);
65 const Eigen::MatrixXd g = -((M *
x - A *
y)(free_nodes, Eigen::all));
66 const Eigen::MatrixXd sol = H.llt().solve(g);
67 x(free_nodes, Eigen::all) += sol;
72 std::shared_ptr<polysolve::nonlinear::Solver> nl_solver,
74 const Eigen::SparseMatrix<double> &M,
75 const Eigen::SparseMatrix<double> &A,
76 const Eigen::VectorXd &
y,
78 const Eigen::MatrixXd &rest_positions,
79 const Eigen::MatrixXi &elements,
82 const ipc::CollisionMesh &collision_mesh,
84 const double barrier_stiffness,
85 const bool use_convergent_formulation,
86 const ipc::BroadPhaseMethod broad_phase_method,
87 const double ccd_tolerance,
88 const int ccd_max_iterations,
90 const std::vector<int> &boundary_nodes,
91 const size_t obstacle_ndof,
92 const Eigen::VectorXd &target_x,
94 const Eigen::VectorXd &x0)
98 assert(M.rows() == M.cols());
99 assert(A.rows() == M.rows());
100 assert(A.cols() ==
y.size());
102 std::vector<std::shared_ptr<Form>> forms;
104 forms.push_back(std::make_shared<L2ProjectionForm>(M, A,
y));
106 forms.push_back(std::make_shared<InversionBarrierForm>(
107 rest_positions, elements, dim, 1e-12));
108 forms.back()->set_weight(barrier_stiffness);
109 assert(forms.back()->is_step_valid(x0, x0));
111 if (collision_mesh.num_vertices() != 0)
113 forms.push_back(std::make_shared<ContactForm>(
114 collision_mesh, dhat, 1.0, use_convergent_formulation,
116 false, broad_phase_method, ccd_tolerance,
117 ccd_max_iterations));
118 forms.back()->set_weight(barrier_stiffness);
119 assert(!ipc::has_intersections(collision_mesh, collision_mesh.displace_vertices(
utils::unflatten(x0, dim))));
122 const int ndof = x0.size();
124 std::shared_ptr<BCLagrangianForm> bc_lagrangian_form = std::make_shared<BCLagrangianForm>(
125 ndof, boundary_nodes, M, obstacle_ndof, target_x);
126 forms.push_back(bc_lagrangian_form);
130 std::vector<std::shared_ptr<AugmentedLagrangianForm>> bc_forms;
131 bc_forms.push_back(bc_lagrangian_form);
139 constexpr double al_initial_weight = 1e6;
140 constexpr double al_scaling = 2.0;
141 constexpr int al_max_weight = 100 * al_initial_weight;
142 constexpr double al_eta_tol = 0.99;
143 constexpr size_t al_max_solver_iter = 1000;
145 bc_forms, al_initial_weight,
146 al_scaling, al_max_weight, al_eta_tol,
147 [&](
const Eigen::MatrixXd &
x) {});
149 Eigen::MatrixXd sol = x0;
151 const size_t default_max_iterations = nl_solver->stop_criteria().iterations;
152 nl_solver->stop_criteria().iterations = al_max_solver_iter;
153 al_solver.
solve_al(nl_solver, problem, sol);
155 nl_solver->stop_criteria().iterations = default_max_iterations;
156 al_solver.solve_reduced(nl_solver, problem, sol);
159 assert(forms[1]->is_step_valid(sol, sol));
160 if (collision_mesh.num_vertices() != 0)
161 assert(!ipc::has_intersections(collision_mesh, collision_mesh.displace_vertices(
utils::unflatten(sol, dim))));
Eigen::VectorXd constrained_L2_projection(std::shared_ptr< polysolve::nonlinear::Solver > nl_solver, const Eigen::SparseMatrix< double > &M, const Eigen::SparseMatrix< double > &A, const Eigen::VectorXd &y, const Eigen::MatrixXd &rest_positions, const Eigen::MatrixXi &elements, const int dim, const ipc::CollisionMesh &collision_mesh, const double dhat, const double barrier_stiffness, const bool use_convergent_formulation, const ipc::BroadPhaseMethod broad_phase_method, const double ccd_tolerance, const int ccd_max_iterations, const std::vector< int > &boundary_nodes, const size_t obstacle_ndof, const Eigen::VectorXd &target_x, const Eigen::VectorXd &x0)