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