8#include <ipc/barrier/barrier.hpp>
9#include <ipc/utils/local_to_global.hpp>
10#include <ipc/utils/eigen_ext.hpp>
15 const Eigen::MatrixXd &rest_positions,
const Eigen::MatrixXi &elements,
const int dim,
const double vhat)
16 : rest_positions_(rest_positions), elements_(elements), dim_(dim), vhat_(vhat)
24 auto storage = utils::create_thread_storage<double>(0.0);
29 double &local_potential = utils::get_local_thread_storage(storage, thread_id);
30 for (int i = start; i < end; i++)
33 scale * element_volume(rest_positions_(elements_.row(i), Eigen::all))
34 * ipc::barrier(element_volume(V(elements_.row(i), Eigen::all)), vhat_);
39 for (
const auto &local_potential : storage)
40 potential += local_potential;
48 auto storage = utils::create_thread_storage<Eigen::VectorXd>(Eigen::VectorXd::Zero(
x.size()));
53 Eigen::VectorXd &grad = utils::get_local_thread_storage(storage, thread_id);
54 for (int i = start; i < end; i++)
56 const Eigen::MatrixXd element_vertices = V(elements_.row(i), Eigen::all);
58 Eigen::VectorXd local_grad =
59 (scale * element_volume(rest_positions_(elements_.row(i), Eigen::all))
60 * ipc::barrier_first_derivative(element_volume(element_vertices), vhat_))
61 * element_volume_gradient(element_vertices);
63 ipc::local_gradient_to_global_gradient(local_grad, elements_.row(i), dim_, grad);
67 gradv = Eigen::VectorXd::Zero(
x.size());
68 for (
const auto &local_grad : storage)
81 std::vector<Eigen::Triplet<double>> &hess_triplets =
82 utils::get_local_thread_storage(storage, thread_id);
84 for (int i = start; i < end; i++)
86 const Eigen::MatrixXd element_vertices = V(elements_.row(i), Eigen::all);
88 const double volume = element_volume(element_vertices);
89 const Eigen::VectorXd volume_grad = element_volume_gradient(element_vertices);
91 const double rest_volume = element_volume(rest_positions_(elements_.row(i), Eigen::all));
93 Eigen::MatrixXd local_hess =
94 (scale * rest_volume * ipc::barrier_second_derivative(volume, vhat_)) * volume_grad * volume_grad.transpose()
95 + (scale * rest_volume * ipc::barrier_first_derivative(volume, vhat_)) * element_volume_hessian(element_vertices);
98 local_hess = ipc::project_to_psd(local_hess);
100 ipc::local_hessian_to_global_triplets(local_hess, elements_.row(i), dim_, hess_triplets);
104 hessian.resize(
x.size(),
x.size());
105 for (
const auto &local_hess_triplets : storage)
107 Eigen::SparseMatrix<double> local_hess(
x.size(),
x.size());
108 local_hess.setFromTriplets(
109 local_hess_triplets.begin(), local_hess_triplets.end());
110 hessian += local_hess;
116 if (element_vertices.rows() == 3)
119 assert(element_vertices.rows() == 4 && element_vertices.cols() == 3);
125 Eigen::VectorXd grad(element_vertices.size());
126 if (element_vertices.rows() == 3)
128 assert(element_vertices.cols() == 2);
130 element_vertices(0, 0), element_vertices(0, 1),
131 element_vertices(1, 0), element_vertices(1, 1),
132 element_vertices(2, 0), element_vertices(2, 1),
137 assert(element_vertices.rows() == 4 && element_vertices.cols() == 3);
139 element_vertices(0, 0), element_vertices(0, 1), element_vertices(0, 2),
140 element_vertices(1, 0), element_vertices(1, 1), element_vertices(1, 2),
141 element_vertices(2, 0), element_vertices(2, 1), element_vertices(2, 2),
142 element_vertices(3, 0), element_vertices(3, 1), element_vertices(3, 2),
150 Eigen::MatrixXd hess(element_vertices.size(), element_vertices.size());
151 if (element_vertices.rows() == 3)
153 assert(element_vertices.cols() == 2);
155 element_vertices(0, 0), element_vertices(0, 1),
156 element_vertices(1, 0), element_vertices(1, 1),
157 element_vertices(2, 0), element_vertices(2, 1),
162 assert(element_vertices.rows() == 4 && element_vertices.cols() == 3);
164 element_vertices(0, 0), element_vertices(0, 1), element_vertices(0, 2),
165 element_vertices(1, 0), element_vertices(1, 1), element_vertices(1, 2),
166 element_vertices(2, 0), element_vertices(2, 1), element_vertices(2, 2),
167 element_vertices(3, 0), element_vertices(3, 1), element_vertices(3, 2),
177 for (
size_t i = 0; i <
elements_.rows(); ++i)
void triangle_area_2D_hessian(double ax, double ay, double bx, double by, double cx, double cy, double H[36])
Compute the Hessian of the signed area of a 2D triangle defined by three points.
void tetrahedron_volume_gradient(double ax, double ay, double az, double bx, double by, double bz, double cx, double cy, double cz, double dx, double dy, double dz, double g[12])
Compute the gradient of the signed volume of a tetrahedron defined by four points.
void tetrahedron_volume_hessian(double ax, double ay, double az, double bx, double by, double bz, double cx, double cy, double cz, double dx, double dy, double dz, double H[144])
Compute the gradient of the signed area of a 2D triangle defined by three points.
double tetrahedron_volume(const Eigen::Vector3d &a, const Eigen::Vector3d &b, const Eigen::Vector3d &c, const Eigen::Vector3d &d)
Compute the signed volume of a tetrahedron defined by four points.
void triangle_area_2D_gradient(double ax, double ay, double bx, double by, double cx, double cy, double g[6])
Compute the gradient of the signed area of a 2D triangle defined by three points.
Eigen::MatrixXd unflatten(const Eigen::VectorXd &x, int dim)
Unflatten rowwises, so every dim elements in x become a row.
auto create_thread_storage(const LocalStorage &initial_local_storage)
double triangle_area(const Eigen::MatrixXd V)
Compute the signed area of a triangle defined by three points.
void maybe_parallel_for(int size, const std::function< void(int, int, int)> &partial_for)
Eigen::SparseMatrix< double, Eigen::ColMajor > StiffnessMatrix