31#ifndef MFEM_BILININTEG_ELASTICITY_KERNELS_HPP
32#define MFEM_BILININTEG_ELASTICITY_KERNELS_HPP
65void ElasticityAddMultPA(
const int dim,
const int nDofs,
66 const FiniteElementSpace &fespace,
const CoefficientVector &lambda,
67 const CoefficientVector &
mu,
const GeometricFactors &geom,
68 const DofToQuad &maps,
const Vector &x, QuadratureFunction &QVec, Vector &y);
93void ElasticityComponentAddMultPA(
94 const int dim,
const int nDofs,
const FiniteElementSpace &fespace,
95 const CoefficientVector &lambda,
const CoefficientVector &
mu,
96 const GeometricFactors &geom,
const DofToQuad &maps,
const Vector &x,
97 QuadratureFunction &QVec, Vector &y,
const int i_block,
const int j_block);
121void ElasticityAssembleEA(
const int dim,
const int i_block,
const int j_block,
122 const int nDofs,
const IntegrationRule &ir,
123 const CoefficientVector &lambda,
124 const CoefficientVector &
mu,
const GeometricFactors &geom,
125 const DofToQuad &maps, Vector &emat);
137void ElasticityAssembleDiagonalPA(
const int dim,
const int nDofs,
138 const CoefficientVector &lambda,
139 const CoefficientVector &
mu,
const GeometricFactors &geom,
140 const DofToQuad &maps,
const IntegrationRule &ir, Vector &diag);
143template<
int dim,
int i_block = -1,
int j_block = -1>
144void ElasticityAddMultPA_(
const int nDofs,
const FiniteElementSpace &fespace,
145 const CoefficientVector &lambda,
const CoefficientVector &
mu,
146 const GeometricFactors &geom,
const DofToQuad &maps,
const Vector &x,
147 QuadratureFunction &QVec, Vector &y)
149 using future::tensor;
154 static_assert((i_block < 0) == (j_block < 0),
155 "i_block and j_block must both be non-negative or strictly negative.");
156 static constexpr int d =
dim;
157 static constexpr int qLower = (i_block < 0) ? 0 : i_block;
158 static constexpr int qUpper = (i_block < 0) ? d : i_block+1;
159 static constexpr int qSize = qUpper-qLower;
160 static constexpr int aLower = (j_block < 0) ? 0 : j_block;
161 static constexpr int aUpper = (j_block < 0) ? d : j_block+1;
162 static constexpr int aSize = aUpper-aLower;
163 static constexpr bool isComponent = (i_block >= 0);
166 const auto &ir = QVec.GetIntRule(0);
167 const QuadratureInterpolator *E_To_Q_Map = fespace.GetQuadratureInterpolator(
171 E_To_Q_Map->PhysDerivatives(x, QVec);
173 const int numPoints = ir.GetNPoints();
174 const int numEls = fespace.GetNE();
175 const auto lamDev =
Reshape(lambda.Read(), numPoints, numEls);
176 const auto muDev =
Reshape(
mu.Read(), numPoints, numEls);
177 const auto J =
Reshape(geom.J.Read(), numPoints, d, d, numEls);
178 auto Q =
Reshape(QVec.ReadWrite(), numPoints, d, qSize, numEls);
179 const real_t *ipWeights = ir.GetWeights().Read();
183 MFEM_FOREACH_THREAD(
p, x,numPoints)
185 auto invJ =
inv(make_tensor<d, d>(
186 [&](
int i,
int j) {
return J(
p, i, j, e); }));
187 tensor<real_t, aSize, d> gradx;
191 for (
int i = 0; i < d; i++)
193 gradx(0,i) = Q(
p, i, 0, e);
198 for (
int j = 0; j < d; j++)
200 for (
int i = 0; i < d; i++)
202 gradx(i,j) = Q(
p, i, j, e);
208 for (
int i = aLower; i < aUpper; i++)
211 const int iIndex = isComponent ? 0 : i;
212 div += gradx(iIndex,i);
215 for (
int m = 0; m < d; m++)
217 for (
int q = qLower; q < qUpper; q++)
226 for (
int a = 0;
a < d;
a++)
228 contraction += 2*((
a == q)*invJ(m,j_block)
229 + (j_block==q)*invJ(m,
a))*(gradx(0,
a));
234 for (
int a = 0;
a < d;
a++)
236 for (
int b = 0;
b < d;
b++)
238 contraction += ((
a == q)*invJ(m,
b) + (
b == q)*invJ(m,
a))
239 *(gradx(
a,
b) + gradx(
b,
a));
245 const int qIndex = isComponent ? 0 : q;
246 Q(
p,m,qIndex,e) = w*(lamDev(
p, e)*invJ(m,q)*div
247 + 0.5*muDev(
p, e)*contraction);
254 const auto QRead =
Reshape(QVec.Read(), numPoints, d, qSize, numEls);
255 const auto G =
Reshape(maps.G.Read(), numPoints, d, nDofs);
256 auto yDev =
Reshape(y.ReadWrite(), nDofs, qSize, numEls);
259 MFEM_FOREACH_THREAD(i, y, nDofs)
261 MFEM_FOREACH_THREAD(q, x, qSize)
263 const int qIndex = isComponent ? 0 : q;
265 for (
int m = 0; m < d; m++ )
267 for (
int p = 0;
p < numPoints;
p++ )
269 sum += QRead(
p,m,qIndex,e)*G(
p,m,i);
272 yDev(i, qIndex, e) += sum;
280void ElasticityAssembleDiagonalPA_(
const int nDofs,
281 const CoefficientVector &lambda,
282 const CoefficientVector &
mu,
283 const GeometricFactors &geom,
284 const DofToQuad &maps,
285 const IntegrationRule &ir,
291 using future::tensor;
294 static constexpr int d =
dim;
295 const int numPoints = ir.GetNPoints();
296 const int numEls = lambda.Size() / numPoints;
298 const auto lamDev =
Reshape(lambda.Read(), numPoints, numEls);
299 const auto muDev =
Reshape(
mu.Read(), numPoints, numEls);
300 const auto J =
Reshape(geom.J.Read(), numPoints, d, d, numEls);
301 const real_t *ipWeights = ir.GetWeights().Read();
302 const auto G =
Reshape(maps.G.Read(), numPoints, d, nDofs);
303 auto diagDev =
Reshape(diag.Write(), nDofs, d, numEls);
307 MFEM_FOREACH_THREAD_DIRECT(i, y, nDofs)
309 MFEM_FOREACH_THREAD_DIRECT(q, x, d)
312 for (
int p = 0;
p < numPoints;
p++)
314 const auto invJ =
inv(make_tensor<d, d>([&](
int r,
int c)
316 return J(
p, r, c, e);
320 for (
int n = 0; n < d; n++)
322 for (
int m = 0; m < d; m++)
328 for (
int a = 0;
a < d;
a++)
330 for (
int b = 0;
b < d;
b++)
333 ((
a == q) * invJ(m,
b) + (
b == q) * invJ(m,
a)) *
334 ((
a == q) * invJ(n,
b) + (
b == q) * invJ(n,
a));
340 w * (lamDev(
p, e) * invJ(m, q) * invJ(n, q)
341 + 0.5 * muDev(
p, e) * contraction);
342 sum += Q * G(
p, m, i) * G(
p, n, i);
346 diagDev(i, q, e) = sum;
354void ElasticityAssembleEA_(
const int i_block,
357 const IntegrationRule &ir,
358 const CoefficientVector &lambda,
359 const CoefficientVector &
mu,
360 const GeometricFactors &geom,
361 const DofToQuad &maps,
364 using future::tensor;
370 static constexpr int d =
dim;
371 const int numPoints = ir.GetNPoints();
372 const int numEls = lambda.Size()/numPoints;
373 const auto lamDev =
Reshape(lambda.Read(), numPoints, numEls);
374 const auto muDev =
Reshape(
mu.Read(), numPoints, numEls);
375 const auto J =
Reshape(geom.J.Read(), numPoints, d, d, numEls);
376 const auto G =
Reshape(maps.G.Read(), numPoints, d, nDofs);
377 auto ematDev =
Reshape(emat.Write(), nDofs, nDofs, numEls);
378 const real_t *ipWeights = ir.GetWeights().Read();
381 MFEM_FOREACH_THREAD(JDof, y, nDofs)
383 MFEM_FOREACH_THREAD(IDof, x, nDofs)
386 for (
int p = 0 ;
p < numPoints;
p++)
388 auto invJ =
inv(make_tensor<d, d>(
389 [&](
int i,
int j) {
return J(
p, i, j, e); }));
391 for (
int n = 0; n < d; n++)
393 for (
int m = 0; m < d; m++)
397 for (
int a = 0;
a < d;
a++)
399 for (
int b = 0;
b < d;
b++)
401 contraction += ((
a == i_block)*invJ(m,
b) + (
b==i_block)*invJ(m,
402 a))*((
a == j_block)*invJ(n,
403 b) + (
b==j_block)*invJ(n,
a));
408 sum += w*(lamDev(
p, e)*invJ(m,i_block)*invJ(n,j_block)
409 + 0.5*muDev(
p, e)*contraction)*G(
p,m,IDof)*G(
p,n,JDof);
413 ematDev(IDof, JDof, e) = sum;
MFEM_HOST_DEVICE T det(const tensor< T, 1, 1 > &A)
Returns the determinant of a matrix.
MFEM_HOST_DEVICE constexpr auto make_tensor(lambda_type f) -> tensor< decltype(f())>
Creates a tensor of requested dimension by subsequent calls to a functor Can be thought of as analogo...
MFEM_HOST_DEVICE tensor< T, 1, 1 > inv(const tensor< T, 1, 1 > &A)
Inverts a matrix.
MFEM_HOST_DEVICE DeviceTensor< sizeof...(Dims), T > Reshape(T *ptr, Dims... dims)
Wrap a pointer as a DeviceTensor with automatically deduced template parameters.
void forall_2D(int N, int X, int Y, lambda &&body)
real_t p(const Vector &x, real_t t)
Implementation of the tensor class.