16#ifndef PBAT_FEM_LAPLACIAN_H
17#define PBAT_FEM_LAPLACIAN_H
26#include <tbb/parallel_for.h>
61 Eigen::DenseBase<TDerivedE>
const& E,
63 Eigen::DenseBase<TDerivedeg>
const& eg,
64 Eigen::DenseBase<TDerivedwg>
const& wg,
65 Eigen::MatrixBase<TDerivedGNeg>
const& GNeg,
67 Eigen::MatrixBase<TDerivedIn>
const& X,
68 Eigen::DenseBase<TDerivedOut>& Y);
96 Eigen::DenseBase<TDerivedeg>
const& eg,
97 Eigen::DenseBase<TDerivedwg>
const& wg,
98 Eigen::MatrixBase<TDerivedGNeg>
const& GNeg,
100 Eigen::MatrixBase<TDerivedIn>
const& X,
101 Eigen::DenseBase<TDerivedOut>& Y)
105 static_cast<typename TMesh::IndexType
>(mesh.X.cols()),
135 Eigen::StorageOptions Options,
141 Eigen::DenseBase<TDerivedE>
const& E,
143 Eigen::DenseBase<TDerivedeg>
const& eg,
144 Eigen::DenseBase<TDerivedwg>
const& wg,
145 Eigen::MatrixBase<TDerivedGNeg>
const& GNeg,
147 -> Eigen::SparseMatrix<typename TDerivedGNeg::Scalar, Options, typename TDerivedE::Scalar>;
165 Eigen::StorageOptions Options,
172 Eigen::DenseBase<TDerivedeg>
const& eg,
173 Eigen::DenseBase<TDerivedwg>
const& wg,
174 Eigen::MatrixBase<TDerivedGNeg>
const& GNeg,
176 -> Eigen::SparseMatrix<typename TDerivedGNeg::Scalar, Options, typename TMesh::IndexType>
180 static_cast<typename TMesh::IndexType
>(mesh.X.cols()),
197 Eigen::DenseBase<TDerivedE>
const& E,
199 Eigen::DenseBase<TDerivedeg>
const& eg,
200 Eigen::DenseBase<TDerivedwg>
const& wg,
201 Eigen::MatrixBase<TDerivedGNeg>
const& GNeg,
203 Eigen::MatrixBase<TDerivedIn>
const& X,
204 Eigen::DenseBase<TDerivedOut>& Y)
206 PBAT_PROFILE_NAMED_SCOPE(
"pbat.fem.GemmLaplacian");
209 auto const numberOfDofs = dims * nNodes;
210 bool const bDimensionsMatch =
211 (X.cols() == Y.cols()) and (X.rows() == numberOfDofs) and (Y.rows() == numberOfDofs);
212 if (not bDimensionsMatch)
214 std::string
const what = fmt::format(
215 "Expected input and output to have {} rows and same number of columns, but got "
216 "dimensions X,Y=({} x {}), ({} x {})",
222 throw std::invalid_argument(what);
227 std::string
const what = fmt::format(
"Expected dims >= 1, got {} instead", dims);
228 throw std::invalid_argument(what);
232 auto constexpr kNodesPerElement = TElement::kNodes;
233 auto constexpr kDims = Dims;
234 auto const nQuadPts = eg.size();
235 for (
auto c = 0; c < X.cols(); ++c)
237 for (
auto g = 0; g < nQuadPts; ++g)
239 auto const e = eg(g);
240 auto const nodes = E.col(e);
241 auto const w = wg(g);
243 auto const GP = GNeg.template block<kNodesPerElement, kDims>(0, g * kDims);
245 auto ye = Y.col(c).reshaped(dims, nNodes)(Eigen::placeholders::all, nodes);
246 auto const xe = X.col(c).reshaped(dims, nNodes)(Eigen::placeholders::all, nodes);
247 ye -= ((w * xe) * GP) * GP.transpose();
255 Eigen::StorageOptions Options,
261 Eigen::DenseBase<TDerivedE>
const& E,
263 Eigen::DenseBase<TDerivedeg>
const& eg,
264 Eigen::DenseBase<TDerivedwg>
const& wg,
265 Eigen::MatrixBase<TDerivedGNeg>
const& GNeg,
267 -> Eigen::SparseMatrix<typename TDerivedGNeg::Scalar, Options, typename TDerivedE::Scalar>
269 PBAT_PROFILE_NAMED_SCOPE(
"pbat.fem.LaplacianMatrix");
270 using ScalarType =
typename TDerivedGNeg::Scalar;
271 using IndexType =
typename TDerivedE::Scalar;
272 using SparseMatrixType = Eigen::SparseMatrix<ScalarType, Options, IndexType>;
273 using Triplet = Eigen::Triplet<ScalarType, IndexType>;
275 auto constexpr kNodesPerElement = TElement::kNodes;
276 auto constexpr kDims = Dims;
278 auto const nQuadPts = eg.size();
279 std::vector<Triplet> triplets{};
281 static_cast<std::size_t
>(kNodesPerElement * kNodesPerElement * nQuadPts * dims));
283 auto const numberOfDofs = dims * nNodes;
284 SparseMatrixType L(numberOfDofs, numberOfDofs);
286 for (
auto g = 0; g < nQuadPts; ++g)
288 auto const e = eg(g);
289 auto const nodes = E.col(e);
290 auto const w = wg(g);
293 auto const GP = GNeg.template block<kNodesPerElement, kDims>(0, g * kDims);
296 auto const Leg = -w * GP * GP.transpose();
299 for (
auto i = 0; i < kNodesPerElement; ++i)
301 for (
auto j = 0; j < kNodesPerElement; ++j)
303 for (
auto d = 0; d < dims; ++d)
305 auto const ni =
static_cast<IndexType
>(dims * nodes(i) + d);
306 auto const nj =
static_cast<IndexType
>(dims * nodes(j) + d);
307 triplets.emplace_back(ni, nj, Leg(i, j));
313 L.setFromTriplets(triplets.begin(), triplets.end());
Eigen adaptors for ranges.
Reference finite element.
Definition Concepts.h:63
Finite element mesh.
Definition Concepts.h:84
Finite Element Method (FEM)
Definition Concepts.h:19
auto LaplacianMatrix(Eigen::DenseBase< TDerivedE > const &E, Eigen::Index nNodes, Eigen::DenseBase< TDerivedeg > const &eg, Eigen::DenseBase< TDerivedwg > const &wg, Eigen::MatrixBase< TDerivedGNeg > const &GNeg, int dims=1) -> Eigen::SparseMatrix< typename TDerivedGNeg::Scalar, Options, typename TDerivedE::Scalar >
Construct the Laplacian operator's sparse matrix representation.
Definition Laplacian.h:260
void GemmLaplacian(Eigen::DenseBase< TDerivedE > const &E, Eigen::Index nNodes, Eigen::DenseBase< TDerivedeg > const &eg, Eigen::DenseBase< TDerivedwg > const &wg, Eigen::MatrixBase< TDerivedGNeg > const &GNeg, int dims, Eigen::MatrixBase< TDerivedIn > const &X, Eigen::DenseBase< TDerivedOut > &Y)
Compute Laplacian matrix-vector multiply .
Definition Laplacian.h:196
Profiling utilities for the Physics-Based Animation Toolkit (PBAT)