1c8565611SJeremy L Thompson // Copyright (c) 2017-2024, 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 11*c0b5abf0SJeremy L Thompson #include <ceed/types.h> 12*c0b5abf0SJeremy L Thompson #ifndef CEED_RUNNING_JIT_PASS 13c8565611SJeremy L Thompson #include <math.h> 14*c0b5abf0SJeremy 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 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 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 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 // ----------------------------------------------------------------------------- 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 // ----------------------------------------------------------------------------- 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 // ----------------------------------------------------------------------------- 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 // ----------------------------------------------------------------------------- 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 // ----------------------------------------------------------------------------- 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