1*88b783a1SJames Wright // Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at 2*88b783a1SJames Wright // the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights 3*88b783a1SJames Wright // reserved. See files LICENSE and NOTICE for details. 4*88b783a1SJames Wright // 5*88b783a1SJames Wright // This file is part of CEED, a collection of benchmarks, miniapps, software 6*88b783a1SJames Wright // libraries and APIs for efficient high-order finite element and spectral 7*88b783a1SJames Wright // element discretizations for exascale applications. For more information and 8*88b783a1SJames Wright // source code availability see http://github.com/ceed. 9*88b783a1SJames Wright // 10*88b783a1SJames Wright // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC, 11*88b783a1SJames Wright // a collaborative effort of two U.S. Department of Energy organizations (Office 12*88b783a1SJames Wright // of Science and the National Nuclear Security Administration) responsible for 13*88b783a1SJames Wright // the planning and preparation of a capable exascale ecosystem, including 14*88b783a1SJames Wright // software, applications, hardware, advanced system engineering and early 15*88b783a1SJames Wright // testbed platforms, in support of the nation's exascale computing imperative. 16*88b783a1SJames Wright 17*88b783a1SJames Wright /// @file 18*88b783a1SJames Wright /// Operator for Navier-Stokes example using PETSc 19*88b783a1SJames Wright 20*88b783a1SJames Wright 21*88b783a1SJames Wright #ifndef newtonian_h 22*88b783a1SJames Wright #define newtonian_h 23*88b783a1SJames Wright 24*88b783a1SJames Wright #include <math.h> 25*88b783a1SJames Wright #include <ceed.h> 26*88b783a1SJames Wright 27*88b783a1SJames Wright #ifndef M_PI 28*88b783a1SJames Wright #define M_PI 3.14159265358979323846 29*88b783a1SJames Wright #endif 30*88b783a1SJames Wright 31*88b783a1SJames Wright #ifndef setup_context_struct 32*88b783a1SJames Wright #define setup_context_struct 33*88b783a1SJames Wright typedef struct SetupContext_ *SetupContext; 34*88b783a1SJames Wright struct SetupContext_ { 35*88b783a1SJames Wright CeedScalar theta0; 36*88b783a1SJames Wright CeedScalar thetaC; 37*88b783a1SJames Wright CeedScalar P0; 38*88b783a1SJames Wright CeedScalar N; 39*88b783a1SJames Wright CeedScalar cv; 40*88b783a1SJames Wright CeedScalar cp; 41*88b783a1SJames Wright CeedScalar g; 42*88b783a1SJames Wright CeedScalar rc; 43*88b783a1SJames Wright CeedScalar lx; 44*88b783a1SJames Wright CeedScalar ly; 45*88b783a1SJames Wright CeedScalar lz; 46*88b783a1SJames Wright CeedScalar center[3]; 47*88b783a1SJames Wright CeedScalar dc_axis[3]; 48*88b783a1SJames Wright CeedScalar wind[3]; 49*88b783a1SJames Wright CeedScalar time; 50*88b783a1SJames Wright int wind_type; // See WindType: 0=ROTATION, 1=TRANSLATION 51*88b783a1SJames Wright int bubble_type; // See BubbleType: 0=SPHERE, 1=CYLINDER 52*88b783a1SJames Wright int bubble_continuity_type; // See BubbleContinuityType: 0=SMOOTH, 1=BACK_SHARP 2=THICK 53*88b783a1SJames Wright }; 54*88b783a1SJames Wright #endif 55*88b783a1SJames Wright 56*88b783a1SJames Wright #ifndef newtonian_context_struct 57*88b783a1SJames Wright #define newtonian_context_struct 58*88b783a1SJames Wright typedef enum { 59*88b783a1SJames Wright STAB_NONE = 0, 60*88b783a1SJames Wright STAB_SU = 1, // Streamline Upwind 61*88b783a1SJames Wright STAB_SUPG = 2, // Streamline Upwind Petrov-Galerkin 62*88b783a1SJames Wright } StabilizationType; 63*88b783a1SJames Wright 64*88b783a1SJames Wright typedef struct NewtonianIdealGasContext_ *NewtonianIdealGasContext; 65*88b783a1SJames Wright struct NewtonianIdealGasContext_ { 66*88b783a1SJames Wright CeedScalar lambda; 67*88b783a1SJames Wright CeedScalar mu; 68*88b783a1SJames Wright CeedScalar k; 69*88b783a1SJames Wright CeedScalar cv; 70*88b783a1SJames Wright CeedScalar cp; 71*88b783a1SJames Wright CeedScalar g; 72*88b783a1SJames Wright CeedScalar c_tau; 73*88b783a1SJames Wright StabilizationType stabilization; 74*88b783a1SJames Wright }; 75*88b783a1SJames Wright #endif 76*88b783a1SJames Wright 77*88b783a1SJames Wright // ***************************************************************************** 78*88b783a1SJames Wright // Helper function for computing flux Jacobian 79*88b783a1SJames Wright // ***************************************************************************** 80*88b783a1SJames Wright CEED_QFUNCTION_HELPER void computeFluxJacobian_NS(CeedScalar dF[3][5][5], 81*88b783a1SJames Wright const CeedScalar rho, const CeedScalar u[3], const CeedScalar E, 82*88b783a1SJames Wright const CeedScalar gamma, const CeedScalar g, CeedScalar z) { 83*88b783a1SJames Wright CeedScalar u_sq = u[0]*u[0] + u[1]*u[1] + u[2]*u[2]; // Velocity square 84*88b783a1SJames Wright for (CeedInt i=0; i<3; i++) { // Jacobian matrices for 3 directions 85*88b783a1SJames Wright for (CeedInt j=0; j<3; j++) { // Rows of each Jacobian matrix 86*88b783a1SJames Wright dF[i][j+1][0] = ((i==j) ? ((gamma-1.)*(u_sq/2. - g*z)) : 0.) - u[i]*u[j]; 87*88b783a1SJames Wright for (CeedInt k=0; k<3; k++) { // Columns of each Jacobian matrix 88*88b783a1SJames Wright dF[i][0][k+1] = ((i==k) ? 1. : 0.); 89*88b783a1SJames Wright dF[i][j+1][k+1] = ((j==k) ? u[i] : 0.) + 90*88b783a1SJames Wright ((i==k) ? u[j] : 0.) - 91*88b783a1SJames Wright ((i==j) ? u[k] : 0.) * (gamma-1.); 92*88b783a1SJames Wright dF[i][4][k+1] = ((i==k) ? (E*gamma/rho - (gamma-1.)*u_sq/2.) : 0.) - 93*88b783a1SJames Wright (gamma-1.)*u[i]*u[k]; 94*88b783a1SJames Wright } 95*88b783a1SJames Wright dF[i][j+1][4] = ((i==j) ? (gamma-1.) : 0.); 96*88b783a1SJames Wright } 97*88b783a1SJames Wright dF[i][4][0] = u[i] * ((gamma-1.)*u_sq - E*gamma/rho); 98*88b783a1SJames Wright dF[i][4][4] = u[i] * gamma; 99*88b783a1SJames Wright } 100*88b783a1SJames Wright } 101*88b783a1SJames Wright 102*88b783a1SJames Wright // ***************************************************************************** 103*88b783a1SJames Wright // Helper function for computing Tau elements (stabilization constant) 104*88b783a1SJames Wright // Model from: 105*88b783a1SJames Wright // Stabilized Methods for Compressible Flows, Hughes et al 2010 106*88b783a1SJames Wright // 107*88b783a1SJames Wright // Spatial criterion #2 - Tau is a 3x3 diagonal matrix 108*88b783a1SJames Wright // Tau[i] = c_tau h[i] Xi(Pe) / rho(A[i]) (no sum) 109*88b783a1SJames Wright // 110*88b783a1SJames Wright // Where 111*88b783a1SJames Wright // c_tau = stabilization constant (0.5 is reported as "optimal") 112*88b783a1SJames Wright // h[i] = 2 length(dxdX[i]) 113*88b783a1SJames Wright // Pe = Peclet number ( Pe = sqrt(u u) / dot(dXdx,u) diffusivity ) 114*88b783a1SJames Wright // Xi(Pe) = coth Pe - 1. / Pe (1. at large local Peclet number ) 115*88b783a1SJames Wright // rho(A[i]) = spectral radius of the convective flux Jacobian i, 116*88b783a1SJames Wright // wave speed in direction i 117*88b783a1SJames Wright // ***************************************************************************** 118*88b783a1SJames Wright CEED_QFUNCTION_HELPER void Tau_spatial(CeedScalar Tau_x[3], 119*88b783a1SJames Wright const CeedScalar dXdx[3][3], const CeedScalar u[3], 120*88b783a1SJames Wright const CeedScalar sound_speed, const CeedScalar c_tau) { 121*88b783a1SJames Wright for (int i=0; i<3; i++) { 122*88b783a1SJames Wright // length of element in direction i 123*88b783a1SJames Wright CeedScalar h = 2 / sqrt(dXdx[0][i]*dXdx[0][i] + dXdx[1][i]*dXdx[1][i] + 124*88b783a1SJames Wright dXdx[2][i]*dXdx[2][i]); 125*88b783a1SJames Wright // fastest wave in direction i 126*88b783a1SJames Wright CeedScalar fastest_wave = fabs(u[i]) + sound_speed; 127*88b783a1SJames Wright Tau_x[i] = c_tau * h / fastest_wave; 128*88b783a1SJames Wright } 129*88b783a1SJames Wright } 130*88b783a1SJames Wright 131*88b783a1SJames Wright // ***************************************************************************** 132*88b783a1SJames Wright // This QFunction sets a "still" initial condition for generic Newtonian IG problems 133*88b783a1SJames Wright // ***************************************************************************** 134*88b783a1SJames Wright CEED_QFUNCTION(ICsNewtonianIG)(void *ctx, CeedInt Q, 135*88b783a1SJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 136*88b783a1SJames Wright // Inputs 137*88b783a1SJames Wright const CeedScalar (*X)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 138*88b783a1SJames Wright 139*88b783a1SJames Wright // Outputs 140*88b783a1SJames Wright CeedScalar (*q0)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 141*88b783a1SJames Wright 142*88b783a1SJames Wright // Quadrature Point Loop 143*88b783a1SJames Wright CeedPragmaSIMD 144*88b783a1SJames Wright for (CeedInt i=0; i<Q; i++) { 145*88b783a1SJames Wright CeedScalar q[5] = {0.}; 146*88b783a1SJames Wright 147*88b783a1SJames Wright // Context 148*88b783a1SJames Wright const SetupContext context = (SetupContext)ctx; 149*88b783a1SJames Wright const CeedScalar theta0 = context->theta0; 150*88b783a1SJames Wright const CeedScalar P0 = context->P0; 151*88b783a1SJames Wright const CeedScalar N = context->N; 152*88b783a1SJames Wright const CeedScalar cv = context->cv; 153*88b783a1SJames Wright const CeedScalar cp = context->cp; 154*88b783a1SJames Wright const CeedScalar g = context->g; 155*88b783a1SJames Wright const CeedScalar Rd = cp - cv; 156*88b783a1SJames Wright 157*88b783a1SJames Wright // Setup 158*88b783a1SJames Wright // -- Coordinates 159*88b783a1SJames Wright const CeedScalar z = X[2][i]; 160*88b783a1SJames Wright 161*88b783a1SJames Wright // -- Exner pressure, hydrostatic balance 162*88b783a1SJames Wright const CeedScalar Pi = 1. + g*g*(exp(-N*N*z/g) - 1.) / (cp*theta0*N*N); 163*88b783a1SJames Wright 164*88b783a1SJames Wright // -- Density 165*88b783a1SJames Wright const CeedScalar rho = P0 * pow(Pi, cv/Rd) / (Rd*theta0); 166*88b783a1SJames Wright 167*88b783a1SJames Wright // Initial Conditions 168*88b783a1SJames Wright q[0] = rho; 169*88b783a1SJames Wright q[1] = 0.0; 170*88b783a1SJames Wright q[2] = 0.0; 171*88b783a1SJames Wright q[3] = 0.0; 172*88b783a1SJames Wright q[4] = rho * (cv*theta0*Pi + g*z); 173*88b783a1SJames Wright 174*88b783a1SJames Wright for (CeedInt j=0; j<5; j++) 175*88b783a1SJames Wright q0[j][i] = q[j]; 176*88b783a1SJames Wright } // End of Quadrature Point Loop 177*88b783a1SJames Wright return 0; 178*88b783a1SJames Wright } 179*88b783a1SJames Wright 180*88b783a1SJames Wright // ***************************************************************************** 181*88b783a1SJames Wright // This QFunction implements the following formulation of Navier-Stokes with 182*88b783a1SJames Wright // explicit time stepping method 183*88b783a1SJames Wright // 184*88b783a1SJames Wright // This is 3D compressible Navier-Stokes in conservation form with state 185*88b783a1SJames Wright // variables of density, momentum density, and total energy density. 186*88b783a1SJames Wright // 187*88b783a1SJames Wright // State Variables: q = ( rho, U1, U2, U3, E ) 188*88b783a1SJames Wright // rho - Mass Density 189*88b783a1SJames Wright // Ui - Momentum Density, Ui = rho ui 190*88b783a1SJames Wright // E - Total Energy Density, E = rho (cv T + (u u)/2 + g z) 191*88b783a1SJames Wright // 192*88b783a1SJames Wright // Navier-Stokes Equations: 193*88b783a1SJames Wright // drho/dt + div( U ) = 0 194*88b783a1SJames Wright // dU/dt + div( rho (u x u) + P I3 ) + rho g khat = div( Fu ) 195*88b783a1SJames Wright // dE/dt + div( (E + P) u ) = div( Fe ) 196*88b783a1SJames Wright // 197*88b783a1SJames Wright // Viscous Stress: 198*88b783a1SJames Wright // Fu = mu (grad( u ) + grad( u )^T + lambda div ( u ) I3) 199*88b783a1SJames Wright // 200*88b783a1SJames Wright // Thermal Stress: 201*88b783a1SJames Wright // Fe = u Fu + k grad( T ) 202*88b783a1SJames Wright // 203*88b783a1SJames Wright // Equation of State: 204*88b783a1SJames Wright // P = (gamma - 1) (E - rho (u u) / 2 - rho g z) 205*88b783a1SJames Wright // 206*88b783a1SJames Wright // Stabilization: 207*88b783a1SJames Wright // Tau = diag(TauC, TauM, TauM, TauM, TauE) 208*88b783a1SJames Wright // f1 = rho sqrt(ui uj gij) 209*88b783a1SJames Wright // gij = dXi/dX * dXi/dX 210*88b783a1SJames Wright // TauC = Cc f1 / (8 gii) 211*88b783a1SJames Wright // TauM = min( 1 , 1 / f1 ) 212*88b783a1SJames Wright // TauE = TauM / (Ce cv) 213*88b783a1SJames Wright // 214*88b783a1SJames Wright // SU = Galerkin + grad(v) . ( Ai^T * Tau * (Aj q,j) ) 215*88b783a1SJames Wright // 216*88b783a1SJames Wright // Constants: 217*88b783a1SJames Wright // lambda = - 2 / 3, From Stokes hypothesis 218*88b783a1SJames Wright // mu , Dynamic viscosity 219*88b783a1SJames Wright // k , Thermal conductivity 220*88b783a1SJames Wright // cv , Specific heat, constant volume 221*88b783a1SJames Wright // cp , Specific heat, constant pressure 222*88b783a1SJames Wright // g , Gravity 223*88b783a1SJames Wright // gamma = cp / cv, Specific heat ratio 224*88b783a1SJames Wright // 225*88b783a1SJames Wright // We require the product of the inverse of the Jacobian (dXdx_j,k) and 226*88b783a1SJames Wright // its transpose (dXdx_k,j) to properly compute integrals of the form: 227*88b783a1SJames Wright // int( gradv gradu ) 228*88b783a1SJames Wright // 229*88b783a1SJames Wright // ***************************************************************************** 230*88b783a1SJames Wright CEED_QFUNCTION(Newtonian)(void *ctx, CeedInt Q, 231*88b783a1SJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 232*88b783a1SJames Wright // *INDENT-OFF* 233*88b783a1SJames Wright // Inputs 234*88b783a1SJames Wright const CeedScalar (*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 235*88b783a1SJames Wright (*dq)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 236*88b783a1SJames Wright (*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 237*88b783a1SJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; 238*88b783a1SJames Wright // Outputs 239*88b783a1SJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], 240*88b783a1SJames Wright (*dv)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 241*88b783a1SJames Wright // *INDENT-ON* 242*88b783a1SJames Wright 243*88b783a1SJames Wright // Context 244*88b783a1SJames Wright NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 245*88b783a1SJames Wright const CeedScalar lambda = context->lambda; 246*88b783a1SJames Wright const CeedScalar mu = context->mu; 247*88b783a1SJames Wright const CeedScalar k = context->k; 248*88b783a1SJames Wright const CeedScalar cv = context->cv; 249*88b783a1SJames Wright const CeedScalar cp = context->cp; 250*88b783a1SJames Wright const CeedScalar g = context->g; 251*88b783a1SJames Wright const CeedScalar c_tau = context->c_tau; 252*88b783a1SJames Wright const CeedScalar gamma = cp / cv; 253*88b783a1SJames Wright 254*88b783a1SJames Wright CeedPragmaSIMD 255*88b783a1SJames Wright // Quadrature Point Loop 256*88b783a1SJames Wright for (CeedInt i=0; i<Q; i++) { 257*88b783a1SJames Wright // *INDENT-OFF* 258*88b783a1SJames Wright // Setup 259*88b783a1SJames Wright // -- Interp in 260*88b783a1SJames Wright const CeedScalar rho = q[0][i]; 261*88b783a1SJames Wright const CeedScalar u[3] = {q[1][i] / rho, 262*88b783a1SJames Wright q[2][i] / rho, 263*88b783a1SJames Wright q[3][i] / rho 264*88b783a1SJames Wright }; 265*88b783a1SJames Wright const CeedScalar E = q[4][i]; 266*88b783a1SJames Wright // -- Grad in 267*88b783a1SJames Wright const CeedScalar drho[3] = {dq[0][0][i], 268*88b783a1SJames Wright dq[1][0][i], 269*88b783a1SJames Wright dq[2][0][i] 270*88b783a1SJames Wright }; 271*88b783a1SJames Wright const CeedScalar dU[3][3] = {{dq[0][1][i], 272*88b783a1SJames Wright dq[1][1][i], 273*88b783a1SJames Wright dq[2][1][i]}, 274*88b783a1SJames Wright {dq[0][2][i], 275*88b783a1SJames Wright dq[1][2][i], 276*88b783a1SJames Wright dq[2][2][i]}, 277*88b783a1SJames Wright {dq[0][3][i], 278*88b783a1SJames Wright dq[1][3][i], 279*88b783a1SJames Wright dq[2][3][i]} 280*88b783a1SJames Wright }; 281*88b783a1SJames Wright const CeedScalar dE[3] = {dq[0][4][i], 282*88b783a1SJames Wright dq[1][4][i], 283*88b783a1SJames Wright dq[2][4][i] 284*88b783a1SJames Wright }; 285*88b783a1SJames Wright // -- Interp-to-Interp q_data 286*88b783a1SJames Wright const CeedScalar wdetJ = q_data[0][i]; 287*88b783a1SJames Wright // -- Interp-to-Grad q_data 288*88b783a1SJames Wright // ---- Inverse of change of coordinate matrix: X_i,j 289*88b783a1SJames Wright // *INDENT-OFF* 290*88b783a1SJames Wright const CeedScalar dXdx[3][3] = {{q_data[1][i], 291*88b783a1SJames Wright q_data[2][i], 292*88b783a1SJames Wright q_data[3][i]}, 293*88b783a1SJames Wright {q_data[4][i], 294*88b783a1SJames Wright q_data[5][i], 295*88b783a1SJames Wright q_data[6][i]}, 296*88b783a1SJames Wright {q_data[7][i], 297*88b783a1SJames Wright q_data[8][i], 298*88b783a1SJames Wright q_data[9][i]} 299*88b783a1SJames Wright }; 300*88b783a1SJames Wright // *INDENT-ON* 301*88b783a1SJames Wright // -- Grad-to-Grad q_data 302*88b783a1SJames Wright // dU/dx 303*88b783a1SJames Wright CeedScalar du[3][3] = {{0}}; 304*88b783a1SJames Wright CeedScalar drhodx[3] = {0}; 305*88b783a1SJames Wright CeedScalar dEdx[3] = {0}; 306*88b783a1SJames Wright CeedScalar dUdx[3][3] = {{0}}; 307*88b783a1SJames Wright CeedScalar dXdxdXdxT[3][3] = {{0}}; 308*88b783a1SJames Wright for (int j=0; j<3; j++) { 309*88b783a1SJames Wright for (int k=0; k<3; k++) { 310*88b783a1SJames Wright du[j][k] = (dU[j][k] - drho[k]*u[j]) / rho; 311*88b783a1SJames Wright drhodx[j] += drho[k] * dXdx[k][j]; 312*88b783a1SJames Wright dEdx[j] += dE[k] * dXdx[k][j]; 313*88b783a1SJames Wright for (int l=0; l<3; l++) { 314*88b783a1SJames Wright dUdx[j][k] += dU[j][l] * dXdx[l][k]; 315*88b783a1SJames Wright dXdxdXdxT[j][k] += dXdx[j][l]*dXdx[k][l]; //dXdx_j,k * dXdx_k,j 316*88b783a1SJames Wright } 317*88b783a1SJames Wright } 318*88b783a1SJames Wright } 319*88b783a1SJames Wright CeedScalar dudx[3][3] = {{0}}; 320*88b783a1SJames Wright for (int j=0; j<3; j++) 321*88b783a1SJames Wright for (int k=0; k<3; k++) 322*88b783a1SJames Wright for (int l=0; l<3; l++) 323*88b783a1SJames Wright dudx[j][k] += du[j][l] * dXdx[l][k]; 324*88b783a1SJames Wright // -- grad_T 325*88b783a1SJames Wright const CeedScalar grad_T[3] = {(dEdx[0]/rho - E*drhodx[0]/(rho*rho) - /* *NOPAD* */ 326*88b783a1SJames Wright (u[0]*dudx[0][0] + u[1]*dudx[1][0] + u[2]*dudx[2][0]))/cv, 327*88b783a1SJames Wright (dEdx[1]/rho - E*drhodx[1]/(rho*rho) - /* *NOPAD* */ 328*88b783a1SJames Wright (u[0]*dudx[0][1] + u[1]*dudx[1][1] + u[2]*dudx[2][1]))/cv, 329*88b783a1SJames Wright (dEdx[2]/rho - E*drhodx[2]/(rho*rho) - /* *NOPAD* */ 330*88b783a1SJames Wright (u[0]*dudx[0][2] + u[1]*dudx[1][2] + u[2]*dudx[2][2]) - g)/cv 331*88b783a1SJames Wright }; 332*88b783a1SJames Wright 333*88b783a1SJames Wright // -- Fuvisc 334*88b783a1SJames Wright // ---- Symmetric 3x3 matrix 335*88b783a1SJames Wright const CeedScalar Fu[6] = {mu*(dudx[0][0] * (2 + lambda) + /* *NOPAD* */ 336*88b783a1SJames Wright lambda * (dudx[1][1] + dudx[2][2])), 337*88b783a1SJames Wright mu*(dudx[0][1] + dudx[1][0]), /* *NOPAD* */ 338*88b783a1SJames Wright mu*(dudx[0][2] + dudx[2][0]), /* *NOPAD* */ 339*88b783a1SJames Wright mu*(dudx[1][1] * (2 + lambda) + /* *NOPAD* */ 340*88b783a1SJames Wright lambda * (dudx[0][0] + dudx[2][2])), 341*88b783a1SJames Wright mu*(dudx[1][2] + dudx[2][1]), /* *NOPAD* */ 342*88b783a1SJames Wright mu*(dudx[2][2] * (2 + lambda) + /* *NOPAD* */ 343*88b783a1SJames Wright lambda * (dudx[0][0] + dudx[1][1])) 344*88b783a1SJames Wright }; 345*88b783a1SJames Wright // -- Fevisc 346*88b783a1SJames Wright const CeedScalar Fe[3] = {u[0]*Fu[0] + u[1]*Fu[1] + u[2]*Fu[2] + /* *NOPAD* */ 347*88b783a1SJames Wright k*grad_T[0], /* *NOPAD* */ 348*88b783a1SJames Wright u[0]*Fu[1] + u[1]*Fu[3] + u[2]*Fu[4] + /* *NOPAD* */ 349*88b783a1SJames Wright k*grad_T[1], /* *NOPAD* */ 350*88b783a1SJames Wright u[0]*Fu[2] + u[1]*Fu[4] + u[2]*Fu[5] + /* *NOPAD* */ 351*88b783a1SJames Wright k*grad_T[2] /* *NOPAD* */ 352*88b783a1SJames Wright }; 353*88b783a1SJames Wright // Pressure 354*88b783a1SJames Wright const CeedScalar 355*88b783a1SJames Wright E_kinetic = 0.5 * rho * (u[0]*u[0] + u[1]*u[1] + u[2]*u[2]), 356*88b783a1SJames Wright E_potential = rho*g*x[2][i], 357*88b783a1SJames Wright E_internal = E - E_kinetic - E_potential, 358*88b783a1SJames Wright P = E_internal * (gamma - 1.); // P = pressure 359*88b783a1SJames Wright 360*88b783a1SJames Wright // jacob_F_conv[3][5][5] = dF(convective)/dq at each direction 361*88b783a1SJames Wright CeedScalar jacob_F_conv[3][5][5] = {{{0.}}}; 362*88b783a1SJames Wright computeFluxJacobian_NS(jacob_F_conv, rho, u, E, gamma, g, x[2][i]); 363*88b783a1SJames Wright 364*88b783a1SJames Wright // jacob_F_conv_T = jacob_F_conv^T 365*88b783a1SJames Wright CeedScalar jacob_F_conv_T[3][5][5]; 366*88b783a1SJames Wright for (int j=0; j<3; j++) 367*88b783a1SJames Wright for (int k=0; k<5; k++) 368*88b783a1SJames Wright for (int l=0; l<5; l++) 369*88b783a1SJames Wright jacob_F_conv_T[j][k][l] = jacob_F_conv[j][l][k]; 370*88b783a1SJames Wright 371*88b783a1SJames Wright // dqdx collects drhodx, dUdx and dEdx in one vector 372*88b783a1SJames Wright CeedScalar dqdx[5][3]; 373*88b783a1SJames Wright for (int j=0; j<3; j++) { 374*88b783a1SJames Wright dqdx[0][j] = drhodx[j]; 375*88b783a1SJames Wright dqdx[4][j] = dEdx[j]; 376*88b783a1SJames Wright for (int k=0; k<3; k++) 377*88b783a1SJames Wright dqdx[k+1][j] = dUdx[k][j]; 378*88b783a1SJames Wright } 379*88b783a1SJames Wright 380*88b783a1SJames Wright // strong_conv = dF/dq * dq/dx (Strong convection) 381*88b783a1SJames Wright CeedScalar strong_conv[5] = {0}; 382*88b783a1SJames Wright for (int j=0; j<3; j++) 383*88b783a1SJames Wright for (int k=0; k<5; k++) 384*88b783a1SJames Wright for (int l=0; l<5; l++) 385*88b783a1SJames Wright strong_conv[k] += jacob_F_conv[j][k][l] * dqdx[l][j]; 386*88b783a1SJames Wright 387*88b783a1SJames Wright // Body force 388*88b783a1SJames Wright const CeedScalar body_force[5] = {0, 0, 0, -rho*g, 0}; 389*88b783a1SJames Wright 390*88b783a1SJames Wright // The Physics 391*88b783a1SJames Wright // Zero dv so all future terms can safely sum into it 392*88b783a1SJames Wright for (int j=0; j<5; j++) 393*88b783a1SJames Wright for (int k=0; k<3; k++) 394*88b783a1SJames Wright dv[k][j][i] = 0; 395*88b783a1SJames Wright 396*88b783a1SJames Wright // -- Density 397*88b783a1SJames Wright // ---- u rho 398*88b783a1SJames Wright for (int j=0; j<3; j++) 399*88b783a1SJames Wright dv[j][0][i] += wdetJ*(rho*u[0]*dXdx[j][0] + rho*u[1]*dXdx[j][1] + 400*88b783a1SJames Wright rho*u[2]*dXdx[j][2]); 401*88b783a1SJames Wright // -- Momentum 402*88b783a1SJames Wright // ---- rho (u x u) + P I3 403*88b783a1SJames Wright for (int j=0; j<3; j++) 404*88b783a1SJames Wright for (int k=0; k<3; k++) 405*88b783a1SJames Wright dv[k][j+1][i] += wdetJ*((rho*u[j]*u[0] + (j==0?P:0))*dXdx[k][0] + 406*88b783a1SJames Wright (rho*u[j]*u[1] + (j==1?P:0))*dXdx[k][1] + 407*88b783a1SJames Wright (rho*u[j]*u[2] + (j==2?P:0))*dXdx[k][2]); 408*88b783a1SJames Wright // ---- Fuvisc 409*88b783a1SJames Wright const CeedInt Fuviscidx[3][3] = {{0, 1, 2}, {1, 3, 4}, {2, 4, 5}}; // symmetric matrix indices 410*88b783a1SJames Wright for (int j=0; j<3; j++) 411*88b783a1SJames Wright for (int k=0; k<3; k++) 412*88b783a1SJames Wright dv[k][j+1][i] -= wdetJ*(Fu[Fuviscidx[j][0]]*dXdx[k][0] + 413*88b783a1SJames Wright Fu[Fuviscidx[j][1]]*dXdx[k][1] + 414*88b783a1SJames Wright Fu[Fuviscidx[j][2]]*dXdx[k][2]); 415*88b783a1SJames Wright // -- Total Energy Density 416*88b783a1SJames Wright // ---- (E + P) u 417*88b783a1SJames Wright for (int j=0; j<3; j++) 418*88b783a1SJames Wright dv[j][4][i] += wdetJ * (E + P) * (u[0]*dXdx[j][0] + u[1]*dXdx[j][1] + 419*88b783a1SJames Wright u[2]*dXdx[j][2]); 420*88b783a1SJames Wright // ---- Fevisc 421*88b783a1SJames Wright for (int j=0; j<3; j++) 422*88b783a1SJames Wright dv[j][4][i] -= wdetJ * (Fe[0]*dXdx[j][0] + Fe[1]*dXdx[j][1] + 423*88b783a1SJames Wright Fe[2]*dXdx[j][2]); 424*88b783a1SJames Wright // Body Force 425*88b783a1SJames Wright for (int j=0; j<5; j++) 426*88b783a1SJames Wright v[j][i] = wdetJ * body_force[j]; 427*88b783a1SJames Wright 428*88b783a1SJames Wright // Stabilization 429*88b783a1SJames Wright // -- Tau elements 430*88b783a1SJames Wright const CeedScalar sound_speed = sqrt(gamma * P / rho); 431*88b783a1SJames Wright CeedScalar Tau_x[3] = {0.}; 432*88b783a1SJames Wright Tau_spatial(Tau_x, dXdx, u, sound_speed, c_tau); 433*88b783a1SJames Wright 434*88b783a1SJames Wright // -- Stabilization method: none or SU 435*88b783a1SJames Wright CeedScalar stab[5][3]; 436*88b783a1SJames Wright switch (context->stabilization) { 437*88b783a1SJames Wright case STAB_NONE: // Galerkin 438*88b783a1SJames Wright break; 439*88b783a1SJames Wright case STAB_SU: // SU 440*88b783a1SJames Wright for (int j=0; j<3; j++) 441*88b783a1SJames Wright for (int k=0; k<5; k++) 442*88b783a1SJames Wright for (int l=0; l<5; l++) 443*88b783a1SJames Wright stab[k][j] = jacob_F_conv_T[j][k][l] * Tau_x[j] * strong_conv[l]; 444*88b783a1SJames Wright 445*88b783a1SJames Wright for (int j=0; j<5; j++) 446*88b783a1SJames Wright for (int k=0; k<3; k++) 447*88b783a1SJames Wright dv[k][j][i] -= wdetJ*(stab[j][0] * dXdx[k][0] + 448*88b783a1SJames Wright stab[j][1] * dXdx[k][1] + 449*88b783a1SJames Wright stab[j][2] * dXdx[k][2]); 450*88b783a1SJames Wright break; 451*88b783a1SJames Wright case STAB_SUPG: // SUPG is not implemented for explicit scheme 452*88b783a1SJames Wright break; 453*88b783a1SJames Wright } 454*88b783a1SJames Wright 455*88b783a1SJames Wright } // End Quadrature Point Loop 456*88b783a1SJames Wright 457*88b783a1SJames Wright // Return 458*88b783a1SJames Wright return 0; 459*88b783a1SJames Wright } 460*88b783a1SJames Wright 461*88b783a1SJames Wright // ***************************************************************************** 462*88b783a1SJames Wright // This QFunction implements the Navier-Stokes equations (mentioned above) with 463*88b783a1SJames Wright // implicit time stepping method 464*88b783a1SJames Wright // 465*88b783a1SJames Wright // SU = Galerkin + grad(v) . ( Ai^T * Tau * (Aj q,j) ) 466*88b783a1SJames Wright // SUPG = Galerkin + grad(v) . ( Ai^T * Tau * (q_dot + Aj q,j - body force) ) 467*88b783a1SJames Wright // (diffussive terms will be added later) 468*88b783a1SJames Wright // 469*88b783a1SJames Wright // ***************************************************************************** 470*88b783a1SJames Wright CEED_QFUNCTION(IFunction_Newtonian)(void *ctx, CeedInt Q, 471*88b783a1SJames Wright const CeedScalar *const *in, 472*88b783a1SJames Wright CeedScalar *const *out) { 473*88b783a1SJames Wright // *INDENT-OFF* 474*88b783a1SJames Wright // Inputs 475*88b783a1SJames Wright const CeedScalar (*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 476*88b783a1SJames Wright (*dq)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 477*88b783a1SJames Wright (*q_dot)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 478*88b783a1SJames Wright (*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 479*88b783a1SJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 480*88b783a1SJames Wright // Outputs 481*88b783a1SJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], 482*88b783a1SJames Wright (*dv)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 483*88b783a1SJames Wright // *INDENT-ON* 484*88b783a1SJames Wright // Context 485*88b783a1SJames Wright NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 486*88b783a1SJames Wright const CeedScalar lambda = context->lambda; 487*88b783a1SJames Wright const CeedScalar mu = context->mu; 488*88b783a1SJames Wright const CeedScalar k = context->k; 489*88b783a1SJames Wright const CeedScalar cv = context->cv; 490*88b783a1SJames Wright const CeedScalar cp = context->cp; 491*88b783a1SJames Wright const CeedScalar g = context->g; 492*88b783a1SJames Wright const CeedScalar c_tau = context->c_tau; 493*88b783a1SJames Wright const CeedScalar gamma = cp / cv; 494*88b783a1SJames Wright 495*88b783a1SJames Wright CeedPragmaSIMD 496*88b783a1SJames Wright // Quadrature Point Loop 497*88b783a1SJames Wright for (CeedInt i=0; i<Q; i++) { 498*88b783a1SJames Wright // Setup 499*88b783a1SJames Wright // -- Interp in 500*88b783a1SJames Wright const CeedScalar rho = q[0][i]; 501*88b783a1SJames Wright const CeedScalar u[3] = {q[1][i] / rho, 502*88b783a1SJames Wright q[2][i] / rho, 503*88b783a1SJames Wright q[3][i] / rho 504*88b783a1SJames Wright }; 505*88b783a1SJames Wright const CeedScalar E = q[4][i]; 506*88b783a1SJames Wright // -- Grad in 507*88b783a1SJames Wright const CeedScalar drho[3] = {dq[0][0][i], 508*88b783a1SJames Wright dq[1][0][i], 509*88b783a1SJames Wright dq[2][0][i] 510*88b783a1SJames Wright }; 511*88b783a1SJames Wright // *INDENT-OFF* 512*88b783a1SJames Wright const CeedScalar dU[3][3] = {{dq[0][1][i], 513*88b783a1SJames Wright dq[1][1][i], 514*88b783a1SJames Wright dq[2][1][i]}, 515*88b783a1SJames Wright {dq[0][2][i], 516*88b783a1SJames Wright dq[1][2][i], 517*88b783a1SJames Wright dq[2][2][i]}, 518*88b783a1SJames Wright {dq[0][3][i], 519*88b783a1SJames Wright dq[1][3][i], 520*88b783a1SJames Wright dq[2][3][i]} 521*88b783a1SJames Wright }; 522*88b783a1SJames Wright // *INDENT-ON* 523*88b783a1SJames Wright const CeedScalar dE[3] = {dq[0][4][i], 524*88b783a1SJames Wright dq[1][4][i], 525*88b783a1SJames Wright dq[2][4][i] 526*88b783a1SJames Wright }; 527*88b783a1SJames Wright // -- Interp-to-Interp q_data 528*88b783a1SJames Wright const CeedScalar wdetJ = q_data[0][i]; 529*88b783a1SJames Wright // -- Interp-to-Grad q_data 530*88b783a1SJames Wright // ---- Inverse of change of coordinate matrix: X_i,j 531*88b783a1SJames Wright // *INDENT-OFF* 532*88b783a1SJames Wright const CeedScalar dXdx[3][3] = {{q_data[1][i], 533*88b783a1SJames Wright q_data[2][i], 534*88b783a1SJames Wright q_data[3][i]}, 535*88b783a1SJames Wright {q_data[4][i], 536*88b783a1SJames Wright q_data[5][i], 537*88b783a1SJames Wright q_data[6][i]}, 538*88b783a1SJames Wright {q_data[7][i], 539*88b783a1SJames Wright q_data[8][i], 540*88b783a1SJames Wright q_data[9][i]} 541*88b783a1SJames Wright }; 542*88b783a1SJames Wright // *INDENT-ON* 543*88b783a1SJames Wright // -- Grad-to-Grad q_data 544*88b783a1SJames Wright // dU/dx 545*88b783a1SJames Wright CeedScalar du[3][3] = {{0}}; 546*88b783a1SJames Wright CeedScalar drhodx[3] = {0}; 547*88b783a1SJames Wright CeedScalar dEdx[3] = {0}; 548*88b783a1SJames Wright CeedScalar dUdx[3][3] = {{0}}; 549*88b783a1SJames Wright CeedScalar dXdxdXdxT[3][3] = {{0}}; 550*88b783a1SJames Wright for (int j=0; j<3; j++) { 551*88b783a1SJames Wright for (int k=0; k<3; k++) { 552*88b783a1SJames Wright du[j][k] = (dU[j][k] - drho[k]*u[j]) / rho; 553*88b783a1SJames Wright drhodx[j] += drho[k] * dXdx[k][j]; 554*88b783a1SJames Wright dEdx[j] += dE[k] * dXdx[k][j]; 555*88b783a1SJames Wright for (int l=0; l<3; l++) { 556*88b783a1SJames Wright dUdx[j][k] += dU[j][l] * dXdx[l][k]; 557*88b783a1SJames Wright dXdxdXdxT[j][k] += dXdx[j][l]*dXdx[k][l]; //dXdx_j,k * dXdx_k,j 558*88b783a1SJames Wright } 559*88b783a1SJames Wright } 560*88b783a1SJames Wright } 561*88b783a1SJames Wright CeedScalar dudx[3][3] = {{0}}; 562*88b783a1SJames Wright for (int j=0; j<3; j++) 563*88b783a1SJames Wright for (int k=0; k<3; k++) 564*88b783a1SJames Wright for (int l=0; l<3; l++) 565*88b783a1SJames Wright dudx[j][k] += du[j][l] * dXdx[l][k]; 566*88b783a1SJames Wright // -- grad_T 567*88b783a1SJames Wright const CeedScalar grad_T[3] = {(dEdx[0]/rho - E*drhodx[0]/(rho*rho) - /* *NOPAD* */ 568*88b783a1SJames Wright (u[0]*dudx[0][0] + u[1]*dudx[1][0] + u[2]*dudx[2][0]))/cv, 569*88b783a1SJames Wright (dEdx[1]/rho - E*drhodx[1]/(rho*rho) - /* *NOPAD* */ 570*88b783a1SJames Wright (u[0]*dudx[0][1] + u[1]*dudx[1][1] + u[2]*dudx[2][1]))/cv, 571*88b783a1SJames Wright (dEdx[2]/rho - E*drhodx[2]/(rho*rho) - /* *NOPAD* */ 572*88b783a1SJames Wright (u[0]*dudx[0][2] + u[1]*dudx[1][2] + u[2]*dudx[2][2]) - g)/cv 573*88b783a1SJames Wright }; 574*88b783a1SJames Wright // -- Fuvisc 575*88b783a1SJames Wright // ---- Symmetric 3x3 matrix 576*88b783a1SJames Wright const CeedScalar Fu[6] = {mu*(dudx[0][0] * (2 + lambda) + /* *NOPAD* */ 577*88b783a1SJames Wright lambda * (dudx[1][1] + dudx[2][2])), 578*88b783a1SJames Wright mu*(dudx[0][1] + dudx[1][0]), /* *NOPAD* */ 579*88b783a1SJames Wright mu*(dudx[0][2] + dudx[2][0]), /* *NOPAD* */ 580*88b783a1SJames Wright mu*(dudx[1][1] * (2 + lambda) + /* *NOPAD* */ 581*88b783a1SJames Wright lambda * (dudx[0][0] + dudx[2][2])), 582*88b783a1SJames Wright mu*(dudx[1][2] + dudx[2][1]), /* *NOPAD* */ 583*88b783a1SJames Wright mu*(dudx[2][2] * (2 + lambda) + /* *NOPAD* */ 584*88b783a1SJames Wright lambda * (dudx[0][0] + dudx[1][1])) 585*88b783a1SJames Wright }; 586*88b783a1SJames Wright // -- Fevisc 587*88b783a1SJames Wright const CeedScalar Fe[3] = {u[0]*Fu[0] + u[1]*Fu[1] + u[2]*Fu[2] + /* *NOPAD* */ 588*88b783a1SJames Wright k*grad_T[0], /* *NOPAD* */ 589*88b783a1SJames Wright u[0]*Fu[1] + u[1]*Fu[3] + u[2]*Fu[4] + /* *NOPAD* */ 590*88b783a1SJames Wright k*grad_T[1], /* *NOPAD* */ 591*88b783a1SJames Wright u[0]*Fu[2] + u[1]*Fu[4] + u[2]*Fu[5] + /* *NOPAD* */ 592*88b783a1SJames Wright k*grad_T[2] /* *NOPAD* */ 593*88b783a1SJames Wright }; 594*88b783a1SJames Wright // Pressure 595*88b783a1SJames Wright const CeedScalar 596*88b783a1SJames Wright E_kinetic = 0.5 * rho * (u[0]*u[0] + u[1]*u[1] + u[2]*u[2]), 597*88b783a1SJames Wright E_potential = rho*g*x[2][i], 598*88b783a1SJames Wright E_internal = E - E_kinetic - E_potential, 599*88b783a1SJames Wright P = E_internal * (gamma - 1.); // P = pressure 600*88b783a1SJames Wright 601*88b783a1SJames Wright // jacob_F_conv[3][5][5] = dF(convective)/dq at each direction 602*88b783a1SJames Wright CeedScalar jacob_F_conv[3][5][5] = {{{0.}}}; 603*88b783a1SJames Wright computeFluxJacobian_NS(jacob_F_conv, rho, u, E, gamma, g, x[2][i]); 604*88b783a1SJames Wright 605*88b783a1SJames Wright // jacob_F_conv_T = jacob_F_conv^T 606*88b783a1SJames Wright CeedScalar jacob_F_conv_T[3][5][5]; 607*88b783a1SJames Wright for (int j=0; j<3; j++) 608*88b783a1SJames Wright for (int k=0; k<5; k++) 609*88b783a1SJames Wright for (int l=0; l<5; l++) 610*88b783a1SJames Wright jacob_F_conv_T[j][k][l] = jacob_F_conv[j][l][k]; 611*88b783a1SJames Wright // dqdx collects drhodx, dUdx and dEdx in one vector 612*88b783a1SJames Wright CeedScalar dqdx[5][3]; 613*88b783a1SJames Wright for (int j=0; j<3; j++) { 614*88b783a1SJames Wright dqdx[0][j] = drhodx[j]; 615*88b783a1SJames Wright dqdx[4][j] = dEdx[j]; 616*88b783a1SJames Wright for (int k=0; k<3; k++) 617*88b783a1SJames Wright dqdx[k+1][j] = dUdx[k][j]; 618*88b783a1SJames Wright } 619*88b783a1SJames Wright // strong_conv = dF/dq * dq/dx (Strong convection) 620*88b783a1SJames Wright CeedScalar strong_conv[5] = {0}; 621*88b783a1SJames Wright for (int j=0; j<3; j++) 622*88b783a1SJames Wright for (int k=0; k<5; k++) 623*88b783a1SJames Wright for (int l=0; l<5; l++) 624*88b783a1SJames Wright strong_conv[k] += jacob_F_conv[j][k][l] * dqdx[l][j]; 625*88b783a1SJames Wright 626*88b783a1SJames Wright // Body force 627*88b783a1SJames Wright const CeedScalar body_force[5] = {0, 0, 0, -rho*g, 0}; 628*88b783a1SJames Wright 629*88b783a1SJames Wright // Strong residual 630*88b783a1SJames Wright CeedScalar strong_res[5]; 631*88b783a1SJames Wright for (int j=0; j<5; j++) 632*88b783a1SJames Wright strong_res[j] = q_dot[j][i] + strong_conv[j] - body_force[j]; 633*88b783a1SJames Wright 634*88b783a1SJames Wright // The Physics 635*88b783a1SJames Wright //-----mass matrix 636*88b783a1SJames Wright for (int j=0; j<5; j++) 637*88b783a1SJames Wright v[j][i] = wdetJ*q_dot[j][i]; 638*88b783a1SJames Wright 639*88b783a1SJames Wright // Zero dv so all future terms can safely sum into it 640*88b783a1SJames Wright for (int j=0; j<5; j++) 641*88b783a1SJames Wright for (int k=0; k<3; k++) 642*88b783a1SJames Wright dv[k][j][i] = 0; 643*88b783a1SJames Wright 644*88b783a1SJames Wright // -- Density 645*88b783a1SJames Wright // ---- u rho 646*88b783a1SJames Wright for (int j=0; j<3; j++) 647*88b783a1SJames Wright dv[j][0][i] -= wdetJ*(rho*u[0]*dXdx[j][0] + rho*u[1]*dXdx[j][1] + 648*88b783a1SJames Wright rho*u[2]*dXdx[j][2]); 649*88b783a1SJames Wright // -- Momentum 650*88b783a1SJames Wright // ---- rho (u x u) + P I3 651*88b783a1SJames Wright for (int j=0; j<3; j++) 652*88b783a1SJames Wright for (int k=0; k<3; k++) 653*88b783a1SJames Wright dv[k][j+1][i] -= wdetJ*((rho*u[j]*u[0] + (j==0?P:0))*dXdx[k][0] + 654*88b783a1SJames Wright (rho*u[j]*u[1] + (j==1?P:0))*dXdx[k][1] + 655*88b783a1SJames Wright (rho*u[j]*u[2] + (j==2?P:0))*dXdx[k][2]); 656*88b783a1SJames Wright // ---- Fuvisc 657*88b783a1SJames Wright const CeedInt Fuviscidx[3][3] = {{0, 1, 2}, {1, 3, 4}, {2, 4, 5}}; // symmetric matrix indices 658*88b783a1SJames Wright for (int j=0; j<3; j++) 659*88b783a1SJames Wright for (int k=0; k<3; k++) 660*88b783a1SJames Wright dv[k][j+1][i] += wdetJ*(Fu[Fuviscidx[j][0]]*dXdx[k][0] + 661*88b783a1SJames Wright Fu[Fuviscidx[j][1]]*dXdx[k][1] + 662*88b783a1SJames Wright Fu[Fuviscidx[j][2]]*dXdx[k][2]); 663*88b783a1SJames Wright // -- Total Energy Density 664*88b783a1SJames Wright // ---- (E + P) u 665*88b783a1SJames Wright for (int j=0; j<3; j++) 666*88b783a1SJames Wright dv[j][4][i] -= wdetJ * (E + P) * (u[0]*dXdx[j][0] + u[1]*dXdx[j][1] + 667*88b783a1SJames Wright u[2]*dXdx[j][2]); 668*88b783a1SJames Wright // ---- Fevisc 669*88b783a1SJames Wright for (int j=0; j<3; j++) 670*88b783a1SJames Wright dv[j][4][i] += wdetJ * (Fe[0]*dXdx[j][0] + Fe[1]*dXdx[j][1] + 671*88b783a1SJames Wright Fe[2]*dXdx[j][2]); 672*88b783a1SJames Wright // Body Force 673*88b783a1SJames Wright for (int j=0; j<5; j++) 674*88b783a1SJames Wright v[j][i] -= wdetJ*body_force[j]; 675*88b783a1SJames Wright 676*88b783a1SJames Wright // Stabilization 677*88b783a1SJames Wright // -- Tau elements 678*88b783a1SJames Wright const CeedScalar sound_speed = sqrt(gamma * P / rho); 679*88b783a1SJames Wright CeedScalar Tau_x[3] = {0.}; 680*88b783a1SJames Wright Tau_spatial(Tau_x, dXdx, u, sound_speed, c_tau); 681*88b783a1SJames Wright 682*88b783a1SJames Wright // -- Stabilization method: none, SU, or SUPG 683*88b783a1SJames Wright CeedScalar stab[5][3]; 684*88b783a1SJames Wright switch (context->stabilization) { 685*88b783a1SJames Wright case STAB_NONE: // Galerkin 686*88b783a1SJames Wright break; 687*88b783a1SJames Wright case STAB_SU: // SU 688*88b783a1SJames Wright for (int j=0; j<3; j++) 689*88b783a1SJames Wright for (int k=0; k<5; k++) 690*88b783a1SJames Wright for (int l=0; l<5; l++) 691*88b783a1SJames Wright stab[k][j] = jacob_F_conv_T[j][k][l] * Tau_x[j] * strong_conv[l]; 692*88b783a1SJames Wright 693*88b783a1SJames Wright for (int j=0; j<5; j++) 694*88b783a1SJames Wright for (int k=0; k<3; k++) 695*88b783a1SJames Wright dv[k][j][i] += wdetJ*(stab[j][0] * dXdx[k][0] + 696*88b783a1SJames Wright stab[j][1] * dXdx[k][1] + 697*88b783a1SJames Wright stab[j][2] * dXdx[k][2]); 698*88b783a1SJames Wright break; 699*88b783a1SJames Wright case STAB_SUPG: // SUPG 700*88b783a1SJames Wright for (int j=0; j<3; j++) 701*88b783a1SJames Wright for (int k=0; k<5; k++) 702*88b783a1SJames Wright for (int l=0; l<5; l++) 703*88b783a1SJames Wright stab[k][j] = jacob_F_conv_T[j][k][l] * Tau_x[j] * strong_res[l]; 704*88b783a1SJames Wright 705*88b783a1SJames Wright for (int j=0; j<5; j++) 706*88b783a1SJames Wright for (int k=0; k<3; k++) 707*88b783a1SJames Wright dv[k][j][i] += wdetJ*(stab[j][0] * dXdx[k][0] + 708*88b783a1SJames Wright stab[j][1] * dXdx[k][1] + 709*88b783a1SJames Wright stab[j][2] * dXdx[k][2]); 710*88b783a1SJames Wright break; 711*88b783a1SJames Wright } 712*88b783a1SJames Wright 713*88b783a1SJames Wright } // End Quadrature Point Loop 714*88b783a1SJames Wright 715*88b783a1SJames Wright // Return 716*88b783a1SJames Wright return 0; 717*88b783a1SJames Wright } 718*88b783a1SJames Wright // ***************************************************************************** 719*88b783a1SJames Wright #endif // newtonian_h 720