PhysicsBasedAnimationToolkit 0.0.10
Cross-platform C++20 library of algorithms and data structures commonly used in computer graphics research on physically-based simulation.
Loading...
Searching...
No Matches
HessianProduct.h
Go to the documentation of this file.
1
8
9#ifndef PBAT_SIM_ALGORITHM_NEWTON_HESSIANPRODUCT_H
10#define PBAT_SIM_ALGORITHM_NEWTON_HESSIANPRODUCT_H
11
12#include "pbat/Aliases.h"
14#include "pbat/math/linalg/SelectionMatrix.h"
15#include "pbat/math/linalg/SparsityPattern.h"
16
17#include <vector>
18
20struct HessianOperator;
21} // namespace pbat::sim::algorithm::newton
22
23namespace Eigen {
24namespace internal {
28template <>
29struct traits<pbat::sim::algorithm::newton::HessianOperator>
30 : public Eigen::internal::traits<pbat::CSCMatrix>
31{
32};
33} // namespace internal
34} // namespace Eigen
35
42template <class T>
43concept CElasticPotential = requires(T U)
44{
45 { U.ComputeElementElasticity(std::declval<VectorX>(), false, true, true) };
46 { U.ToMatrix(std::declval<CSCMatrix&>()) };
47 { U.GH } -> std::convertible_to<math::linalg::SparsityPattern<>>;
48};
49
53struct Hessian
54{
55 static auto constexpr kDims = 3;
56 static auto constexpr kContactInds = 4;
57 using TripletType = Eigen::Triplet<Scalar, CSCMatrix::StorageIndex>;
62 void AllocateContacts(std::size_t nContacts);
69 void SetSparsityPattern(CSCMatrix const& HS);
76 template <class TDerivedF>
77 void ImposeDirichletConstraints(Eigen::DenseBase<TDerivedF> const& F);
87 template <class TDerivedHCB, class TDerivedHCIB>
88 void AddContactHessianBlock(
89 Eigen::DenseBase<TDerivedHCB> const& HCB,
90 Eigen::DenseBase<TDerivedHCIB> const& HCIB);
105 template <CElasticPotential TElasticPotential, class TDerivedM>
106 void ConstructContactLessHessian(
107 Eigen::DenseBase<TDerivedM> const& diagM,
108 Scalar bt2,
109 TElasticPotential const& U);
113 void ConstructContactHessian();
114
115 IndexVectorX diag;
116 CSCMatrix HNC;
117 std::vector<TripletType>
118 HCij;
121 CSCMatrix HC;
122 CSCMatrix S;
125};
126
132struct HessianOperator : public Eigen::EigenBase<HessianOperator>
133{
134 using Scalar = pbat::Scalar;
135 using RealScalar = pbat::Scalar;
136 using StorageIndex = typename CSCMatrix::StorageIndex;
137 enum
138 {
139 ColsAtCompileTime = Eigen::Dynamic,
140 MaxColsAtCompileTime = Eigen::Dynamic,
141 IsRowMajor = false
142 };
143
144 using SelfType = HessianOperator;
148 HessianOperator() = default;
153 HessianOperator(Hessian* data);
158 [[maybe_unused]] Eigen::Index rows() const { return mData->HNC.rows(); }
163 [[maybe_unused]] Eigen::Index cols() const { return mData->HNC.cols(); }
171 template <class Rhs>
172 Eigen::Product<SelfType, Rhs, Eigen::AliasFreeProduct>
173 operator*(Eigen::MatrixBase<Rhs> const& x) const
174 {
175 return Eigen::Product<SelfType, Rhs, Eigen::AliasFreeProduct>(*this, x.derived());
176 }
177
178 Hessian* mData;
179};
180
181template <class TDerivedF>
182inline void Hessian::ImposeDirichletConstraints(Eigen::DenseBase<TDerivedF> const& F)
183{
184 S = math::linalg::SelectionMatrix(F, diag.size());
185 HNC = S.transpose() * (HNC * S);
186 HC = S.transpose() * (HC * S);
187}
188
189template <class TDerivedHCB, class TDerivedHCIB>
190inline void Hessian::AddContactHessianBlock(
191 Eigen::DenseBase<TDerivedHCB> const& HCB,
192 Eigen::DenseBase<TDerivedHCIB> const& HCIB)
193{
195 [&]<auto kj>() {
197 [&]<auto ki>() {
198 auto const bi = HCIB(ki);
199 auto const bj = HCIB(kj);
200 auto const istart = bi * kDims;
201 auto const jstart = bj * kDims;
202 auto const HCbibj = HCB.template block<kDims, kDims>(ki, kj);
203 using IndexType = std::remove_cvref_t<decltype(std::declval<TripletType>().row()
204 )>;
206 [&]<auto j>() {
208 [&]<auto i>() {
209 HCij.emplace_back(
210 static_cast<IndexType>(istart + i),
211 static_cast<IndexType>(jstart + j),
212 HCbibj(i, j));
213 });
214 });
215 });
216 });
217}
218
219template <CElasticPotential TElasticPotential, class TDerivedM>
220inline void Hessian::ConstructContactLessHessian(
221 Eigen::DenseBase<TDerivedM> const& diagM,
222 Scalar bt2,
223 TElasticPotential const& U)
224{
225 U.ToMatrix(HNC);
226 HNC *= bt2;
227 HNC.coeffs()(diag) += diagM;
228}
229} // namespace pbat::sim::algorithm::newton
230
231namespace Eigen {
232namespace internal {
239template <typename Rhs, int ProductType>
240struct generic_product_impl<
241 pbat::sim::algorithm::newton::HessianOperator,
242 Rhs,
243 SparseShape,
244 DenseShape,
245 ProductType>
246 : generic_product_impl_base<
247 pbat::sim::algorithm::newton::HessianOperator,
248 Rhs,
249 generic_product_impl<pbat::sim::algorithm::newton::HessianOperator, Rhs>>
250{
251 using HessianOperator = pbat::sim::algorithm::newton::HessianOperator;
252 using Scalar = typename Product<HessianOperator, Rhs>::Scalar;
253 using Hessian = pbat::sim::algorithm::newton::Hessian;
263 template <typename Dst>
264 static void scaleAndAddTo(
265 Eigen::MatrixBase<Dst>& dst,
266 HessianOperator const& lhs,
267 Eigen::MatrixBase<Rhs> const& rhs,
268 Scalar const& alpha)
269 {
270 dst += alpha * (lhs.mData->HNC * rhs + lhs.mData->HC * rhs);
271 }
272};
273} // namespace internal
274} // namespace Eigen
275
276#endif // PBAT_SIM_ALGORITHM_NEWTON_HESSIANPRODUCT_H
Compile-time for loops.
constexpr void ForRange(F &&f)
Compile-time for loop over a range of values.
Definition ConstexprFor.h:55
CSCMatrix SelectionMatrix(Eigen::DenseBase< TDerivedC > const &C, Index n=Index(-1))
Construct the selection matrix S s.t. X*S selects all columns C of X.
Definition SelectionMatrix.h:19
Namespace for Newton simulation algorithms.
Definition Config.cpp:8
Eigen::Vector< Index, Eigen::Dynamic > IndexVectorX
Dynamic-size index vector type.
Definition Aliases.h:49
Eigen::SparseMatrix< Scalar, Eigen::ColMajor > CSCMatrix
Column-major sparse matrix type.
Definition Aliases.h:52
double Scalar
Scalar type.
Definition Aliases.h:18