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