xref: /libCEED/examples/solids/qfunctions/finite-strain-mooney-rivlin.h (revision d4cc18453651bd0f94c1a2e078b2646a92dafdcc)
1*9ba83ac0SJeremy L Thompson // Copyright (c) 2017-2026, Lawrence Livermore National Security, LLC and other CEED contributors.
2c8565611SJeremy L Thompson // All Rights Reserved. See the top-level LICENSE and NOTICE files for details.
3c8565611SJeremy L Thompson //
4c8565611SJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause
5c8565611SJeremy L Thompson //
6c8565611SJeremy L Thompson // This file is part of CEED:  http://github.com/ceed
7c8565611SJeremy L Thompson 
8c8565611SJeremy L Thompson /// @file
9c8565611SJeremy L Thompson /// Hyperelasticity, finite strain for solid mechanics example using PETSc
10c8565611SJeremy L Thompson 
11c0b5abf0SJeremy L Thompson #include <ceed/types.h>
12c0b5abf0SJeremy L Thompson #ifndef CEED_RUNNING_JIT_PASS
13c8565611SJeremy L Thompson #include <math.h>
14c0b5abf0SJeremy L Thompson #endif
15c8565611SJeremy L Thompson 
16c8565611SJeremy L Thompson // -----------------------------------------------------------------------------
17c8565611SJeremy L Thompson // Mooney-Rivlin context
18c8565611SJeremy L Thompson #ifndef PHYSICS_STRUCT_MR
19c8565611SJeremy L Thompson #define PHYSICS_STRUCT_MR
20c8565611SJeremy L Thompson typedef struct Physics_private_MR *Physics_MR;
21c8565611SJeremy L Thompson 
22c8565611SJeremy L Thompson struct Physics_private_MR {
23c8565611SJeremy L Thompson   // material properties for MR
24c8565611SJeremy L Thompson   CeedScalar mu_1;
25c8565611SJeremy L Thompson   CeedScalar mu_2;
26c8565611SJeremy L Thompson   CeedScalar lambda;
27c8565611SJeremy L Thompson };
28c8565611SJeremy L Thompson #endif
29c8565611SJeremy L Thompson 
30c8565611SJeremy L Thompson // -----------------------------------------------------------------------------
31c8565611SJeremy L Thompson // Series approximation of log1p()
32c8565611SJeremy L Thompson //  log1p() is not vectorized in libc
33c8565611SJeremy L Thompson //
34c8565611SJeremy L Thompson //  The series expansion is accurate to 1e-7 in the range sqrt(2)/2 < J < sqrt(2), with machine precision accuracy near J=1.
35c8565611SJeremy L Thompson //  The initialization extends this range to 0.35 ~= sqrt(2)/4 < J < sqrt(2)*2 ~= 2.83, which should be sufficient for applications of the Neo-Hookean
36c8565611SJeremy L Thompson //  model.
37c8565611SJeremy L Thompson // -----------------------------------------------------------------------------
38c8565611SJeremy L Thompson #ifndef LOG1P_SERIES_SHIFTED
39c8565611SJeremy L Thompson #define LOG1P_SERIES_SHIFTED
log1p_series_shifted(CeedScalar x)40c8565611SJeremy L Thompson CEED_QFUNCTION_HELPER CeedScalar log1p_series_shifted(CeedScalar x) {
41c8565611SJeremy L Thompson   const CeedScalar left = sqrt(2.) / 2 - 1, right = sqrt(2.) - 1;
42c8565611SJeremy L Thompson   CeedScalar       sum = 0;
43c8565611SJeremy L Thompson   if (1) {           // Disable if the smaller range sqrt(2)/2 < J < sqrt(2) is sufficient
44c8565611SJeremy L Thompson     if (x < left) {  // Replace if with while for arbitrary range (may hurt vectorization)
45c8565611SJeremy L Thompson       sum -= log(2.) / 2;
46c8565611SJeremy L Thompson       x = 1 + 2 * x;
47c8565611SJeremy L Thompson     } else if (right < x) {
48c8565611SJeremy L Thompson       sum += log(2.) / 2;
49c8565611SJeremy L Thompson       x = (x - 1) / 2;
50c8565611SJeremy L Thompson     }
51c8565611SJeremy L Thompson   }
52c8565611SJeremy L Thompson   CeedScalar       y  = x / (2. + x);
53c8565611SJeremy L Thompson   const CeedScalar y2 = y * y;
54c8565611SJeremy L Thompson   sum += y;
55c8565611SJeremy L Thompson   y *= y2;
56c8565611SJeremy L Thompson   sum += y / 3;
57c8565611SJeremy L Thompson   y *= y2;
58c8565611SJeremy L Thompson   sum += y / 5;
59c8565611SJeremy L Thompson   y *= y2;
60c8565611SJeremy L Thompson   sum += y / 7;
61c8565611SJeremy L Thompson   return 2 * sum;
62c8565611SJeremy L Thompson };
63c8565611SJeremy L Thompson #endif
64c8565611SJeremy L Thompson 
65c8565611SJeremy L Thompson // -----------------------------------------------------------------------------
66c8565611SJeremy L Thompson // Compute det F - 1
67c8565611SJeremy L Thompson // -----------------------------------------------------------------------------
68c8565611SJeremy L Thompson #ifndef DETJM1
69c8565611SJeremy L Thompson #define DETJM1
computeJM1(const CeedScalar grad_u[3][3])70c8565611SJeremy L Thompson CEED_QFUNCTION_HELPER CeedScalar computeJM1(const CeedScalar grad_u[3][3]) {
71c8565611SJeremy L Thompson   return grad_u[0][0] * (grad_u[1][1] * grad_u[2][2] - grad_u[1][2] * grad_u[2][1]) +
72c8565611SJeremy L Thompson          grad_u[0][1] * (grad_u[1][2] * grad_u[2][0] - grad_u[1][0] * grad_u[2][2]) +
73c8565611SJeremy L Thompson          grad_u[0][2] * (grad_u[1][0] * grad_u[2][1] - grad_u[2][0] * grad_u[1][1]) + grad_u[0][0] + grad_u[1][1] + grad_u[2][2] +
74c8565611SJeremy L Thompson          grad_u[0][0] * grad_u[1][1] + grad_u[0][0] * grad_u[2][2] + grad_u[1][1] * grad_u[2][2] - grad_u[0][1] * grad_u[1][0] -
75c8565611SJeremy L Thompson          grad_u[0][2] * grad_u[2][0] - grad_u[1][2] * grad_u[2][1];
76c8565611SJeremy L Thompson };
77c8565611SJeremy L Thompson #endif
78c8565611SJeremy L Thompson 
79c8565611SJeremy L Thompson // -----------------------------------------------------------------------------
80c8565611SJeremy L Thompson // Compute matrix^(-1), where matrix is symetric, returns array of 6
81c8565611SJeremy L Thompson // -----------------------------------------------------------------------------
82c8565611SJeremy L Thompson #ifndef MatinvSym
83c8565611SJeremy L Thompson #define MatinvSym
computeMatinvSym(const CeedScalar A[3][3],const CeedScalar detA,CeedScalar Ainv[6])84c8565611SJeremy L Thompson CEED_QFUNCTION_HELPER int computeMatinvSym(const CeedScalar A[3][3], const CeedScalar detA, CeedScalar Ainv[6]) {
85c8565611SJeremy L Thompson   // Compute A^(-1) : A-Inverse
86c8565611SJeremy L Thompson   CeedScalar B[6] = {
87c8565611SJeremy L Thompson       A[1][1] * A[2][2] - A[1][2] * A[2][1], /* *NOPAD* */
88c8565611SJeremy L Thompson       A[0][0] * A[2][2] - A[0][2] * A[2][0], /* *NOPAD* */
89c8565611SJeremy L Thompson       A[0][0] * A[1][1] - A[0][1] * A[1][0], /* *NOPAD* */
90c8565611SJeremy L Thompson       A[0][2] * A[1][0] - A[0][0] * A[1][2], /* *NOPAD* */
91c8565611SJeremy L Thompson       A[0][1] * A[1][2] - A[0][2] * A[1][1], /* *NOPAD* */
92c8565611SJeremy L Thompson       A[0][2] * A[2][1] - A[0][1] * A[2][2]  /* *NOPAD* */
93c8565611SJeremy L Thompson   };
94c8565611SJeremy L Thompson   for (CeedInt m = 0; m < 6; m++) Ainv[m] = B[m] / (detA);
95c8565611SJeremy L Thompson 
96c8565611SJeremy L Thompson   return CEED_ERROR_SUCCESS;
97c8565611SJeremy L Thompson }
98c8565611SJeremy L Thompson #endif
99c8565611SJeremy L Thompson // -----------------------------------------------------------------------------
100c8565611SJeremy L Thompson // Common computations between FS and dFS
101c8565611SJeremy L Thompson // -----------------------------------------------------------------------------
commonFSMR(const CeedScalar mu_1,const CeedScalar mu_2,const CeedScalar lambda,const CeedScalar grad_u[3][3],CeedScalar Swork[6],CeedScalar Cwork[6],CeedScalar Cinvwork[6],CeedScalar * logJ)102c8565611SJeremy L Thompson CEED_QFUNCTION_HELPER int commonFSMR(const CeedScalar mu_1, const CeedScalar mu_2, const CeedScalar lambda, const CeedScalar grad_u[3][3],
103c8565611SJeremy L Thompson                                      CeedScalar Swork[6], CeedScalar Cwork[6], CeedScalar Cinvwork[6], CeedScalar *logJ) {
104c8565611SJeremy L Thompson   // E - Green-Lagrange strain tensor
105c8565611SJeremy L Thompson   //     E = 1/2 (grad_u + grad_u^T + grad_u^T*grad_u)
106c8565611SJeremy L Thompson   const CeedInt indj[6] = {0, 1, 2, 1, 0, 0}, indk[6] = {0, 1, 2, 2, 2, 1};
107c8565611SJeremy L Thompson   CeedScalar    E2work[6];
108c8565611SJeremy L Thompson   for (CeedInt m = 0; m < 6; m++) {
109c8565611SJeremy L Thompson     E2work[m] = grad_u[indj[m]][indk[m]] + grad_u[indk[m]][indj[m]];
110c8565611SJeremy L Thompson     for (CeedInt n = 0; n < 3; n++) E2work[m] += grad_u[n][indj[m]] * grad_u[n][indk[m]];
111c8565611SJeremy L Thompson   }
112c8565611SJeremy L Thompson   CeedScalar E2[3][3] = {
113c8565611SJeremy L Thompson       {E2work[0], E2work[5], E2work[4]},
114c8565611SJeremy L Thompson       {E2work[5], E2work[1], E2work[3]},
115c8565611SJeremy L Thompson       {E2work[4], E2work[3], E2work[2]}
116c8565611SJeremy L Thompson   };
117c8565611SJeremy L Thompson 
118c8565611SJeremy L Thompson   // C : right Cauchy-Green tensor
119c8565611SJeremy L Thompson   // C = I + 2E
120c8565611SJeremy L Thompson   const CeedScalar C[3][3] = {
121c8565611SJeremy L Thompson       {1 + E2[0][0], E2[0][1],     E2[0][2]    },
122c8565611SJeremy L Thompson       {E2[0][1],     1 + E2[1][1], E2[1][2]    },
123c8565611SJeremy L Thompson       {E2[0][2],     E2[1][2],     1 + E2[2][2]}
124c8565611SJeremy L Thompson   };
125c8565611SJeremy L Thompson 
126c8565611SJeremy L Thompson   Cwork[0] = C[0][0];
127c8565611SJeremy L Thompson   Cwork[1] = C[1][1];
128c8565611SJeremy L Thompson   Cwork[2] = C[2][2];
129c8565611SJeremy L Thompson   Cwork[3] = C[1][2];
130c8565611SJeremy L Thompson   Cwork[4] = C[0][2];
131c8565611SJeremy L Thompson   Cwork[5] = C[0][1];
132c8565611SJeremy L Thompson   // Compute invariants
133c8565611SJeremy L Thompson   // I_1 = trace(C)
134c8565611SJeremy L Thompson   const CeedScalar I_1 = C[0][0] + C[1][1] + C[2][2];
135c8565611SJeremy L Thompson   // J-1
136c8565611SJeremy L Thompson   const CeedScalar Jm1 = computeJM1(grad_u);
137c8565611SJeremy L Thompson   // J = Jm1 + 1
138c8565611SJeremy L Thompson   // Compute C^(-1) : C-Inverse
139c8565611SJeremy L Thompson   const CeedScalar detC = (Jm1 + 1.) * (Jm1 + 1.);
140c8565611SJeremy L Thompson   computeMatinvSym(C, detC, Cinvwork);
141c8565611SJeremy L Thompson 
142c8565611SJeremy L Thompson   // Compute the Second Piola-Kirchhoff (S)
143c8565611SJeremy L Thompson   // S = (lambda*logJ - mu_1 -2*mu_2)*Cinvwork +(mu_1+mu_2*I_1)*I3-mu_2*Cwork
144c8565611SJeremy L Thompson   // *1 for indices 0-2 for I_3
145c8565611SJeremy L Thompson 
146c8565611SJeremy L Thompson   *logJ = log1p_series_shifted(Jm1);
147c8565611SJeremy L Thompson   for (CeedInt i = 0; i < 6; i++) {
148c8565611SJeremy L Thompson     Swork[i] = (lambda * *logJ - mu_1 - 2 * mu_2) * Cinvwork[i] + (mu_1 + mu_2 * I_1) * (i < 3)  // identity I_3
149c8565611SJeremy L Thompson                - mu_2 * Cwork[i];
150c8565611SJeremy L Thompson   }
151c8565611SJeremy L Thompson 
152c8565611SJeremy L Thompson   return CEED_ERROR_SUCCESS;
153c8565611SJeremy L Thompson }
154c8565611SJeremy L Thompson 
155c8565611SJeremy L Thompson // -----------------------------------------------------------------------------
156c8565611SJeremy L Thompson // Residual evaluation for hyperelasticity, finite strain
157c8565611SJeremy L Thompson // -----------------------------------------------------------------------------
ElasFSResidual_MR(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)158c8565611SJeremy L Thompson CEED_QFUNCTION(ElasFSResidual_MR)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
159c8565611SJeremy L Thompson   // Inputs
160c8565611SJeremy L Thompson   const CeedScalar(*ug)[3][CEED_Q_VLA] = (const CeedScalar(*)[3][CEED_Q_VLA])in[0], (*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[1];
161c8565611SJeremy L Thompson 
162c8565611SJeremy L Thompson   // Outputs
163c8565611SJeremy L Thompson   CeedScalar(*dvdX)[3][CEED_Q_VLA] = (CeedScalar(*)[3][CEED_Q_VLA])out[0];
164c8565611SJeremy L Thompson   // Store grad_u for HyperFSdF (Jacobian of HyperFSF)
165c8565611SJeremy L Thompson   CeedScalar(*grad_u)[3][CEED_Q_VLA] = (CeedScalar(*)[3][CEED_Q_VLA])out[1];
166c8565611SJeremy L Thompson 
167c8565611SJeremy L Thompson   // Context
168c8565611SJeremy L Thompson   const Physics_MR context = (Physics_MR)ctx;
169c8565611SJeremy L Thompson   const CeedScalar mu_1    = context->mu_1;
170c8565611SJeremy L Thompson   const CeedScalar mu_2    = context->mu_2;
171c8565611SJeremy L Thompson   const CeedScalar lambda  = context->lambda;
172c8565611SJeremy L Thompson 
173c8565611SJeremy L Thompson   // Formulation Terminology:
174c8565611SJeremy L Thompson   //  I3    : 3x3 Identity matrix
175c8565611SJeremy L Thompson   //  C     : right Cauchy-Green tensor
176c8565611SJeremy L Thompson   //  C_inv : inverse of C
177c8565611SJeremy L Thompson   //  F     : deformation gradient
178c8565611SJeremy L Thompson   //  S     : 2nd Piola-Kirchhoff
179c8565611SJeremy L Thompson   //  P     : 1st Piola-Kirchhoff
180c8565611SJeremy L Thompson 
181c8565611SJeremy L Thompson   // Quadrature Point Loop
182c8565611SJeremy L Thompson   CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) {
183c8565611SJeremy L Thompson     // Read spatial derivatives of u
184c8565611SJeremy L Thompson     const CeedScalar du[3][3] = {
185c8565611SJeremy L Thompson         {ug[0][0][i], ug[1][0][i], ug[2][0][i]},
186c8565611SJeremy L Thompson         {ug[0][1][i], ug[1][1][i], ug[2][1][i]},
187c8565611SJeremy L Thompson         {ug[0][2][i], ug[1][2][i], ug[2][2][i]}
188c8565611SJeremy L Thompson     };
189c8565611SJeremy L Thompson     // -- Qdata
190c8565611SJeremy L Thompson     const CeedScalar wdetJ      = q_data[0][i];
191c8565611SJeremy L Thompson     const CeedScalar dXdx[3][3] = {
192c8565611SJeremy L Thompson         {q_data[1][i], q_data[2][i], q_data[3][i]},
193c8565611SJeremy L Thompson         {q_data[4][i], q_data[5][i], q_data[6][i]},
194c8565611SJeremy L Thompson         {q_data[7][i], q_data[8][i], q_data[9][i]}
195c8565611SJeremy L Thompson     };
196c8565611SJeremy L Thompson 
197c8565611SJeremy L Thompson     // Compute grad_u
198c8565611SJeremy L Thompson     //   dXdx = (dx/dX)^(-1)
199c8565611SJeremy L Thompson     // Apply dXdx to du = grad_u
200c8565611SJeremy L Thompson     for (CeedInt j = 0; j < 3; j++) {    // Component
201c8565611SJeremy L Thompson       for (CeedInt k = 0; k < 3; k++) {  // Derivative
202c8565611SJeremy L Thompson         grad_u[j][k][i] = 0;
203c8565611SJeremy L Thompson         for (CeedInt m = 0; m < 3; m++) grad_u[j][k][i] += dXdx[m][k] * du[j][m];
204c8565611SJeremy L Thompson       }
205c8565611SJeremy L Thompson     }
206c8565611SJeremy L Thompson 
207c8565611SJeremy L Thompson     // I3 : 3x3 Identity matrix
208c8565611SJeremy L Thompson     // Compute The Deformation Gradient : F = I3 + grad_u
209c8565611SJeremy L Thompson     const CeedScalar F[3][3] = {
210c8565611SJeremy L Thompson         {grad_u[0][0][i] + 1, grad_u[0][1][i],     grad_u[0][2][i]    },
211c8565611SJeremy L Thompson         {grad_u[1][0][i],     grad_u[1][1][i] + 1, grad_u[1][2][i]    },
212c8565611SJeremy L Thompson         {grad_u[2][0][i],     grad_u[2][1][i],     grad_u[2][2][i] + 1}
213c8565611SJeremy L Thompson     };
214c8565611SJeremy L Thompson 
215c8565611SJeremy L Thompson     const CeedScalar tempgradu[3][3] = {
216c8565611SJeremy L Thompson         {grad_u[0][0][i], grad_u[0][1][i], grad_u[0][2][i]},
217c8565611SJeremy L Thompson         {grad_u[1][0][i], grad_u[1][1][i], grad_u[1][2][i]},
218c8565611SJeremy L Thompson         {grad_u[2][0][i], grad_u[2][1][i], grad_u[2][2][i]}
219c8565611SJeremy L Thompson     };
220c8565611SJeremy L Thompson 
221c8565611SJeremy L Thompson     // Common components of finite strain calculations
222c8565611SJeremy L Thompson     CeedScalar Swork[6], Cwork[6], Cinvwork[6], logJ;
223c8565611SJeremy L Thompson     commonFSMR(mu_1, mu_2, lambda, tempgradu, Swork, Cwork, Cinvwork, &logJ);
224c8565611SJeremy L Thompson 
225c8565611SJeremy L Thompson     // Second Piola-Kirchhoff (S)
226c8565611SJeremy L Thompson     const CeedScalar S[3][3] = {
227c8565611SJeremy L Thompson         {Swork[0], Swork[5], Swork[4]},
228c8565611SJeremy L Thompson         {Swork[5], Swork[1], Swork[3]},
229c8565611SJeremy L Thompson         {Swork[4], Swork[3], Swork[2]}
230c8565611SJeremy L Thompson     };
231c8565611SJeremy L Thompson 
232c8565611SJeremy L Thompson     // Compute the First Piola-Kirchhoff : P = F*S
233c8565611SJeremy L Thompson     CeedScalar P[3][3];
234c8565611SJeremy L Thompson     for (CeedInt j = 0; j < 3; j++) {
235c8565611SJeremy L Thompson       for (CeedInt k = 0; k < 3; k++) {
236c8565611SJeremy L Thompson         P[j][k] = 0;
237c8565611SJeremy L Thompson         for (CeedInt m = 0; m < 3; m++) P[j][k] += F[j][m] * S[m][k];
238c8565611SJeremy L Thompson       }
239c8565611SJeremy L Thompson     }
240c8565611SJeremy L Thompson 
241c8565611SJeremy L Thompson     // Apply dXdx^T and weight to P (First Piola-Kirchhoff)
242c8565611SJeremy L Thompson     for (CeedInt j = 0; j < 3; j++) {    // Component
243c8565611SJeremy L Thompson       for (CeedInt k = 0; k < 3; k++) {  // Derivative
244c8565611SJeremy L Thompson         dvdX[k][j][i] = 0;
245c8565611SJeremy L Thompson         for (CeedInt m = 0; m < 3; m++) dvdX[k][j][i] += dXdx[k][m] * P[j][m] * wdetJ;
246c8565611SJeremy L Thompson       }
247c8565611SJeremy L Thompson     }
248c8565611SJeremy L Thompson   }  // End of Quadrature Point Loop
249c8565611SJeremy L Thompson 
250c8565611SJeremy L Thompson   return CEED_ERROR_SUCCESS;
251c8565611SJeremy L Thompson }
252c8565611SJeremy L Thompson 
253c8565611SJeremy L Thompson // -----------------------------------------------------------------------------
254c8565611SJeremy L Thompson // Jacobian evaluation for hyperelasticity, finite strain
255c8565611SJeremy L Thompson // -----------------------------------------------------------------------------
ElasFSJacobian_MR(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)256c8565611SJeremy L Thompson CEED_QFUNCTION(ElasFSJacobian_MR)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
257c8565611SJeremy L Thompson   // Inputs
258c8565611SJeremy L Thompson   const CeedScalar(*deltaug)[3][CEED_Q_VLA] = (const CeedScalar(*)[3][CEED_Q_VLA])in[0],
259c8565611SJeremy L Thompson         (*q_data)[CEED_Q_VLA]               = (const CeedScalar(*)[CEED_Q_VLA])in[1];
260c8565611SJeremy L Thompson   // grad_u is used for hyperelasticity (non-linear)
261c8565611SJeremy L Thompson   const CeedScalar(*grad_u)[3][CEED_Q_VLA] = (const CeedScalar(*)[3][CEED_Q_VLA])in[2];
262c8565611SJeremy L Thompson 
263c8565611SJeremy L Thompson   // Outputs
264c8565611SJeremy L Thompson   CeedScalar(*deltadvdX)[3][CEED_Q_VLA] = (CeedScalar(*)[3][CEED_Q_VLA])out[0];
265c8565611SJeremy L Thompson 
266c8565611SJeremy L Thompson   // Context
267c8565611SJeremy L Thompson   const Physics_MR context = (Physics_MR)ctx;
268c8565611SJeremy L Thompson   const CeedScalar mu_1    = context->mu_1;
269c8565611SJeremy L Thompson   const CeedScalar mu_2    = context->mu_2;
270c8565611SJeremy L Thompson   const CeedScalar lambda  = context->lambda;
271c8565611SJeremy L Thompson 
272c8565611SJeremy L Thompson   // Quadrature Point Loop
273c8565611SJeremy L Thompson   CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) {
274c8565611SJeremy L Thompson     // Read spatial derivatives of delta_u
275c8565611SJeremy L Thompson     const CeedScalar deltadu[3][3] = {
276c8565611SJeremy L Thompson         {deltaug[0][0][i], deltaug[1][0][i], deltaug[2][0][i]},
277c8565611SJeremy L Thompson         {deltaug[0][1][i], deltaug[1][1][i], deltaug[2][1][i]},
278c8565611SJeremy L Thompson         {deltaug[0][2][i], deltaug[1][2][i], deltaug[2][2][i]}
279c8565611SJeremy L Thompson     };
280c8565611SJeremy L Thompson     // -- Qdata
281c8565611SJeremy L Thompson     const CeedScalar wdetJ      = q_data[0][i];
282c8565611SJeremy L Thompson     const CeedScalar dXdx[3][3] = {
283c8565611SJeremy L Thompson         {q_data[1][i], q_data[2][i], q_data[3][i]},
284c8565611SJeremy L Thompson         {q_data[4][i], q_data[5][i], q_data[6][i]},
285c8565611SJeremy L Thompson         {q_data[7][i], q_data[8][i], q_data[9][i]}
286c8565611SJeremy L Thompson     };
287c8565611SJeremy L Thompson 
288c8565611SJeremy L Thompson     // Compute graddeltau
289c8565611SJeremy L Thompson     //   dXdx = (dx/dX)^(-1)
290c8565611SJeremy L Thompson     // Apply dXdx to deltadu = graddelta
291c8565611SJeremy L Thompson     // this is dF
292c8565611SJeremy L Thompson     CeedScalar graddeltau[3][3];
293c8565611SJeremy L Thompson     for (CeedInt j = 0; j < 3; j++) {    // Component
294c8565611SJeremy L Thompson       for (CeedInt k = 0; k < 3; k++) {  // Derivative
295c8565611SJeremy L Thompson         graddeltau[j][k] = 0;
296c8565611SJeremy L Thompson         for (CeedInt m = 0; m < 3; m++) graddeltau[j][k] += dXdx[m][k] * deltadu[j][m];
297c8565611SJeremy L Thompson       }
298c8565611SJeremy L Thompson     }
299c8565611SJeremy L Thompson 
300c8565611SJeremy L Thompson     // I3 : 3x3 Identity matrix
301c8565611SJeremy L Thompson     // Deformation Gradient : F = I3 + grad_u
302c8565611SJeremy L Thompson     const CeedScalar F[3][3] = {
303c8565611SJeremy L Thompson         {grad_u[0][0][i] + 1, grad_u[0][1][i],     grad_u[0][2][i]    },
304c8565611SJeremy L Thompson         {grad_u[1][0][i],     grad_u[1][1][i] + 1, grad_u[1][2][i]    },
305c8565611SJeremy L Thompson         {grad_u[2][0][i],     grad_u[2][1][i],     grad_u[2][2][i] + 1}
306c8565611SJeremy L Thompson     };
307c8565611SJeremy L Thompson 
308c8565611SJeremy L Thompson     const CeedScalar tempgradu[3][3] = {
309c8565611SJeremy L Thompson         {grad_u[0][0][i], grad_u[0][1][i], grad_u[0][2][i]},
310c8565611SJeremy L Thompson         {grad_u[1][0][i], grad_u[1][1][i], grad_u[1][2][i]},
311c8565611SJeremy L Thompson         {grad_u[2][0][i], grad_u[2][1][i], grad_u[2][2][i]}
312c8565611SJeremy L Thompson     };
313c8565611SJeremy L Thompson 
314c8565611SJeremy L Thompson     // Common components of finite strain calculations
315c8565611SJeremy L Thompson     CeedScalar Swork[6], Cwork[6], Cinvwork[6], logJ;
316c8565611SJeremy L Thompson     commonFSMR(mu_1, mu_2, lambda, tempgradu, Swork, Cwork, Cinvwork, &logJ);
317c8565611SJeremy L Thompson 
318c8565611SJeremy L Thompson     // dE - Green-Lagrange strain tensor
319c8565611SJeremy L Thompson     const CeedInt indj[6] = {0, 1, 2, 1, 0, 0}, indk[6] = {0, 1, 2, 2, 2, 1};
320c8565611SJeremy L Thompson     CeedScalar    dEwork[6];
321c8565611SJeremy L Thompson     for (CeedInt m = 0; m < 6; m++) {
322c8565611SJeremy L Thompson       dEwork[m] = 0;
323c8565611SJeremy L Thompson       for (CeedInt n = 0; n < 3; n++) dEwork[m] += (graddeltau[n][indj[m]] * F[n][indk[m]] + F[n][indj[m]] * graddeltau[n][indk[m]]) / 2.;
324c8565611SJeremy L Thompson     }
325c8565611SJeremy L Thompson     CeedScalar dE[3][3] = {
326c8565611SJeremy L Thompson         {dEwork[0], dEwork[5], dEwork[4]},
327c8565611SJeremy L Thompson         {dEwork[5], dEwork[1], dEwork[3]},
328c8565611SJeremy L Thompson         {dEwork[4], dEwork[3], dEwork[2]}
329c8565611SJeremy L Thompson     };
330c8565611SJeremy L Thompson     // C : right Cauchy-Green tensor
331c8565611SJeremy L Thompson     // C^(-1) : C-Inverse
332c8565611SJeremy L Thompson     const CeedScalar C[3][3] = {
333c8565611SJeremy L Thompson         {Cwork[0], Cwork[5], Cwork[4]},
334c8565611SJeremy L Thompson         {Cwork[5], Cwork[1], Cwork[3]},
335c8565611SJeremy L Thompson         {Cwork[4], Cwork[3], Cwork[2]}
336c8565611SJeremy L Thompson     };
337c8565611SJeremy L Thompson     const CeedScalar C_inv[3][3] = {
338c8565611SJeremy L Thompson         {Cinvwork[0], Cinvwork[5], Cinvwork[4]},
339c8565611SJeremy L Thompson         {Cinvwork[5], Cinvwork[1], Cinvwork[3]},
340c8565611SJeremy L Thompson         {Cinvwork[4], Cinvwork[3], Cinvwork[2]}
341c8565611SJeremy L Thompson     };
342c8565611SJeremy L Thompson     // -- C_inv:dE
343c8565611SJeremy L Thompson     CeedScalar Cinv_contract_dE = 0;
344c8565611SJeremy L Thompson     for (CeedInt j = 0; j < 3; j++) {
345c8565611SJeremy L Thompson       for (CeedInt k = 0; k < 3; k++) Cinv_contract_dE += C_inv[j][k] * dE[j][k];
346c8565611SJeremy L Thompson     }
347c8565611SJeremy L Thompson 
348c8565611SJeremy L Thompson     // -- C:dE
349c8565611SJeremy L Thompson     CeedScalar C_contract_dE = 0;
350c8565611SJeremy L Thompson     for (CeedInt j = 0; j < 3; j++) {
351c8565611SJeremy L Thompson       for (CeedInt k = 0; k < 3; k++) C_contract_dE += C[j][k] * dE[j][k];
352c8565611SJeremy L Thompson     }
353c8565611SJeremy L Thompson 
354c8565611SJeremy L Thompson     // -- dE*C_inv
355c8565611SJeremy L Thompson     CeedScalar dE_Cinv[3][3];
356c8565611SJeremy L Thompson     for (CeedInt j = 0; j < 3; j++) {
357c8565611SJeremy L Thompson       for (CeedInt k = 0; k < 3; k++) {
358c8565611SJeremy L Thompson         dE_Cinv[j][k] = 0;
359c8565611SJeremy L Thompson         for (CeedInt m = 0; m < 3; m++) dE_Cinv[j][k] += dE[j][m] * C_inv[m][k];
360c8565611SJeremy L Thompson       }
361c8565611SJeremy L Thompson     }
362c8565611SJeremy L Thompson 
363c8565611SJeremy L Thompson     // -- C_inv*dE*C_inv
364c8565611SJeremy L Thompson     CeedScalar Cinv_dE_Cinv[3][3];
365c8565611SJeremy L Thompson     // This product is symmetric and we only use the upper-triangular part below, but naively compute the whole thing here
366c8565611SJeremy L Thompson     for (CeedInt j = 0; j < 3; j++) {
367c8565611SJeremy L Thompson       for (CeedInt k = 0; k < 3; k++) {
368c8565611SJeremy L Thompson         Cinv_dE_Cinv[j][k] = 0;
369c8565611SJeremy L Thompson         for (CeedInt m = 0; m < 3; m++) Cinv_dE_Cinv[j][k] += C_inv[j][m] * dE_Cinv[m][k];
370c8565611SJeremy L Thompson       }
371c8565611SJeremy L Thompson     }
372c8565611SJeremy L Thompson 
373c8565611SJeremy L Thompson     // Compute dS = (mu_2)*((2*I_3:dE)*I_3 - dE) + 2*d*Cinv_dE_Cinv + lambda*Cinv_contract_dE*Cinvwork - 2*lambda*logJ*Cinv_dE_Cinv;
374c8565611SJeremy L Thompson     // (2*I_3:dE)*I_3 - dE = 2*trace(dE)*I_3 - dE = 2trace(dE) - dE on the diagonal
375c8565611SJeremy L Thompson     // (2*I_3:dE)*I_3 - dE = -dE elsewhere
376c8565611SJeremy L Thompson     // CeedScalar J = Jm1 + 1;
377c8565611SJeremy L Thompson     CeedScalar tr_dE = dE[0][0] + dE[1][1] + dE[2][2];
378c8565611SJeremy L Thompson     CeedScalar dSwork[6];
379c8565611SJeremy L Thompson     for (CeedInt i = 0; i < 6; i++) {
380c8565611SJeremy L Thompson       dSwork[i] = lambda * Cinv_contract_dE * Cinvwork[i] + 2 * (mu_1 + 2 * mu_2 - lambda * logJ) * Cinv_dE_Cinv[indj[i]][indk[i]] +
381c8565611SJeremy L Thompson                   2 * mu_2 * (tr_dE * (i < 3) - dEwork[i]);
382c8565611SJeremy L Thompson     }
383c8565611SJeremy L Thompson 
384c8565611SJeremy L Thompson     CeedScalar dS[3][3] = {
385c8565611SJeremy L Thompson         {dSwork[0], dSwork[5], dSwork[4]},
386c8565611SJeremy L Thompson         {dSwork[5], dSwork[1], dSwork[3]},
387c8565611SJeremy L Thompson         {dSwork[4], dSwork[3], dSwork[2]}
388c8565611SJeremy L Thompson     };
389c8565611SJeremy L Thompson     // Second Piola-Kirchhoff (S)
390c8565611SJeremy L Thompson     const CeedScalar S[3][3] = {
391c8565611SJeremy L Thompson         {Swork[0], Swork[5], Swork[4]},
392c8565611SJeremy L Thompson         {Swork[5], Swork[1], Swork[3]},
393c8565611SJeremy L Thompson         {Swork[4], Swork[3], Swork[2]}
394c8565611SJeremy L Thompson     };
395c8565611SJeremy L Thompson     // dP = dPdF:dF = dF*S + F*dS
396c8565611SJeremy L Thompson     CeedScalar dP[3][3];
397c8565611SJeremy L Thompson     for (CeedInt j = 0; j < 3; j++) {
398c8565611SJeremy L Thompson       for (CeedInt k = 0; k < 3; k++) {
399c8565611SJeremy L Thompson         dP[j][k] = 0;
400c8565611SJeremy L Thompson         for (CeedInt m = 0; m < 3; m++) dP[j][k] += graddeltau[j][m] * S[m][k] + F[j][m] * dS[m][k];
401c8565611SJeremy L Thompson       }
402c8565611SJeremy L Thompson     }
403c8565611SJeremy L Thompson 
404c8565611SJeremy L Thompson     // Apply dXdx^T and weight
405c8565611SJeremy L Thompson     for (CeedInt j = 0; j < 3; j++) {    // Component
406c8565611SJeremy L Thompson       for (CeedInt k = 0; k < 3; k++) {  // Derivative
407c8565611SJeremy L Thompson         deltadvdX[k][j][i] = 0;
408c8565611SJeremy L Thompson         for (CeedInt m = 0; m < 3; m++) deltadvdX[k][j][i] += dXdx[k][m] * dP[j][m] * wdetJ;
409c8565611SJeremy L Thompson       }
410c8565611SJeremy L Thompson     }
411c8565611SJeremy L Thompson   }  // End of Quadrature Point Loop
412c8565611SJeremy L Thompson 
413c8565611SJeremy L Thompson   return CEED_ERROR_SUCCESS;
414c8565611SJeremy L Thompson }
415c8565611SJeremy L Thompson 
416c8565611SJeremy L Thompson // -----------------------------------------------------------------------------
417c8565611SJeremy L Thompson // Strain energy computation for hyperelasticity, finite strain
418c8565611SJeremy L Thompson // -----------------------------------------------------------------------------
ElasFSEnergy_MR(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)419c8565611SJeremy L Thompson CEED_QFUNCTION(ElasFSEnergy_MR)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
420c8565611SJeremy L Thompson   // Inputs
421c8565611SJeremy L Thompson   const CeedScalar(*ug)[3][CEED_Q_VLA] = (const CeedScalar(*)[3][CEED_Q_VLA])in[0], (*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[1];
422c8565611SJeremy L Thompson 
423c8565611SJeremy L Thompson   // Outputs
424c8565611SJeremy L Thompson   CeedScalar(*energy) = (CeedScalar(*))out[0];
425c8565611SJeremy L Thompson 
426c8565611SJeremy L Thompson   // Context
427c8565611SJeremy L Thompson   const Physics_MR context = (Physics_MR)ctx;
428c8565611SJeremy L Thompson   const CeedScalar mu_1    = context->mu_1;
429c8565611SJeremy L Thompson   const CeedScalar mu_2    = context->mu_2;
430c8565611SJeremy L Thompson   const CeedScalar lambda  = context->lambda;
431c8565611SJeremy L Thompson 
432c8565611SJeremy L Thompson   // Quadrature Point Loop
433c8565611SJeremy L Thompson   CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) {
434c8565611SJeremy L Thompson     // Read spatial derivatives of u
435c8565611SJeremy L Thompson     const CeedScalar du[3][3] = {
436c8565611SJeremy L Thompson         {ug[0][0][i], ug[1][0][i], ug[2][0][i]},
437c8565611SJeremy L Thompson         {ug[0][1][i], ug[1][1][i], ug[2][1][i]},
438c8565611SJeremy L Thompson         {ug[0][2][i], ug[1][2][i], ug[2][2][i]}
439c8565611SJeremy L Thompson     };
440c8565611SJeremy L Thompson     // -- Qdata
441c8565611SJeremy L Thompson     const CeedScalar wdetJ      = q_data[0][i];
442c8565611SJeremy L Thompson     const CeedScalar dXdx[3][3] = {
443c8565611SJeremy L Thompson         {q_data[1][i], q_data[2][i], q_data[3][i]},
444c8565611SJeremy L Thompson         {q_data[4][i], q_data[5][i], q_data[6][i]},
445c8565611SJeremy L Thompson         {q_data[7][i], q_data[8][i], q_data[9][i]}
446c8565611SJeremy L Thompson     };
447c8565611SJeremy L Thompson     // Compute grad_u
448c8565611SJeremy L Thompson     //   dXdx = (dx/dX)^(-1)
449c8565611SJeremy L Thompson     // Apply dXdx to du = grad_u
450c8565611SJeremy L Thompson     CeedScalar grad_u[3][3];
451c8565611SJeremy L Thompson     for (int j = 0; j < 3; j++) {    // Component
452c8565611SJeremy L Thompson       for (int k = 0; k < 3; k++) {  // Derivative
453c8565611SJeremy L Thompson         grad_u[j][k] = 0;
454c8565611SJeremy L Thompson         for (int m = 0; m < 3; m++) grad_u[j][k] += dXdx[m][k] * du[j][m];
455c8565611SJeremy L Thompson       }
456c8565611SJeremy L Thompson     }
457c8565611SJeremy L Thompson 
458c8565611SJeremy L Thompson     // E - Green-Lagrange strain tensor
459c8565611SJeremy L Thompson     // E = 1/2 (grad_u + grad_u^T + grad_u^T*grad_u)
460c8565611SJeremy L Thompson     const CeedInt indj[6] = {0, 1, 2, 1, 0, 0}, indk[6] = {0, 1, 2, 2, 2, 1};
461c8565611SJeremy L Thompson     CeedScalar    E2work[6];
462c8565611SJeremy L Thompson     for (CeedInt m = 0; m < 6; m++) {
463c8565611SJeremy L Thompson       E2work[m] = grad_u[indj[m]][indk[m]] + grad_u[indk[m]][indj[m]];
464c8565611SJeremy L Thompson       for (CeedInt n = 0; n < 3; n++) E2work[m] += grad_u[n][indj[m]] * grad_u[n][indk[m]];
465c8565611SJeremy L Thompson     }
466c8565611SJeremy L Thompson     CeedScalar E2[3][3] = {
467c8565611SJeremy L Thompson         {E2work[0], E2work[5], E2work[4]},
468c8565611SJeremy L Thompson         {E2work[5], E2work[1], E2work[3]},
469c8565611SJeremy L Thompson         {E2work[4], E2work[3], E2work[2]}
470c8565611SJeremy L Thompson     };
471c8565611SJeremy L Thompson 
472c8565611SJeremy L Thompson     // C : right Cauchy-Green tensor
473c8565611SJeremy L Thompson     // C = I + 2E
474c8565611SJeremy L Thompson     const CeedScalar C[3][3] = {
475c8565611SJeremy L Thompson         {1 + E2[0][0], E2[0][1],     E2[0][2]    },
476c8565611SJeremy L Thompson         {E2[0][1],     1 + E2[1][1], E2[1][2]    },
477c8565611SJeremy L Thompson         {E2[0][2],     E2[1][2],     1 + E2[2][2]}
478c8565611SJeremy L Thompson     };
479c8565611SJeremy L Thompson     // Compute CC = C*C = C^2
480c8565611SJeremy L Thompson     CeedScalar CC[3][3];
481c8565611SJeremy L Thompson     for (CeedInt j = 0; j < 3; j++) {
482c8565611SJeremy L Thompson       for (CeedInt k = 0; k < 3; k++) {
483c8565611SJeremy L Thompson         CC[j][k] = 0;
484c8565611SJeremy L Thompson         for (CeedInt m = 0; m < 3; m++) CC[j][k] += C[j][m] * C[m][k];
485c8565611SJeremy L Thompson       }
486c8565611SJeremy L Thompson     }
487c8565611SJeremy L Thompson 
488c8565611SJeremy L Thompson     const CeedScalar Jm1 = computeJM1(grad_u);
489c8565611SJeremy L Thompson     // CeedScalar J = Jm1 + 1;
490c8565611SJeremy L Thompson     // Compute invariants
491c8565611SJeremy L Thompson     // I_1 = trace(C)
492c8565611SJeremy L Thompson     const CeedScalar I_1 = C[0][0] + C[1][1] + C[2][2];
493c8565611SJeremy L Thompson     // Trace(C^2)
494c8565611SJeremy L Thompson     const CeedScalar tr_CC = CC[0][0] + CC[1][1] + CC[2][2];
495c8565611SJeremy L Thompson     // I_2 = 0.5(I_1^2 - trace(C^2))
496c8565611SJeremy L Thompson     const CeedScalar I_2 = 0.5 * (I_1 * I_1 - tr_CC);
497c8565611SJeremy L Thompson 
498c8565611SJeremy L Thompson     const CeedScalar logJ = log1p_series_shifted(Jm1);
499c8565611SJeremy L Thompson     // Strain energy Phi(E) for Mooney-Rivlin
500c8565611SJeremy L Thompson     energy[i] = (0.5 * lambda * (logJ) * (logJ) - (mu_1 + 2 * mu_2) * logJ + (mu_1 / 2.) * (I_1 - 3) + (mu_2 / 2.) * (I_2 - 3)) * wdetJ;
501c8565611SJeremy L Thompson 
502c8565611SJeremy L Thompson   }  // End of Quadrature Point Loop
503c8565611SJeremy L Thompson 
504c8565611SJeremy L Thompson   return CEED_ERROR_SUCCESS;
505c8565611SJeremy L Thompson }
506c8565611SJeremy L Thompson 
507c8565611SJeremy L Thompson // -----------------------------------------------------------------------------
508c8565611SJeremy L Thompson // Nodal diagnostic quantities for hyperelasticity, finite strain
509c8565611SJeremy L Thompson // -----------------------------------------------------------------------------
ElasFSDiagnostic_MR(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)510c8565611SJeremy L Thompson CEED_QFUNCTION(ElasFSDiagnostic_MR)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
511c8565611SJeremy L Thompson   // Inputs
512c8565611SJeremy L Thompson   const CeedScalar(*u)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], (*ug)[3][CEED_Q_VLA] = (const CeedScalar(*)[3][CEED_Q_VLA])in[1],
513c8565611SJeremy L Thompson         (*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2];
514c8565611SJeremy L Thompson 
515c8565611SJeremy L Thompson   // Outputs
516c8565611SJeremy L Thompson   CeedScalar(*diagnostic)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0];
517c8565611SJeremy L Thompson 
518c8565611SJeremy L Thompson   // Context
519c8565611SJeremy L Thompson   const Physics_MR context = (Physics_MR)ctx;
520c8565611SJeremy L Thompson   const CeedScalar mu_1    = context->mu_1;
521c8565611SJeremy L Thompson   const CeedScalar mu_2    = context->mu_2;
522c8565611SJeremy L Thompson   const CeedScalar lambda  = context->lambda;
523c8565611SJeremy L Thompson 
524c8565611SJeremy L Thompson   // Quadrature Point Loop
525c8565611SJeremy L Thompson   CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) {
526c8565611SJeremy L Thompson     // Read spatial derivatives of u
527c8565611SJeremy L Thompson     const CeedScalar du[3][3] = {
528c8565611SJeremy L Thompson         {ug[0][0][i], ug[1][0][i], ug[2][0][i]},
529c8565611SJeremy L Thompson         {ug[0][1][i], ug[1][1][i], ug[2][1][i]},
530c8565611SJeremy L Thompson         {ug[0][2][i], ug[1][2][i], ug[2][2][i]}
531c8565611SJeremy L Thompson     };
532c8565611SJeremy L Thompson     // -- Qdata
533c8565611SJeremy L Thompson     const CeedScalar dXdx[3][3] = {
534c8565611SJeremy L Thompson         {q_data[1][i], q_data[2][i], q_data[3][i]},
535c8565611SJeremy L Thompson         {q_data[4][i], q_data[5][i], q_data[6][i]},
536c8565611SJeremy L Thompson         {q_data[7][i], q_data[8][i], q_data[9][i]}
537c8565611SJeremy L Thompson     };
538c8565611SJeremy L Thompson 
539c8565611SJeremy L Thompson     // Compute grad_u
540c8565611SJeremy L Thompson     //   dXdx = (dx/dX)^(-1)
541c8565611SJeremy L Thompson     // Apply dXdx to du = grad_u
542c8565611SJeremy L Thompson     CeedScalar grad_u[3][3];
543c8565611SJeremy L Thompson     for (int j = 0; j < 3; j++) {    // Component
544c8565611SJeremy L Thompson       for (int k = 0; k < 3; k++) {  // Derivative
545c8565611SJeremy L Thompson         grad_u[j][k] = 0;
546c8565611SJeremy L Thompson         for (int m = 0; m < 3; m++) grad_u[j][k] += dXdx[m][k] * du[j][m];
547c8565611SJeremy L Thompson       }
548c8565611SJeremy L Thompson     }
549c8565611SJeremy L Thompson 
550c8565611SJeremy L Thompson     // E - Green-Lagrange strain tensor
551c8565611SJeremy L Thompson     //     E = 1/2 (grad_u + grad_u^T + grad_u^T*grad_u)
552c8565611SJeremy L Thompson     const CeedInt indj[6] = {0, 1, 2, 1, 0, 0}, indk[6] = {0, 1, 2, 2, 2, 1};
553c8565611SJeremy L Thompson     CeedScalar    E2work[6];
554c8565611SJeremy L Thompson     for (CeedInt m = 0; m < 6; m++) {
555c8565611SJeremy L Thompson       E2work[m] = grad_u[indj[m]][indk[m]] + grad_u[indk[m]][indj[m]];
556c8565611SJeremy L Thompson       for (CeedInt n = 0; n < 3; n++) E2work[m] += grad_u[n][indj[m]] * grad_u[n][indk[m]];
557c8565611SJeremy L Thompson     }
558c8565611SJeremy L Thompson     CeedScalar E2[3][3] = {
559c8565611SJeremy L Thompson         {E2work[0], E2work[5], E2work[4]},
560c8565611SJeremy L Thompson         {E2work[5], E2work[1], E2work[3]},
561c8565611SJeremy L Thompson         {E2work[4], E2work[3], E2work[2]}
562c8565611SJeremy L Thompson     };
563c8565611SJeremy L Thompson 
564c8565611SJeremy L Thompson     // Displacement
565c8565611SJeremy L Thompson     diagnostic[0][i] = u[0][i];
566c8565611SJeremy L Thompson     diagnostic[1][i] = u[1][i];
567c8565611SJeremy L Thompson     diagnostic[2][i] = u[2][i];
568c8565611SJeremy L Thompson 
569c8565611SJeremy L Thompson     // Pressure
570c8565611SJeremy L Thompson     const CeedScalar Jm1  = computeJM1(grad_u);
571c8565611SJeremy L Thompson     const CeedScalar logJ = log1p_series_shifted(Jm1);
572c8565611SJeremy L Thompson     diagnostic[3][i]      = -lambda * logJ;
573c8565611SJeremy L Thompson 
574c8565611SJeremy L Thompson     // Stress tensor invariants
575c8565611SJeremy L Thompson     diagnostic[4][i] = (E2[0][0] + E2[1][1] + E2[2][2]) / 2.;
576c8565611SJeremy L Thompson     diagnostic[5][i] = 0.;
577c8565611SJeremy L Thompson     for (CeedInt j = 0; j < 3; j++) {
578c8565611SJeremy L Thompson       for (CeedInt m = 0; m < 3; m++) diagnostic[5][i] += E2[j][m] * E2[m][j] / 4.;
579c8565611SJeremy L Thompson     }
580c8565611SJeremy L Thompson     diagnostic[6][i] = Jm1 + 1;
581c8565611SJeremy L Thompson 
582c8565611SJeremy L Thompson     // C : right Cauchy-Green tensor
583c8565611SJeremy L Thompson     // C = I + 2E
584c8565611SJeremy L Thompson     const CeedScalar C[3][3] = {
585c8565611SJeremy L Thompson         {1 + E2[0][0], E2[0][1],     E2[0][2]    },
586c8565611SJeremy L Thompson         {E2[0][1],     1 + E2[1][1], E2[1][2]    },
587c8565611SJeremy L Thompson         {E2[0][2],     E2[1][2],     1 + E2[2][2]}
588c8565611SJeremy L Thompson     };
589c8565611SJeremy L Thompson     // Compute CC = C*C = C^2
590c8565611SJeremy L Thompson     CeedScalar CC[3][3];
591c8565611SJeremy L Thompson     for (CeedInt j = 0; j < 3; j++) {
592c8565611SJeremy L Thompson       for (CeedInt k = 0; k < 3; k++) {
593c8565611SJeremy L Thompson         CC[j][k] = 0;
594c8565611SJeremy L Thompson         for (CeedInt m = 0; m < 3; m++) CC[j][k] += C[j][m] * C[m][k];
595c8565611SJeremy L Thompson       }
596c8565611SJeremy L Thompson     }
597c8565611SJeremy L Thompson 
598c8565611SJeremy L Thompson     // CeedScalar J = Jm1 + 1;
599c8565611SJeremy L Thompson     // Compute invariants
600c8565611SJeremy L Thompson     // I_1 = trace(C)
601c8565611SJeremy L Thompson     const CeedScalar I_1 = C[0][0] + C[1][1] + C[2][2];
602c8565611SJeremy L Thompson     // Trace(C^2)
603c8565611SJeremy L Thompson     const CeedScalar tr_CC = CC[0][0] + CC[1][1] + CC[2][2];
604c8565611SJeremy L Thompson     // I_2 = 0.5(I_1^2 - trace(C^2))
605c8565611SJeremy L Thompson     const CeedScalar I_2 = 0.5 * (pow(I_1, 2) - tr_CC);
606c8565611SJeremy L Thompson 
607c8565611SJeremy L Thompson     // Strain energy
608c8565611SJeremy L Thompson     diagnostic[7][i] = (0.5 * lambda * logJ * logJ - (mu_1 + 2 * mu_2) * logJ + (mu_1 / 2.) * (I_1 - 3) + (mu_2 / 2.) * (I_2 - 3));
609c8565611SJeremy L Thompson   }  // End of Quadrature Point Loop
610c8565611SJeremy L Thompson 
611c8565611SJeremy L Thompson   return CEED_ERROR_SUCCESS;
612c8565611SJeremy L Thompson }
613c8565611SJeremy L Thompson // -----------------------------------------------------------------------------
614