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
LaplacianMatrix.h
Go to the documentation of this file.
1
10
11#ifndef PBAT_FEM_LAPLACIAN_MATRIX_H
12#define PBAT_FEM_LAPLACIAN_MATRIX_H
13
14#include "Concepts.h"
15
16#include <exception>
17#include <fmt/core.h>
18#include <pbat/Aliases.h>
19#include <pbat/common/Eigen.h>
21#include <tbb/parallel_for.h>
22
23namespace pbat {
24namespace fem {
25
53template <CMesh TMesh>
55{
56 public:
58 using MeshType = TMesh;
59 using ElementType = typename TMesh::ElementType;
60
61 static int constexpr kOrder =
62 2 * (ElementType::kOrder - 1);
63
76 MeshType const& mesh,
77 Eigen::Ref<IndexVectorX const> const& eg,
78 Eigen::Ref<VectorX const> const& wg,
79 Eigen::Ref<MatrixX const> const& GNegg,
80 int dims = 1);
81
82 SelfType& operator=(SelfType const&) = delete;
83
94 template <class TDerivedIn, class TDerivedOut>
95 void Apply(Eigen::MatrixBase<TDerivedIn> const& x, Eigen::DenseBase<TDerivedOut>& y) const;
96
101 CSCMatrix ToMatrix() const;
102
108 Index InputDimensions() const { return dims * mesh.X.cols(); }
115
123 void CheckValidState() const;
124
125 MeshType const& mesh;
126 Eigen::Ref<IndexVectorX const>
128 Eigen::Ref<VectorX const> wg;
129 Eigen::Ref<MatrixX const>
134 int dims;
136};
137
138template <CMesh TMesh>
140 MeshType const& mesh,
141 Eigen::Ref<IndexVectorX const> const& eg,
142 Eigen::Ref<VectorX const> const& wg,
143 Eigen::Ref<MatrixX const> const& GNeg,
144 int dims)
145 : mesh(mesh), eg(eg), wg(wg), GNeg(GNeg), deltag(), dims(dims)
146{
148}
149
150template <CMesh TMesh>
152{
153 PBAT_PROFILE_NAMED_SCOPE("pbat.fem.SymmetricLaplacianMatrix.ToMatrix");
156 using SparseIndex = typename CSCMatrix::StorageIndex;
157 using Triplet = Eigen::Triplet<Scalar, SparseIndex>;
158
159 std::vector<Triplet> triplets{};
160 triplets.reserve(static_cast<std::size_t>(deltag.size() * dims));
161 auto const numberOfQuadraturePoints = wg.size();
162 for (auto g = 0; g < numberOfQuadraturePoints; ++g)
163 {
164 auto const e = eg(g);
165 auto const nodes = mesh.E.col(e);
166 auto constexpr kNodesPerElement = ElementType::kNodes;
167 auto const Leg = deltag.block(0, g * kNodesPerElement, kNodesPerElement, kNodesPerElement);
168 for (auto j = 0; j < Leg.cols(); ++j)
169 {
170 for (auto i = 0; i < Leg.rows(); ++i)
171 {
172 for (auto d = 0; d < dims; ++d)
173 {
174 auto const ni = static_cast<SparseIndex>(dims * nodes(i) + d);
175 auto const nj = static_cast<SparseIndex>(dims * nodes(j) + d);
176 triplets.push_back(Triplet(ni, nj, Leg(i, j)));
177 }
178 }
179 }
180 }
181 L.setFromTriplets(triplets.begin(), triplets.end());
182 return L;
183}
184
185template <CMesh TMesh>
187{
188 PBAT_PROFILE_NAMED_SCOPE("pbat.fem.SymmetricLaplacianMatrix.ComputeElementLaplacians");
190 // Compute element laplacians
191 auto constexpr kNodesPerElement = ElementType::kNodes;
192 auto constexpr kDims = MeshType::kDims;
193 auto const numberOfQuadraturePoints = wg.size();
194 deltag.setZero(kNodesPerElement, kNodesPerElement * numberOfQuadraturePoints);
195 tbb::parallel_for(Index{0}, Index{numberOfQuadraturePoints}, [&](Index g) {
196 auto Leg = deltag.block<kNodesPerElement, kNodesPerElement>(0, g * kNodesPerElement);
197 // Use multivariable integration by parts (i.e. Green's identity), and retain only the
198 // symmetric part, i.e.
199 // Lij = -\int_{\Omega} \nabla \phi_i(X) \cdot \nabla \phi_j(X) \partial \Omega.
200 auto const GP = GNeg.block<kNodesPerElement, kDims>(0, g * kDims);
201 Leg -= wg(g) * GP * GP.transpose();
202 });
203}
204
205template <CMesh TMesh>
207{
208 auto const numberOfQuadraturePoints = wg.size();
209 auto constexpr kExpectedGNegRows = ElementType::kNodes;
210 auto const expectedGNegCols = MeshType::kDims * numberOfQuadraturePoints;
211 bool const bShapeFunctionGradientsHaveCorrectDimensions =
212 (GNeg.rows() == kExpectedGNegRows) and (GNeg.cols() == expectedGNegCols);
213 if (not bShapeFunctionGradientsHaveCorrectDimensions)
214 {
215 std::string const what = fmt::format(
216 "Expected shape function gradients at element quadrature points of dimensions "
217 "|#nodes-per-element|={} x |#mesh-dims * #quad.pts.|={} for polynomial but got {}x{} "
218 "instead",
219 kExpectedGNegRows,
220 expectedGNegCols,
221 GNeg.rows(),
222 GNeg.cols());
223 throw std::invalid_argument(what);
224 }
225 if (dims < 1)
226 {
227 std::string const what =
228 fmt::format("Expected output dimensionality >= 1, got {} instead", dims);
229 throw std::invalid_argument(what);
230 }
231}
232
233template <CMesh TMesh>
234template <class TDerivedIn, class TDerivedOut>
236 Eigen::MatrixBase<TDerivedIn> const& x,
237 Eigen::DenseBase<TDerivedOut>& y) const
238{
239 PBAT_PROFILE_NAMED_SCOPE("pbat.fem.SymmetricLaplacianMatrix.Apply");
241 auto const numberOfDofs = InputDimensions();
242 bool const bAreInputOutputValid =
243 (x.rows() != numberOfDofs) or (y.rows() != numberOfDofs) or (y.cols() != x.cols());
244 if (bAreInputOutputValid)
245 {
246 std::string const what = fmt::format(
247 "Expected input x and output y with matching dimensions and {} rows, but got {}x{} "
248 "input and {}x{} output",
249 numberOfDofs,
250 x.rows(),
251 x.cols(),
252 y.rows(),
253 y.cols());
254 throw std::invalid_argument(what);
255 }
256
257 auto const numberOfQuadraturePoints = wg.size();
258 for (auto c = 0; c < x.cols(); ++c)
259 {
260 for (auto g = 0; g < numberOfQuadraturePoints; ++g)
261 {
262 auto const e = eg(g);
263 auto const nodes = mesh.E.col(e);
264 auto constexpr kNodesPerElement = ElementType::kNodes;
265 auto const Leg =
266 deltag.block(0, g * kNodesPerElement, kNodesPerElement, kNodesPerElement);
267 auto ye = y.col(c).reshaped(dims, y.size() / dims)(Eigen::placeholders::all, nodes);
268 auto const xe =
269 x.col(c).reshaped(dims, x.size() / dims)(Eigen::placeholders::all, nodes);
270 ye += xe * Leg /*.transpose() technically, but Laplacian matrix is symmetric*/;
271 }
272 }
273}
274
275} // namespace fem
276} // namespace pbat
277
278#endif // PBAT_FEM_LAPLACIAN_MATRIX_H
Profiling utilities for the Physics-Based Animation Toolkit (PBAT)
#define PBAT_PROFILE_NAMED_SCOPE(name)
Definition Profiling.h:32
Eigen adaptors for ranges.
Finite Element Method (FEM)
Definition Concepts.h:19
The main namespace of the library.
Definition Aliases.h:15
Eigen::SparseMatrix< Scalar, Eigen::ColMajor > CSCMatrix
Column-major sparse matrix type.
Definition Aliases.h:52
Eigen::Matrix< Scalar, Eigen::Dynamic, Eigen::Dynamic > MatrixX
Dynamic-size matrix type.
Definition Aliases.h:34
std::ptrdiff_t Index
Index type.
Definition Aliases.h:17
MeshType const & mesh
The finite element mesh.
Definition LaplacianMatrix.h:125
void CheckValidState() const
Check if the state of this Laplacian matrix is valid.
Definition LaplacianMatrix.h:206
SymmetricLaplacianMatrix< TMesh > SelfType
Self type.
Definition LaplacianMatrix.h:57
Index OutputDimensions() const
Number of rows.
Definition LaplacianMatrix.h:114
void ComputeElementLaplacians()
Compute and store the element laplacians.
Definition LaplacianMatrix.h:186
static int constexpr kOrder
Polynomial order of the Laplacian matrix.
Definition LaplacianMatrix.h:61
SymmetricLaplacianMatrix(MeshType const &mesh, Eigen::Ref< IndexVectorX const > const &eg, Eigen::Ref< VectorX const > const &wg, Eigen::Ref< MatrixX const > const &GNegg, int dims=1)
Construct a new symmetric Laplacian operator.
Definition LaplacianMatrix.h:139
Index InputDimensions() const
Number of columns.
Definition LaplacianMatrix.h:108
typename TMesh::ElementType ElementType
Element type.
Definition LaplacianMatrix.h:59
CSCMatrix ToMatrix() const
Transforms this matrix-free matrix representation into sparse compressed format.
Definition LaplacianMatrix.h:151
Eigen::Ref< MatrixX const > GNeg
Definition LaplacianMatrix.h:130
Eigen::Ref< VectorX const > wg
|# quad.pts.|x1 array of quadrature weights
Definition LaplacianMatrix.h:128
Eigen::Ref< IndexVectorX const > eg
|# quad.pts.|x1 array of elements associated with quadrature points
Definition LaplacianMatrix.h:127
int dims
Definition LaplacianMatrix.h:134
void Apply(Eigen::MatrixBase< TDerivedIn > const &x, Eigen::DenseBase< TDerivedOut > &y) const
Applies this matrix as a linear operator on x, adding result to y.
Definition LaplacianMatrix.h:235
TMesh MeshType
Mesh type.
Definition LaplacianMatrix.h:58
MatrixX deltag
Definition LaplacianMatrix.h:132