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
Gradient.h
Go to the documentation of this file.
1
20
21#ifndef PBAT_FEM_GRADIENT_H
22#define PBAT_FEM_GRADIENT_H
23
24#include "Concepts.h"
25#include "ShapeFunctions.h"
26#include "pbat/Aliases.h"
27#include "pbat/common/Eigen.h"
29
30#include <exception>
31#include <fmt/core.h>
32#include <tbb/parallel_for.h>
33
34namespace pbat::fem {
35
54template <
55 CElement TElement,
56 int Dims,
57 class TDerivedE,
58 class TDerivedeg,
59 class TDerivedGNeg,
60 class TDerivedIn,
61 class TDerivedOut>
62void GemmGradient(
63 Eigen::DenseBase<TDerivedE> const& E,
64 Eigen::Index nNodes,
65 Eigen::DenseBase<TDerivedeg> const& eg,
66 Eigen::MatrixBase<TDerivedGNeg> const& GNeg,
67 Eigen::MatrixBase<TDerivedIn> const& X,
68 Eigen::DenseBase<TDerivedOut>& Y);
69
84template <CMesh TMesh, class TDerivedeg, class TDerivedGNeg, class TDerivedIn, class TDerivedOut>
85inline void GemmGradient(
86 TMesh const& mesh,
87 Eigen::DenseBase<TDerivedeg> const& eg,
88 Eigen::MatrixBase<TDerivedGNeg> const& GNeg,
89 Eigen::MatrixBase<TDerivedIn> const& X,
90 Eigen::DenseBase<TDerivedOut>& Y)
91{
93 mesh.E,
94 static_cast<typename TMesh::IndexType>(mesh.X.cols()),
95 eg.derived(),
96 GNeg.derived(),
97 X.derived(),
98 Y.derived());
99}
100
116template <
117 CElement TElement,
118 int Dims,
119 Eigen::StorageOptions Options,
120 class TDerivedE,
121 class TDerivedeg,
122 class TDerivedGNeg>
123auto GradientMatrix(
124 Eigen::DenseBase<TDerivedE> const& E,
125 Eigen::Index nNodes,
126 Eigen::DenseBase<TDerivedeg> const& eg,
127 Eigen::MatrixBase<TDerivedGNeg> const& GNeg)
128 -> Eigen::SparseMatrix<typename TDerivedGNeg::Scalar, Options, typename TDerivedE::Scalar>;
129
142template <Eigen::StorageOptions Options, CMesh TMesh, class TDerivedeg, class TDerivedGNeg>
144 TMesh const& mesh,
145 Eigen::DenseBase<TDerivedeg> const& eg,
146 Eigen::MatrixBase<TDerivedGNeg> const& GNeg)
147 -> Eigen::SparseMatrix<typename TDerivedGNeg::Scalar, Options, typename TMesh::IndexType>
148{
150 mesh.E,
151 static_cast<typename TMesh::IndexType>(mesh.X.cols()),
152 eg.derived(),
153 GNeg.derived());
154}
155
156template <
157 CElement TElement,
158 int Dims,
159 class TDerivedE,
160 class TDerivedeg,
161 class TDerivedGNeg,
162 class TDerivedIn,
163 class TDerivedOut>
164inline void GemmGradient(
165 Eigen::DenseBase<TDerivedE> const& E,
166 Eigen::Index nNodes,
167 Eigen::DenseBase<TDerivedeg> const& eg,
168 Eigen::MatrixBase<TDerivedGNeg> const& GNeg,
169 Eigen::MatrixBase<TDerivedIn> const& X,
170 Eigen::DenseBase<TDerivedOut>& Y)
171{
172 PBAT_PROFILE_NAMED_SCOPE("pbat.fem.GemmGradient");
173 // Check inputs
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)
179 {
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 {})",
184 cols,
185 rows,
186 X.rows(),
187 X.cols(),
188 Y.rows(),
189 Y.cols());
190 throw std::invalid_argument(what);
191 }
192 // Compute gradient
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)
197 {
198 for (auto g = 0; g < nQuadPts; ++g)
199 {
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)
205 {
206 Y(d * nQuadPts + g) += Geg(Eigen::placeholders::all, d).transpose() * Xe;
207 }
208 }
209 }
210}
211
212template <
213 CElement TElement,
214 int Dims,
215 Eigen::StorageOptions Options,
216 class TDerivedE,
217 class TDerivedeg,
218 class TDerivedGNeg>
220 Eigen::DenseBase<TDerivedE> const& E,
221 Eigen::Index nNodes,
222 Eigen::DenseBase<TDerivedeg> const& eg,
223 Eigen::MatrixBase<TDerivedGNeg> const& GNeg)
224 -> Eigen::SparseMatrix<typename TDerivedGNeg::Scalar, Options, typename TDerivedE::Scalar>
225{
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>;
231
232 // Compile-time constants
233 static_assert(
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;
238
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);
243
244 for (auto g = 0; g < nQuadPts; ++g)
245 {
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)
250 {
251 for (auto j = 0; j < kNodesPerElement; ++j)
252 {
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));
256 }
257 }
258 }
259 G.setFromTriplets(triplets.begin(), triplets.end());
260 return G;
261}
262
263} // namespace pbat::fem
264
265#endif // PBAT_FEM_GRADIENT_H
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)