21#ifndef PBAT_FEM_GRADIENT_H
22#define PBAT_FEM_GRADIENT_H
32#include <tbb/parallel_for.h>
63 Eigen::DenseBase<TDerivedE>
const& E,
65 Eigen::DenseBase<TDerivedeg>
const& eg,
66 Eigen::MatrixBase<TDerivedGNeg>
const& GNeg,
67 Eigen::MatrixBase<TDerivedIn>
const& X,
68 Eigen::DenseBase<TDerivedOut>& Y);
84template <CMesh TMesh,
class TDerivedeg,
class TDerivedGNeg,
class TDerivedIn,
class TDerivedOut>
87 Eigen::DenseBase<TDerivedeg>
const& eg,
88 Eigen::MatrixBase<TDerivedGNeg>
const& GNeg,
89 Eigen::MatrixBase<TDerivedIn>
const& X,
90 Eigen::DenseBase<TDerivedOut>& Y)
94 static_cast<typename TMesh::IndexType
>(mesh.X.cols()),
119 Eigen::StorageOptions Options,
124 Eigen::DenseBase<TDerivedE>
const& E,
126 Eigen::DenseBase<TDerivedeg>
const& eg,
127 Eigen::MatrixBase<TDerivedGNeg>
const& GNeg)
128 -> Eigen::SparseMatrix<typename TDerivedGNeg::Scalar, Options, typename TDerivedE::Scalar>;
142template <Eigen::StorageOptions Options, CMesh TMesh,
class TDerivedeg,
class TDerivedGNeg>
145 Eigen::DenseBase<TDerivedeg>
const& eg,
146 Eigen::MatrixBase<TDerivedGNeg>
const& GNeg)
147 -> Eigen::SparseMatrix<typename TDerivedGNeg::Scalar, Options, typename TMesh::IndexType>
151 static_cast<typename TMesh::IndexType
>(mesh.X.cols()),
165 Eigen::DenseBase<TDerivedE>
const& E,
167 Eigen::DenseBase<TDerivedeg>
const& eg,
168 Eigen::MatrixBase<TDerivedGNeg>
const& GNeg,
169 Eigen::MatrixBase<TDerivedIn>
const& X,
170 Eigen::DenseBase<TDerivedOut>& Y)
172 PBAT_PROFILE_NAMED_SCOPE(
"pbat.fem.GemmGradient");
174 auto const rows = Dims * eg.size();
175 auto const cols = nNodes;
176 bool const bDimensionsMatch =
177 (X.cols() == Y.cols()) and (X.rows() == cols) and (Y.rows() == rows);
178 if (not bDimensionsMatch)
180 std::string
const what = fmt::format(
181 "Expected input to have rows={} and output to have rows={}, and same number of "
182 "columns, but got dimensions "
183 "X,Y=({} x {}), ({} x {})",
190 throw std::invalid_argument(what);
193 auto constexpr kNodesPerElement = TElement::kNodes;
194 auto constexpr kDims = Dims;
195 auto const nQuadPts = eg.size();
196 for (
auto c = 0; c < X.cols(); ++c)
198 for (
auto g = 0; g < nQuadPts; ++g)
200 auto const e = eg(g);
201 auto const nodes = E.col(e);
202 auto const Xe = X.col(c)(nodes);
203 auto const Geg = GNeg.template block<kNodesPerElement, kDims>(0, g * kDims);
204 for (
auto d = 0; d < kDims; ++d)
206 Y(d * nQuadPts + g) += Geg(Eigen::placeholders::all, d).transpose() * Xe;
215 Eigen::StorageOptions Options,
220 Eigen::DenseBase<TDerivedE>
const& E,
222 Eigen::DenseBase<TDerivedeg>
const& eg,
223 Eigen::MatrixBase<TDerivedGNeg>
const& GNeg)
224 -> Eigen::SparseMatrix<typename TDerivedGNeg::Scalar, Options, typename TDerivedE::Scalar>
226 PBAT_PROFILE_NAMED_SCOPE(
"pbat.fem.GradientMatrix");
227 using ScalarType =
typename TDerivedGNeg::Scalar;
228 using IndexType =
typename TDerivedE::Scalar;
229 using SparseMatrixType = Eigen::SparseMatrix<ScalarType, Options, IndexType>;
230 using Triplet = Eigen::Triplet<ScalarType, IndexType>;
234 TElement::kNodes != Eigen::Dynamic,
235 "Element nodes must be known at compile time");
236 auto constexpr kNodesPerElement = TElement::kNodes;
237 auto constexpr kDims = Dims;
239 auto const nQuadPts = eg.size();
240 std::vector<Triplet> triplets{};
241 triplets.reserve(
static_cast<std::size_t
>(kNodesPerElement * kDims * nQuadPts));
242 SparseMatrixType G(kDims * nQuadPts, nNodes);
244 for (
auto g = 0; g < nQuadPts; ++g)
246 auto const e = eg(g);
247 auto const nodes = E.col(e);
248 auto const Geg = GNeg.template block<kNodesPerElement, kDims>(0, g * kDims);
249 for (
auto d = 0; d < kDims; ++d)
251 for (
auto j = 0; j < kNodesPerElement; ++j)
253 auto const ni =
static_cast<IndexType
>(d * nQuadPts + g);
254 auto const nj =
static_cast<IndexType
>(nodes(j));
255 triplets.emplace_back(ni, nj, Geg(j, d));
259 G.setFromTriplets(triplets.begin(), triplets.end());
FEM shape functions and gradients.
Eigen adaptors for ranges.
Reference finite element.
Definition Concepts.h:63
Finite Element Method (FEM)
Definition Concepts.h:19
void GemmGradient(Eigen::DenseBase< TDerivedE > const &E, Eigen::Index nNodes, Eigen::DenseBase< TDerivedeg > const &eg, Eigen::MatrixBase< TDerivedGNeg > const &GNeg, Eigen::MatrixBase< TDerivedIn > const &X, Eigen::DenseBase< TDerivedOut > &Y)
Compute gradient matrix-vector multiply .
Definition Gradient.h:164
auto GradientMatrix(Eigen::DenseBase< TDerivedE > const &E, Eigen::Index nNodes, Eigen::DenseBase< TDerivedeg > const &eg, Eigen::MatrixBase< TDerivedGNeg > const &GNeg) -> Eigen::SparseMatrix< typename TDerivedGNeg::Scalar, Options, typename TDerivedE::Scalar >
Construct the gradient operator's sparse matrix representation.
Definition Gradient.h:219
Profiling utilities for the Physics-Based Animation Toolkit (PBAT)