xref: /honee/qfunctions/newtonian.h (revision 727da7e70824329c32c70307643ee0d0901369c8)
1*727da7e7SJeremy L Thompson // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors.
2*727da7e7SJeremy L Thompson // All Rights Reserved. See the top-level LICENSE and NOTICE files for details.
33a8779fbSJames Wright //
4*727da7e7SJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause
53a8779fbSJames Wright //
6*727da7e7SJeremy L Thompson // This file is part of CEED:  http://github.com/ceed
73a8779fbSJames Wright 
83a8779fbSJames Wright /// @file
93a8779fbSJames Wright /// Operator for Navier-Stokes example using PETSc
103a8779fbSJames Wright 
113a8779fbSJames Wright 
123a8779fbSJames Wright #ifndef newtonian_h
133a8779fbSJames Wright #define newtonian_h
143a8779fbSJames Wright 
153a8779fbSJames Wright #include <math.h>
163a8779fbSJames Wright #include <ceed.h>
173a8779fbSJames Wright 
183a8779fbSJames Wright #ifndef M_PI
193a8779fbSJames Wright #define M_PI    3.14159265358979323846
203a8779fbSJames Wright #endif
213a8779fbSJames Wright 
223a8779fbSJames Wright #ifndef setup_context_struct
233a8779fbSJames Wright #define setup_context_struct
243a8779fbSJames Wright typedef struct SetupContext_ *SetupContext;
253a8779fbSJames Wright struct SetupContext_ {
263a8779fbSJames Wright   CeedScalar theta0;
273a8779fbSJames Wright   CeedScalar thetaC;
283a8779fbSJames Wright   CeedScalar P0;
293a8779fbSJames Wright   CeedScalar N;
303a8779fbSJames Wright   CeedScalar cv;
313a8779fbSJames Wright   CeedScalar cp;
323a8779fbSJames Wright   CeedScalar g;
333a8779fbSJames Wright   CeedScalar rc;
343a8779fbSJames Wright   CeedScalar lx;
353a8779fbSJames Wright   CeedScalar ly;
363a8779fbSJames Wright   CeedScalar lz;
373a8779fbSJames Wright   CeedScalar center[3];
383a8779fbSJames Wright   CeedScalar dc_axis[3];
393a8779fbSJames Wright   CeedScalar wind[3];
403a8779fbSJames Wright   CeedScalar time;
413a8779fbSJames Wright   int wind_type;              // See WindType: 0=ROTATION, 1=TRANSLATION
423a8779fbSJames Wright   int bubble_type;            // See BubbleType: 0=SPHERE, 1=CYLINDER
433a8779fbSJames Wright   int bubble_continuity_type; // See BubbleContinuityType: 0=SMOOTH, 1=BACK_SHARP 2=THICK
443a8779fbSJames Wright };
453a8779fbSJames Wright #endif
463a8779fbSJames Wright 
473a8779fbSJames Wright #ifndef newtonian_context_struct
483a8779fbSJames Wright #define newtonian_context_struct
493a8779fbSJames Wright typedef enum {
503a8779fbSJames Wright   STAB_NONE = 0,
513a8779fbSJames Wright   STAB_SU   = 1, // Streamline Upwind
523a8779fbSJames Wright   STAB_SUPG = 2, // Streamline Upwind Petrov-Galerkin
533a8779fbSJames Wright } StabilizationType;
543a8779fbSJames Wright 
553a8779fbSJames Wright typedef struct NewtonianIdealGasContext_ *NewtonianIdealGasContext;
563a8779fbSJames Wright struct NewtonianIdealGasContext_ {
573a8779fbSJames Wright   CeedScalar lambda;
583a8779fbSJames Wright   CeedScalar mu;
593a8779fbSJames Wright   CeedScalar k;
603a8779fbSJames Wright   CeedScalar cv;
613a8779fbSJames Wright   CeedScalar cp;
623a8779fbSJames Wright   CeedScalar g;
633a8779fbSJames Wright   CeedScalar c_tau;
643a8779fbSJames Wright   StabilizationType stabilization;
653a8779fbSJames Wright };
663a8779fbSJames Wright #endif
673a8779fbSJames Wright 
683a8779fbSJames Wright // *****************************************************************************
693a8779fbSJames Wright // Helper function for computing flux Jacobian
703a8779fbSJames Wright // *****************************************************************************
713a8779fbSJames Wright CEED_QFUNCTION_HELPER void computeFluxJacobian_NS(CeedScalar dF[3][5][5],
723a8779fbSJames Wright     const CeedScalar rho, const CeedScalar u[3], const CeedScalar E,
733a8779fbSJames Wright     const CeedScalar gamma, const CeedScalar g, CeedScalar z) {
743a8779fbSJames Wright   CeedScalar u_sq = u[0]*u[0] + u[1]*u[1] + u[2]*u[2]; // Velocity square
753a8779fbSJames Wright   for (CeedInt i=0; i<3; i++) { // Jacobian matrices for 3 directions
763a8779fbSJames Wright     for (CeedInt j=0; j<3; j++) { // Rows of each Jacobian matrix
773a8779fbSJames Wright       dF[i][j+1][0] = ((i==j) ? ((gamma-1.)*(u_sq/2. - g*z)) : 0.) - u[i]*u[j];
783a8779fbSJames Wright       for (CeedInt k=0; k<3; k++) { // Columns of each Jacobian matrix
793a8779fbSJames Wright         dF[i][0][k+1]   = ((i==k) ? 1. : 0.);
803a8779fbSJames Wright         dF[i][j+1][k+1] = ((j==k) ? u[i] : 0.) +
813a8779fbSJames Wright                           ((i==k) ? u[j] : 0.) -
823a8779fbSJames Wright                           ((i==j) ? u[k] : 0.) * (gamma-1.);
833a8779fbSJames Wright         dF[i][4][k+1]   = ((i==k) ? (E*gamma/rho - (gamma-1.)*u_sq/2.) : 0.) -
843a8779fbSJames Wright                           (gamma-1.)*u[i]*u[k];
853a8779fbSJames Wright       }
863a8779fbSJames Wright       dF[i][j+1][4] = ((i==j) ? (gamma-1.) : 0.);
873a8779fbSJames Wright     }
883a8779fbSJames Wright     dF[i][4][0] = u[i] * ((gamma-1.)*u_sq - E*gamma/rho);
893a8779fbSJames Wright     dF[i][4][4] = u[i] * gamma;
903a8779fbSJames Wright   }
913a8779fbSJames Wright }
923a8779fbSJames Wright 
933a8779fbSJames Wright // *****************************************************************************
943a8779fbSJames Wright // Helper function for computing Tau elements (stabilization constant)
953a8779fbSJames Wright //   Model from:
963a8779fbSJames Wright //     Stabilized Methods for Compressible Flows, Hughes et al 2010
973a8779fbSJames Wright //
983a8779fbSJames Wright //   Spatial criterion #2 - Tau is a 3x3 diagonal matrix
993a8779fbSJames Wright //   Tau[i] = c_tau h[i] Xi(Pe) / rho(A[i]) (no sum)
1003a8779fbSJames Wright //
1013a8779fbSJames Wright // Where
1023a8779fbSJames Wright //   c_tau     = stabilization constant (0.5 is reported as "optimal")
1033a8779fbSJames Wright //   h[i]      = 2 length(dxdX[i])
1043a8779fbSJames Wright //   Pe        = Peclet number ( Pe = sqrt(u u) / dot(dXdx,u) diffusivity )
1053a8779fbSJames Wright //   Xi(Pe)    = coth Pe - 1. / Pe (1. at large local Peclet number )
1063a8779fbSJames Wright //   rho(A[i]) = spectral radius of the convective flux Jacobian i,
1073a8779fbSJames Wright //               wave speed in direction i
1083a8779fbSJames Wright // *****************************************************************************
1093a8779fbSJames Wright CEED_QFUNCTION_HELPER void Tau_spatial(CeedScalar Tau_x[3],
1103a8779fbSJames Wright                                        const CeedScalar dXdx[3][3], const CeedScalar u[3],
1113a8779fbSJames Wright                                        const CeedScalar sound_speed, const CeedScalar c_tau) {
1123a8779fbSJames Wright   for (int i=0; i<3; i++) {
1133a8779fbSJames Wright     // length of element in direction i
1143a8779fbSJames Wright     CeedScalar h = 2 / sqrt(dXdx[0][i]*dXdx[0][i] + dXdx[1][i]*dXdx[1][i] +
1153a8779fbSJames Wright                             dXdx[2][i]*dXdx[2][i]);
1163a8779fbSJames Wright     // fastest wave in direction i
1173a8779fbSJames Wright     CeedScalar fastest_wave = fabs(u[i]) + sound_speed;
1183a8779fbSJames Wright     Tau_x[i] = c_tau * h / fastest_wave;
1193a8779fbSJames Wright   }
1203a8779fbSJames Wright }
1213a8779fbSJames Wright 
1223a8779fbSJames Wright // *****************************************************************************
1233a8779fbSJames Wright // This QFunction sets a "still" initial condition for generic Newtonian IG problems
1243a8779fbSJames Wright // *****************************************************************************
1253a8779fbSJames Wright CEED_QFUNCTION(ICsNewtonianIG)(void *ctx, CeedInt Q,
1263a8779fbSJames Wright                                const CeedScalar *const *in, CeedScalar *const *out) {
1273a8779fbSJames Wright   // Inputs
1283a8779fbSJames Wright   const CeedScalar (*X)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0];
1293a8779fbSJames Wright 
1303a8779fbSJames Wright   // Outputs
1313a8779fbSJames Wright   CeedScalar (*q0)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0];
1323a8779fbSJames Wright 
1333a8779fbSJames Wright   // Quadrature Point Loop
1343a8779fbSJames Wright   CeedPragmaSIMD
1353a8779fbSJames Wright   for (CeedInt i=0; i<Q; i++) {
1363a8779fbSJames Wright     CeedScalar q[5] = {0.};
1373a8779fbSJames Wright 
1383a8779fbSJames Wright     // Context
1393a8779fbSJames Wright     const SetupContext context = (SetupContext)ctx;
1403a8779fbSJames Wright     const CeedScalar theta0    = context->theta0;
1413a8779fbSJames Wright     const CeedScalar P0        = context->P0;
1423a8779fbSJames Wright     const CeedScalar N         = context->N;
1433a8779fbSJames Wright     const CeedScalar cv        = context->cv;
1443a8779fbSJames Wright     const CeedScalar cp        = context->cp;
1453a8779fbSJames Wright     const CeedScalar g         = context->g;
1463a8779fbSJames Wright     const CeedScalar Rd        = cp - cv;
1473a8779fbSJames Wright 
1483a8779fbSJames Wright     // Setup
1493a8779fbSJames Wright     // -- Coordinates
1503a8779fbSJames Wright     const CeedScalar z = X[2][i];
1513a8779fbSJames Wright 
1523a8779fbSJames Wright     // -- Exner pressure, hydrostatic balance
1533a8779fbSJames Wright     const CeedScalar Pi = 1. + g*g*(exp(-N*N*z/g) - 1.) / (cp*theta0*N*N);
1543a8779fbSJames Wright 
1553a8779fbSJames Wright     // -- Density
1563a8779fbSJames Wright     const CeedScalar rho = P0 * pow(Pi, cv/Rd) / (Rd*theta0);
1573a8779fbSJames Wright 
1583a8779fbSJames Wright     // Initial Conditions
1593a8779fbSJames Wright     q[0] = rho;
1603a8779fbSJames Wright     q[1] = 0.0;
1613a8779fbSJames Wright     q[2] = 0.0;
1623a8779fbSJames Wright     q[3] = 0.0;
1633a8779fbSJames Wright     q[4] = rho * (cv*theta0*Pi + g*z);
1643a8779fbSJames Wright 
1653a8779fbSJames Wright     for (CeedInt j=0; j<5; j++)
1663a8779fbSJames Wright       q0[j][i] = q[j];
1673a8779fbSJames Wright   } // End of Quadrature Point Loop
1683a8779fbSJames Wright   return 0;
1693a8779fbSJames Wright }
1703a8779fbSJames Wright 
1713a8779fbSJames Wright // *****************************************************************************
1723a8779fbSJames Wright // This QFunction implements the following formulation of Navier-Stokes with
1733a8779fbSJames Wright //   explicit time stepping method
1743a8779fbSJames Wright //
1753a8779fbSJames Wright // This is 3D compressible Navier-Stokes in conservation form with state
1763a8779fbSJames Wright //   variables of density, momentum density, and total energy density.
1773a8779fbSJames Wright //
1783a8779fbSJames Wright // State Variables: q = ( rho, U1, U2, U3, E )
1793a8779fbSJames Wright //   rho - Mass Density
1803a8779fbSJames Wright //   Ui  - Momentum Density,      Ui = rho ui
1813a8779fbSJames Wright //   E   - Total Energy Density,  E  = rho (cv T + (u u)/2 + g z)
1823a8779fbSJames Wright //
1833a8779fbSJames Wright // Navier-Stokes Equations:
1843a8779fbSJames Wright //   drho/dt + div( U )                               = 0
1853a8779fbSJames Wright //   dU/dt   + div( rho (u x u) + P I3 ) + rho g khat = div( Fu )
1863a8779fbSJames Wright //   dE/dt   + div( (E + P) u )                       = div( Fe )
1873a8779fbSJames Wright //
1883a8779fbSJames Wright // Viscous Stress:
1893a8779fbSJames Wright //   Fu = mu (grad( u ) + grad( u )^T + lambda div ( u ) I3)
1903a8779fbSJames Wright //
1913a8779fbSJames Wright // Thermal Stress:
1923a8779fbSJames Wright //   Fe = u Fu + k grad( T )
1933a8779fbSJames Wright //
1943a8779fbSJames Wright // Equation of State:
1953a8779fbSJames Wright //   P = (gamma - 1) (E - rho (u u) / 2 - rho g z)
1963a8779fbSJames Wright //
1973a8779fbSJames Wright // Stabilization:
1983a8779fbSJames Wright //   Tau = diag(TauC, TauM, TauM, TauM, TauE)
1993a8779fbSJames Wright //     f1 = rho  sqrt(ui uj gij)
2003a8779fbSJames Wright //     gij = dXi/dX * dXi/dX
2013a8779fbSJames Wright //     TauC = Cc f1 / (8 gii)
2023a8779fbSJames Wright //     TauM = min( 1 , 1 / f1 )
2033a8779fbSJames Wright //     TauE = TauM / (Ce cv)
2043a8779fbSJames Wright //
2053a8779fbSJames Wright //  SU   = Galerkin + grad(v) . ( Ai^T * Tau * (Aj q,j) )
2063a8779fbSJames Wright //
2073a8779fbSJames Wright // Constants:
2083a8779fbSJames Wright //   lambda = - 2 / 3,  From Stokes hypothesis
2093a8779fbSJames Wright //   mu              ,  Dynamic viscosity
2103a8779fbSJames Wright //   k               ,  Thermal conductivity
2113a8779fbSJames Wright //   cv              ,  Specific heat, constant volume
2123a8779fbSJames Wright //   cp              ,  Specific heat, constant pressure
2133a8779fbSJames Wright //   g               ,  Gravity
2143a8779fbSJames Wright //   gamma  = cp / cv,  Specific heat ratio
2153a8779fbSJames Wright //
2163a8779fbSJames Wright // We require the product of the inverse of the Jacobian (dXdx_j,k) and
2173a8779fbSJames Wright // its transpose (dXdx_k,j) to properly compute integrals of the form:
2183a8779fbSJames Wright // int( gradv gradu )
2193a8779fbSJames Wright //
2203a8779fbSJames Wright // *****************************************************************************
2213a8779fbSJames Wright CEED_QFUNCTION(Newtonian)(void *ctx, CeedInt Q,
2223a8779fbSJames Wright                           const CeedScalar *const *in, CeedScalar *const *out) {
2233a8779fbSJames Wright   // *INDENT-OFF*
2243a8779fbSJames Wright   // Inputs
2253a8779fbSJames Wright   const CeedScalar (*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0],
2263a8779fbSJames Wright                    (*dq)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1],
2273a8779fbSJames Wright                    (*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2],
2283a8779fbSJames Wright                    (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3];
2293a8779fbSJames Wright   // Outputs
2303a8779fbSJames Wright   CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0],
2313a8779fbSJames Wright              (*dv)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1];
2323a8779fbSJames Wright   // *INDENT-ON*
2333a8779fbSJames Wright 
2343a8779fbSJames Wright   // Context
2353a8779fbSJames Wright   NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx;
2363a8779fbSJames Wright   const CeedScalar lambda = context->lambda;
2373a8779fbSJames Wright   const CeedScalar mu     = context->mu;
2383a8779fbSJames Wright   const CeedScalar k      = context->k;
2393a8779fbSJames Wright   const CeedScalar cv     = context->cv;
2403a8779fbSJames Wright   const CeedScalar cp     = context->cp;
2413a8779fbSJames Wright   const CeedScalar g      = context->g;
2423a8779fbSJames Wright   const CeedScalar c_tau  = context->c_tau;
2433a8779fbSJames Wright   const CeedScalar gamma  = cp / cv;
2443a8779fbSJames Wright 
2453a8779fbSJames Wright   CeedPragmaSIMD
2463a8779fbSJames Wright   // Quadrature Point Loop
2473a8779fbSJames Wright   for (CeedInt i=0; i<Q; i++) {
2483a8779fbSJames Wright     // *INDENT-OFF*
2493a8779fbSJames Wright     // Setup
2503a8779fbSJames Wright     // -- Interp in
2513a8779fbSJames Wright     const CeedScalar rho        =   q[0][i];
2523a8779fbSJames Wright     const CeedScalar u[3]       =  {q[1][i] / rho,
2533a8779fbSJames Wright                                     q[2][i] / rho,
2543a8779fbSJames Wright                                     q[3][i] / rho
2553a8779fbSJames Wright                                    };
2563a8779fbSJames Wright     const CeedScalar E          =   q[4][i];
2573a8779fbSJames Wright     // -- Grad in
2583a8779fbSJames Wright     const CeedScalar drho[3]    =  {dq[0][0][i],
2593a8779fbSJames Wright                                     dq[1][0][i],
2603a8779fbSJames Wright                                     dq[2][0][i]
2613a8779fbSJames Wright                                    };
2623a8779fbSJames Wright     const CeedScalar dU[3][3]   = {{dq[0][1][i],
2633a8779fbSJames Wright                                     dq[1][1][i],
2643a8779fbSJames Wright                                     dq[2][1][i]},
2653a8779fbSJames Wright                                    {dq[0][2][i],
2663a8779fbSJames Wright                                     dq[1][2][i],
2673a8779fbSJames Wright                                     dq[2][2][i]},
2683a8779fbSJames Wright                                    {dq[0][3][i],
2693a8779fbSJames Wright                                     dq[1][3][i],
2703a8779fbSJames Wright                                     dq[2][3][i]}
2713a8779fbSJames Wright                                   };
2723a8779fbSJames Wright     const CeedScalar dE[3]      =  {dq[0][4][i],
2733a8779fbSJames Wright                                     dq[1][4][i],
2743a8779fbSJames Wright                                     dq[2][4][i]
2753a8779fbSJames Wright                                    };
2763a8779fbSJames Wright     // -- Interp-to-Interp q_data
2773a8779fbSJames Wright     const CeedScalar wdetJ      =   q_data[0][i];
2783a8779fbSJames Wright     // -- Interp-to-Grad q_data
2793a8779fbSJames Wright     // ---- Inverse of change of coordinate matrix: X_i,j
2803a8779fbSJames Wright     // *INDENT-OFF*
2813a8779fbSJames Wright     const CeedScalar dXdx[3][3] = {{q_data[1][i],
2823a8779fbSJames Wright                                     q_data[2][i],
2833a8779fbSJames Wright                                     q_data[3][i]},
2843a8779fbSJames Wright                                    {q_data[4][i],
2853a8779fbSJames Wright                                     q_data[5][i],
2863a8779fbSJames Wright                                     q_data[6][i]},
2873a8779fbSJames Wright                                    {q_data[7][i],
2883a8779fbSJames Wright                                     q_data[8][i],
2893a8779fbSJames Wright                                     q_data[9][i]}
2903a8779fbSJames Wright                                   };
2913a8779fbSJames Wright     // *INDENT-ON*
2923a8779fbSJames Wright     // -- Grad-to-Grad q_data
2933a8779fbSJames Wright     // dU/dx
2943a8779fbSJames Wright     CeedScalar du[3][3] = {{0}};
2953a8779fbSJames Wright     CeedScalar drhodx[3] = {0};
2963a8779fbSJames Wright     CeedScalar dEdx[3] = {0};
2973a8779fbSJames Wright     CeedScalar dUdx[3][3] = {{0}};
2983a8779fbSJames Wright     CeedScalar dXdxdXdxT[3][3] = {{0}};
2993a8779fbSJames Wright     for (int j=0; j<3; j++) {
3003a8779fbSJames Wright       for (int k=0; k<3; k++) {
3013a8779fbSJames Wright         du[j][k] = (dU[j][k] - drho[k]*u[j]) / rho;
3023a8779fbSJames Wright         drhodx[j] += drho[k] * dXdx[k][j];
3033a8779fbSJames Wright         dEdx[j] += dE[k] * dXdx[k][j];
3043a8779fbSJames Wright         for (int l=0; l<3; l++) {
3053a8779fbSJames Wright           dUdx[j][k] += dU[j][l] * dXdx[l][k];
3063a8779fbSJames Wright           dXdxdXdxT[j][k] += dXdx[j][l]*dXdx[k][l];  //dXdx_j,k * dXdx_k,j
3073a8779fbSJames Wright         }
3083a8779fbSJames Wright       }
3093a8779fbSJames Wright     }
3103a8779fbSJames Wright     CeedScalar dudx[3][3] = {{0}};
3113a8779fbSJames Wright     for (int j=0; j<3; j++)
3123a8779fbSJames Wright       for (int k=0; k<3; k++)
3133a8779fbSJames Wright         for (int l=0; l<3; l++)
3143a8779fbSJames Wright           dudx[j][k] += du[j][l] * dXdx[l][k];
3153a8779fbSJames Wright     // -- grad_T
3163a8779fbSJames Wright     const CeedScalar grad_T[3]  = {(dEdx[0]/rho - E*drhodx[0]/(rho*rho) - /* *NOPAD* */
3173a8779fbSJames Wright                                     (u[0]*dudx[0][0] + u[1]*dudx[1][0] + u[2]*dudx[2][0]))/cv,
3183a8779fbSJames Wright                                    (dEdx[1]/rho - E*drhodx[1]/(rho*rho) - /* *NOPAD* */
3193a8779fbSJames Wright                                     (u[0]*dudx[0][1] + u[1]*dudx[1][1] + u[2]*dudx[2][1]))/cv,
3203a8779fbSJames Wright                                    (dEdx[2]/rho - E*drhodx[2]/(rho*rho) - /* *NOPAD* */
3213a8779fbSJames Wright                                     (u[0]*dudx[0][2] + u[1]*dudx[1][2] + u[2]*dudx[2][2]) - g)/cv
3223a8779fbSJames Wright                                   };
3233a8779fbSJames Wright 
3243a8779fbSJames Wright     // -- Fuvisc
3253a8779fbSJames Wright     // ---- Symmetric 3x3 matrix
3263a8779fbSJames Wright     const CeedScalar Fu[6]     =  {mu*(dudx[0][0] * (2 + lambda) + /* *NOPAD* */
3273a8779fbSJames Wright                                        lambda * (dudx[1][1] + dudx[2][2])),
3283a8779fbSJames Wright                                    mu*(dudx[0][1] + dudx[1][0]), /* *NOPAD* */
3293a8779fbSJames Wright                                    mu*(dudx[0][2] + dudx[2][0]), /* *NOPAD* */
3303a8779fbSJames Wright                                    mu*(dudx[1][1] * (2 + lambda) + /* *NOPAD* */
3313a8779fbSJames Wright                                        lambda * (dudx[0][0] + dudx[2][2])),
3323a8779fbSJames Wright                                    mu*(dudx[1][2] + dudx[2][1]), /* *NOPAD* */
3333a8779fbSJames Wright                                    mu*(dudx[2][2] * (2 + lambda) + /* *NOPAD* */
3343a8779fbSJames Wright                                        lambda * (dudx[0][0] + dudx[1][1]))
3353a8779fbSJames Wright                                   };
3363a8779fbSJames Wright     // -- Fevisc
3373a8779fbSJames Wright     const CeedScalar Fe[3]     =  {u[0]*Fu[0] + u[1]*Fu[1] + u[2]*Fu[2] + /* *NOPAD* */
3383a8779fbSJames Wright                                    k*grad_T[0], /* *NOPAD* */
3393a8779fbSJames Wright                                    u[0]*Fu[1] + u[1]*Fu[3] + u[2]*Fu[4] + /* *NOPAD* */
3403a8779fbSJames Wright                                    k*grad_T[1], /* *NOPAD* */
3413a8779fbSJames Wright                                    u[0]*Fu[2] + u[1]*Fu[4] + u[2]*Fu[5] + /* *NOPAD* */
3423a8779fbSJames Wright                                    k*grad_T[2] /* *NOPAD* */
3433a8779fbSJames Wright                                   };
3443a8779fbSJames Wright     // Pressure
3453a8779fbSJames Wright     const CeedScalar
3463a8779fbSJames Wright     E_kinetic   = 0.5 * rho * (u[0]*u[0] + u[1]*u[1] + u[2]*u[2]),
3473a8779fbSJames Wright     E_potential = rho*g*x[2][i],
3483a8779fbSJames Wright     E_internal  = E - E_kinetic - E_potential,
3493a8779fbSJames Wright     P           = E_internal * (gamma - 1.); // P = pressure
3503a8779fbSJames Wright 
3513a8779fbSJames Wright     // jacob_F_conv[3][5][5] = dF(convective)/dq at each direction
3523a8779fbSJames Wright     CeedScalar jacob_F_conv[3][5][5] = {{{0.}}};
3533a8779fbSJames Wright     computeFluxJacobian_NS(jacob_F_conv, rho, u, E, gamma, g, x[2][i]);
3543a8779fbSJames Wright 
3553a8779fbSJames Wright     // jacob_F_conv_T = jacob_F_conv^T
3563a8779fbSJames Wright     CeedScalar jacob_F_conv_T[3][5][5];
3573a8779fbSJames Wright     for (int j=0; j<3; j++)
3583a8779fbSJames Wright       for (int k=0; k<5; k++)
3593a8779fbSJames Wright         for (int l=0; l<5; l++)
3603a8779fbSJames Wright           jacob_F_conv_T[j][k][l] = jacob_F_conv[j][l][k];
3613a8779fbSJames Wright 
3623a8779fbSJames Wright     // dqdx collects drhodx, dUdx and dEdx in one vector
3633a8779fbSJames Wright     CeedScalar dqdx[5][3];
3643a8779fbSJames Wright     for (int j=0; j<3; j++) {
3653a8779fbSJames Wright       dqdx[0][j] = drhodx[j];
3663a8779fbSJames Wright       dqdx[4][j] = dEdx[j];
3673a8779fbSJames Wright       for (int k=0; k<3; k++)
3683a8779fbSJames Wright         dqdx[k+1][j] = dUdx[k][j];
3693a8779fbSJames Wright     }
3703a8779fbSJames Wright 
3713a8779fbSJames Wright     // strong_conv = dF/dq * dq/dx    (Strong convection)
3723a8779fbSJames Wright     CeedScalar strong_conv[5] = {0};
3733a8779fbSJames Wright     for (int j=0; j<3; j++)
3743a8779fbSJames Wright       for (int k=0; k<5; k++)
3753a8779fbSJames Wright         for (int l=0; l<5; l++)
3763a8779fbSJames Wright           strong_conv[k] += jacob_F_conv[j][k][l] * dqdx[l][j];
3773a8779fbSJames Wright 
3783a8779fbSJames Wright     // Body force
3793a8779fbSJames Wright     const CeedScalar body_force[5] = {0, 0, 0, -rho*g, 0};
3803a8779fbSJames Wright 
3813a8779fbSJames Wright     // The Physics
3823a8779fbSJames Wright     // Zero dv so all future terms can safely sum into it
3833a8779fbSJames Wright     for (int j=0; j<5; j++)
3843a8779fbSJames Wright       for (int k=0; k<3; k++)
3853a8779fbSJames Wright         dv[k][j][i] = 0;
3863a8779fbSJames Wright 
3873a8779fbSJames Wright     // -- Density
3883a8779fbSJames Wright     // ---- u rho
3893a8779fbSJames Wright     for (int j=0; j<3; j++)
3903a8779fbSJames Wright       dv[j][0][i]  += wdetJ*(rho*u[0]*dXdx[j][0] + rho*u[1]*dXdx[j][1] +
3913a8779fbSJames Wright                              rho*u[2]*dXdx[j][2]);
3923a8779fbSJames Wright     // -- Momentum
3933a8779fbSJames Wright     // ---- rho (u x u) + P I3
3943a8779fbSJames Wright     for (int j=0; j<3; j++)
3953a8779fbSJames Wright       for (int k=0; k<3; k++)
3963a8779fbSJames Wright         dv[k][j+1][i]  += wdetJ*((rho*u[j]*u[0] + (j==0?P:0))*dXdx[k][0] +
3973a8779fbSJames Wright                                  (rho*u[j]*u[1] + (j==1?P:0))*dXdx[k][1] +
3983a8779fbSJames Wright                                  (rho*u[j]*u[2] + (j==2?P:0))*dXdx[k][2]);
3993a8779fbSJames Wright     // ---- Fuvisc
4003a8779fbSJames Wright     const CeedInt Fuviscidx[3][3] = {{0, 1, 2}, {1, 3, 4}, {2, 4, 5}}; // symmetric matrix indices
4013a8779fbSJames Wright     for (int j=0; j<3; j++)
4023a8779fbSJames Wright       for (int k=0; k<3; k++)
4033a8779fbSJames Wright         dv[k][j+1][i] -= wdetJ*(Fu[Fuviscidx[j][0]]*dXdx[k][0] +
4043a8779fbSJames Wright                                 Fu[Fuviscidx[j][1]]*dXdx[k][1] +
4053a8779fbSJames Wright                                 Fu[Fuviscidx[j][2]]*dXdx[k][2]);
4063a8779fbSJames Wright     // -- Total Energy Density
4073a8779fbSJames Wright     // ---- (E + P) u
4083a8779fbSJames Wright     for (int j=0; j<3; j++)
4093a8779fbSJames Wright       dv[j][4][i]  += wdetJ * (E + P) * (u[0]*dXdx[j][0] + u[1]*dXdx[j][1] +
4103a8779fbSJames Wright                                          u[2]*dXdx[j][2]);
4113a8779fbSJames Wright     // ---- Fevisc
4123a8779fbSJames Wright     for (int j=0; j<3; j++)
4133a8779fbSJames Wright       dv[j][4][i] -= wdetJ * (Fe[0]*dXdx[j][0] + Fe[1]*dXdx[j][1] +
4143a8779fbSJames Wright                               Fe[2]*dXdx[j][2]);
4153a8779fbSJames Wright     // Body Force
4163a8779fbSJames Wright     for (int j=0; j<5; j++)
4173a8779fbSJames Wright       v[j][i] = wdetJ * body_force[j];
4183a8779fbSJames Wright 
4193a8779fbSJames Wright     // Stabilization
4203a8779fbSJames Wright     // -- Tau elements
4213a8779fbSJames Wright     const CeedScalar sound_speed = sqrt(gamma * P / rho);
4223a8779fbSJames Wright     CeedScalar Tau_x[3] = {0.};
4233a8779fbSJames Wright     Tau_spatial(Tau_x, dXdx, u, sound_speed, c_tau);
4243a8779fbSJames Wright 
4253a8779fbSJames Wright     // -- Stabilization method: none or SU
4263a8779fbSJames Wright     CeedScalar stab[5][3];
4273a8779fbSJames Wright     switch (context->stabilization) {
4283a8779fbSJames Wright     case STAB_NONE:        // Galerkin
4293a8779fbSJames Wright       break;
4303a8779fbSJames Wright     case STAB_SU:        // SU
4313a8779fbSJames Wright       for (int j=0; j<3; j++)
4323a8779fbSJames Wright         for (int k=0; k<5; k++)
4333a8779fbSJames Wright           for (int l=0; l<5; l++)
4343a8779fbSJames Wright             stab[k][j] = jacob_F_conv_T[j][k][l] * Tau_x[j] * strong_conv[l];
4353a8779fbSJames Wright 
4363a8779fbSJames Wright       for (int j=0; j<5; j++)
4373a8779fbSJames Wright         for (int k=0; k<3; k++)
4383a8779fbSJames Wright           dv[k][j][i] -= wdetJ*(stab[j][0] * dXdx[k][0] +
4393a8779fbSJames Wright                                 stab[j][1] * dXdx[k][1] +
4403a8779fbSJames Wright                                 stab[j][2] * dXdx[k][2]);
4413a8779fbSJames Wright       break;
4423a8779fbSJames Wright     case STAB_SUPG:        // SUPG is not implemented for explicit scheme
4433a8779fbSJames Wright       break;
4443a8779fbSJames Wright     }
4453a8779fbSJames Wright 
4463a8779fbSJames Wright   } // End Quadrature Point Loop
4473a8779fbSJames Wright 
4483a8779fbSJames Wright   // Return
4493a8779fbSJames Wright   return 0;
4503a8779fbSJames Wright }
4513a8779fbSJames Wright 
4523a8779fbSJames Wright // *****************************************************************************
4533a8779fbSJames Wright // This QFunction implements the Navier-Stokes equations (mentioned above) with
4543a8779fbSJames Wright //   implicit time stepping method
4553a8779fbSJames Wright //
4563a8779fbSJames Wright //  SU   = Galerkin + grad(v) . ( Ai^T * Tau * (Aj q,j) )
4573a8779fbSJames Wright //  SUPG = Galerkin + grad(v) . ( Ai^T * Tau * (q_dot + Aj q,j - body force) )
4583a8779fbSJames Wright //                                       (diffussive terms will be added later)
4593a8779fbSJames Wright //
4603a8779fbSJames Wright // *****************************************************************************
4613a8779fbSJames Wright CEED_QFUNCTION(IFunction_Newtonian)(void *ctx, CeedInt Q,
4623a8779fbSJames Wright                                     const CeedScalar *const *in,
4633a8779fbSJames Wright                                     CeedScalar *const *out) {
4643a8779fbSJames Wright   // *INDENT-OFF*
4653a8779fbSJames Wright   // Inputs
4663a8779fbSJames Wright   const CeedScalar (*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0],
4673a8779fbSJames Wright                    (*dq)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1],
4683a8779fbSJames Wright                    (*q_dot)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2],
4693a8779fbSJames Wright                    (*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3],
4703a8779fbSJames Wright                    (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4];
4713a8779fbSJames Wright   // Outputs
4723a8779fbSJames Wright   CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0],
4733a8779fbSJames Wright              (*dv)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1];
4743a8779fbSJames Wright   // *INDENT-ON*
4753a8779fbSJames Wright   // Context
4763a8779fbSJames Wright   NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx;
4773a8779fbSJames Wright   const CeedScalar lambda = context->lambda;
4783a8779fbSJames Wright   const CeedScalar mu     = context->mu;
4793a8779fbSJames Wright   const CeedScalar k      = context->k;
4803a8779fbSJames Wright   const CeedScalar cv     = context->cv;
4813a8779fbSJames Wright   const CeedScalar cp     = context->cp;
4823a8779fbSJames Wright   const CeedScalar g      = context->g;
4833a8779fbSJames Wright   const CeedScalar c_tau  = context->c_tau;
4843a8779fbSJames Wright   const CeedScalar gamma  = cp / cv;
4853a8779fbSJames Wright 
4863a8779fbSJames Wright   CeedPragmaSIMD
4873a8779fbSJames Wright   // Quadrature Point Loop
4883a8779fbSJames Wright   for (CeedInt i=0; i<Q; i++) {
4893a8779fbSJames Wright     // Setup
4903a8779fbSJames Wright     // -- Interp in
4913a8779fbSJames Wright     const CeedScalar rho        =   q[0][i];
4923a8779fbSJames Wright     const CeedScalar u[3]       =  {q[1][i] / rho,
4933a8779fbSJames Wright                                     q[2][i] / rho,
4943a8779fbSJames Wright                                     q[3][i] / rho
4953a8779fbSJames Wright                                    };
4963a8779fbSJames Wright     const CeedScalar E          =   q[4][i];
4973a8779fbSJames Wright     // -- Grad in
4983a8779fbSJames Wright     const CeedScalar drho[3]    =  {dq[0][0][i],
4993a8779fbSJames Wright                                     dq[1][0][i],
5003a8779fbSJames Wright                                     dq[2][0][i]
5013a8779fbSJames Wright                                    };
5023a8779fbSJames Wright     // *INDENT-OFF*
5033a8779fbSJames Wright     const CeedScalar dU[3][3]   = {{dq[0][1][i],
5043a8779fbSJames Wright                                     dq[1][1][i],
5053a8779fbSJames Wright                                     dq[2][1][i]},
5063a8779fbSJames Wright                                    {dq[0][2][i],
5073a8779fbSJames Wright                                     dq[1][2][i],
5083a8779fbSJames Wright                                     dq[2][2][i]},
5093a8779fbSJames Wright                                    {dq[0][3][i],
5103a8779fbSJames Wright                                     dq[1][3][i],
5113a8779fbSJames Wright                                     dq[2][3][i]}
5123a8779fbSJames Wright                                   };
5133a8779fbSJames Wright     // *INDENT-ON*
5143a8779fbSJames Wright     const CeedScalar dE[3]      =  {dq[0][4][i],
5153a8779fbSJames Wright                                     dq[1][4][i],
5163a8779fbSJames Wright                                     dq[2][4][i]
5173a8779fbSJames Wright                                    };
5183a8779fbSJames Wright     // -- Interp-to-Interp q_data
5193a8779fbSJames Wright     const CeedScalar wdetJ      =   q_data[0][i];
5203a8779fbSJames Wright     // -- Interp-to-Grad q_data
5213a8779fbSJames Wright     // ---- Inverse of change of coordinate matrix: X_i,j
5223a8779fbSJames Wright     // *INDENT-OFF*
5233a8779fbSJames Wright     const CeedScalar dXdx[3][3] = {{q_data[1][i],
5243a8779fbSJames Wright                                     q_data[2][i],
5253a8779fbSJames Wright                                     q_data[3][i]},
5263a8779fbSJames Wright                                    {q_data[4][i],
5273a8779fbSJames Wright                                     q_data[5][i],
5283a8779fbSJames Wright                                     q_data[6][i]},
5293a8779fbSJames Wright                                    {q_data[7][i],
5303a8779fbSJames Wright                                     q_data[8][i],
5313a8779fbSJames Wright                                     q_data[9][i]}
5323a8779fbSJames Wright                                   };
5333a8779fbSJames Wright     // *INDENT-ON*
5343a8779fbSJames Wright     // -- Grad-to-Grad q_data
5353a8779fbSJames Wright     // dU/dx
5363a8779fbSJames Wright     CeedScalar du[3][3] = {{0}};
5373a8779fbSJames Wright     CeedScalar drhodx[3] = {0};
5383a8779fbSJames Wright     CeedScalar dEdx[3] = {0};
5393a8779fbSJames Wright     CeedScalar dUdx[3][3] = {{0}};
5403a8779fbSJames Wright     CeedScalar dXdxdXdxT[3][3] = {{0}};
5413a8779fbSJames Wright     for (int j=0; j<3; j++) {
5423a8779fbSJames Wright       for (int k=0; k<3; k++) {
5433a8779fbSJames Wright         du[j][k] = (dU[j][k] - drho[k]*u[j]) / rho;
5443a8779fbSJames Wright         drhodx[j] += drho[k] * dXdx[k][j];
5453a8779fbSJames Wright         dEdx[j] += dE[k] * dXdx[k][j];
5463a8779fbSJames Wright         for (int l=0; l<3; l++) {
5473a8779fbSJames Wright           dUdx[j][k] += dU[j][l] * dXdx[l][k];
5483a8779fbSJames Wright           dXdxdXdxT[j][k] += dXdx[j][l]*dXdx[k][l];  //dXdx_j,k * dXdx_k,j
5493a8779fbSJames Wright         }
5503a8779fbSJames Wright       }
5513a8779fbSJames Wright     }
5523a8779fbSJames Wright     CeedScalar dudx[3][3] = {{0}};
5533a8779fbSJames Wright     for (int j=0; j<3; j++)
5543a8779fbSJames Wright       for (int k=0; k<3; k++)
5553a8779fbSJames Wright         for (int l=0; l<3; l++)
5563a8779fbSJames Wright           dudx[j][k] += du[j][l] * dXdx[l][k];
5573a8779fbSJames Wright     // -- grad_T
5583a8779fbSJames Wright     const CeedScalar grad_T[3]  = {(dEdx[0]/rho - E*drhodx[0]/(rho*rho) - /* *NOPAD* */
5593a8779fbSJames Wright                                     (u[0]*dudx[0][0] + u[1]*dudx[1][0] + u[2]*dudx[2][0]))/cv,
5603a8779fbSJames Wright                                    (dEdx[1]/rho - E*drhodx[1]/(rho*rho) - /* *NOPAD* */
5613a8779fbSJames Wright                                     (u[0]*dudx[0][1] + u[1]*dudx[1][1] + u[2]*dudx[2][1]))/cv,
5623a8779fbSJames Wright                                    (dEdx[2]/rho - E*drhodx[2]/(rho*rho) - /* *NOPAD* */
5633a8779fbSJames Wright                                     (u[0]*dudx[0][2] + u[1]*dudx[1][2] + u[2]*dudx[2][2]) - g)/cv
5643a8779fbSJames Wright                                   };
5653a8779fbSJames Wright     // -- Fuvisc
5663a8779fbSJames Wright     // ---- Symmetric 3x3 matrix
5673a8779fbSJames Wright     const CeedScalar Fu[6]     =  {mu*(dudx[0][0] * (2 + lambda) + /* *NOPAD* */
5683a8779fbSJames Wright                                        lambda * (dudx[1][1] + dudx[2][2])),
5693a8779fbSJames Wright                                    mu*(dudx[0][1] + dudx[1][0]), /* *NOPAD* */
5703a8779fbSJames Wright                                    mu*(dudx[0][2] + dudx[2][0]), /* *NOPAD* */
5713a8779fbSJames Wright                                    mu*(dudx[1][1] * (2 + lambda) + /* *NOPAD* */
5723a8779fbSJames Wright                                        lambda * (dudx[0][0] + dudx[2][2])),
5733a8779fbSJames Wright                                    mu*(dudx[1][2] + dudx[2][1]), /* *NOPAD* */
5743a8779fbSJames Wright                                    mu*(dudx[2][2] * (2 + lambda) + /* *NOPAD* */
5753a8779fbSJames Wright                                        lambda * (dudx[0][0] + dudx[1][1]))
5763a8779fbSJames Wright                                   };
5773a8779fbSJames Wright     // -- Fevisc
5783a8779fbSJames Wright     const CeedScalar Fe[3]     =  {u[0]*Fu[0] + u[1]*Fu[1] + u[2]*Fu[2] + /* *NOPAD* */
5793a8779fbSJames Wright                                    k*grad_T[0], /* *NOPAD* */
5803a8779fbSJames Wright                                    u[0]*Fu[1] + u[1]*Fu[3] + u[2]*Fu[4] + /* *NOPAD* */
5813a8779fbSJames Wright                                    k*grad_T[1], /* *NOPAD* */
5823a8779fbSJames Wright                                    u[0]*Fu[2] + u[1]*Fu[4] + u[2]*Fu[5] + /* *NOPAD* */
5833a8779fbSJames Wright                                    k*grad_T[2] /* *NOPAD* */
5843a8779fbSJames Wright                                   };
5853a8779fbSJames Wright     // Pressure
5863a8779fbSJames Wright     const CeedScalar
5873a8779fbSJames Wright     E_kinetic   = 0.5 * rho * (u[0]*u[0] + u[1]*u[1] + u[2]*u[2]),
5883a8779fbSJames Wright     E_potential = rho*g*x[2][i],
5893a8779fbSJames Wright     E_internal  = E - E_kinetic - E_potential,
5903a8779fbSJames Wright     P           = E_internal * (gamma - 1.); // P = pressure
5913a8779fbSJames Wright 
5923a8779fbSJames Wright     // jacob_F_conv[3][5][5] = dF(convective)/dq at each direction
5933a8779fbSJames Wright     CeedScalar jacob_F_conv[3][5][5] = {{{0.}}};
5943a8779fbSJames Wright     computeFluxJacobian_NS(jacob_F_conv, rho, u, E, gamma, g, x[2][i]);
5953a8779fbSJames Wright 
5963a8779fbSJames Wright     // jacob_F_conv_T = jacob_F_conv^T
5973a8779fbSJames Wright     CeedScalar jacob_F_conv_T[3][5][5];
5983a8779fbSJames Wright     for (int j=0; j<3; j++)
5993a8779fbSJames Wright       for (int k=0; k<5; k++)
6003a8779fbSJames Wright         for (int l=0; l<5; l++)
6013a8779fbSJames Wright           jacob_F_conv_T[j][k][l] = jacob_F_conv[j][l][k];
6023a8779fbSJames Wright     // dqdx collects drhodx, dUdx and dEdx in one vector
6033a8779fbSJames Wright     CeedScalar dqdx[5][3];
6043a8779fbSJames Wright     for (int j=0; j<3; j++) {
6053a8779fbSJames Wright       dqdx[0][j] = drhodx[j];
6063a8779fbSJames Wright       dqdx[4][j] = dEdx[j];
6073a8779fbSJames Wright       for (int k=0; k<3; k++)
6083a8779fbSJames Wright         dqdx[k+1][j] = dUdx[k][j];
6093a8779fbSJames Wright     }
6103a8779fbSJames Wright     // strong_conv = dF/dq * dq/dx    (Strong convection)
6113a8779fbSJames Wright     CeedScalar strong_conv[5] = {0};
6123a8779fbSJames Wright     for (int j=0; j<3; j++)
6133a8779fbSJames Wright       for (int k=0; k<5; k++)
6143a8779fbSJames Wright         for (int l=0; l<5; l++)
6153a8779fbSJames Wright           strong_conv[k] += jacob_F_conv[j][k][l] * dqdx[l][j];
6163a8779fbSJames Wright 
6173a8779fbSJames Wright     // Body force
6183a8779fbSJames Wright     const CeedScalar body_force[5] = {0, 0, 0, -rho*g, 0};
6193a8779fbSJames Wright 
6203a8779fbSJames Wright     // Strong residual
6213a8779fbSJames Wright     CeedScalar strong_res[5];
6223a8779fbSJames Wright     for (int j=0; j<5; j++)
6233a8779fbSJames Wright       strong_res[j] = q_dot[j][i] + strong_conv[j] - body_force[j];
6243a8779fbSJames Wright 
6253a8779fbSJames Wright     // The Physics
6263a8779fbSJames Wright     //-----mass matrix
6273a8779fbSJames Wright     for (int j=0; j<5; j++)
6283a8779fbSJames Wright       v[j][i] = wdetJ*q_dot[j][i];
6293a8779fbSJames Wright 
6303a8779fbSJames Wright     // Zero dv so all future terms can safely sum into it
6313a8779fbSJames Wright     for (int j=0; j<5; j++)
6323a8779fbSJames Wright       for (int k=0; k<3; k++)
6333a8779fbSJames Wright         dv[k][j][i] = 0;
6343a8779fbSJames Wright 
6353a8779fbSJames Wright     // -- Density
6363a8779fbSJames Wright     // ---- u rho
6373a8779fbSJames Wright     for (int j=0; j<3; j++)
6383a8779fbSJames Wright       dv[j][0][i]  -= wdetJ*(rho*u[0]*dXdx[j][0] + rho*u[1]*dXdx[j][1] +
6393a8779fbSJames Wright                              rho*u[2]*dXdx[j][2]);
6403a8779fbSJames Wright     // -- Momentum
6413a8779fbSJames Wright     // ---- rho (u x u) + P I3
6423a8779fbSJames Wright     for (int j=0; j<3; j++)
6433a8779fbSJames Wright       for (int k=0; k<3; k++)
6443a8779fbSJames Wright         dv[k][j+1][i]  -= wdetJ*((rho*u[j]*u[0] + (j==0?P:0))*dXdx[k][0] +
6453a8779fbSJames Wright                                  (rho*u[j]*u[1] + (j==1?P:0))*dXdx[k][1] +
6463a8779fbSJames Wright                                  (rho*u[j]*u[2] + (j==2?P:0))*dXdx[k][2]);
6473a8779fbSJames Wright     // ---- Fuvisc
6483a8779fbSJames Wright     const CeedInt Fuviscidx[3][3] = {{0, 1, 2}, {1, 3, 4}, {2, 4, 5}}; // symmetric matrix indices
6493a8779fbSJames Wright     for (int j=0; j<3; j++)
6503a8779fbSJames Wright       for (int k=0; k<3; k++)
6513a8779fbSJames Wright         dv[k][j+1][i] += wdetJ*(Fu[Fuviscidx[j][0]]*dXdx[k][0] +
6523a8779fbSJames Wright                                 Fu[Fuviscidx[j][1]]*dXdx[k][1] +
6533a8779fbSJames Wright                                 Fu[Fuviscidx[j][2]]*dXdx[k][2]);
6543a8779fbSJames Wright     // -- Total Energy Density
6553a8779fbSJames Wright     // ---- (E + P) u
6563a8779fbSJames Wright     for (int j=0; j<3; j++)
6573a8779fbSJames Wright       dv[j][4][i]  -= wdetJ * (E + P) * (u[0]*dXdx[j][0] + u[1]*dXdx[j][1] +
6583a8779fbSJames Wright                                          u[2]*dXdx[j][2]);
6593a8779fbSJames Wright     // ---- Fevisc
6603a8779fbSJames Wright     for (int j=0; j<3; j++)
6613a8779fbSJames Wright       dv[j][4][i] += wdetJ * (Fe[0]*dXdx[j][0] + Fe[1]*dXdx[j][1] +
6623a8779fbSJames Wright                               Fe[2]*dXdx[j][2]);
6633a8779fbSJames Wright     // Body Force
6643a8779fbSJames Wright     for (int j=0; j<5; j++)
6653a8779fbSJames Wright       v[j][i] -= wdetJ*body_force[j];
6663a8779fbSJames Wright 
6673a8779fbSJames Wright     // Stabilization
6683a8779fbSJames Wright     // -- Tau elements
6693a8779fbSJames Wright     const CeedScalar sound_speed = sqrt(gamma * P / rho);
6703a8779fbSJames Wright     CeedScalar Tau_x[3] = {0.};
6713a8779fbSJames Wright     Tau_spatial(Tau_x, dXdx, u, sound_speed, c_tau);
6723a8779fbSJames Wright 
6733a8779fbSJames Wright     // -- Stabilization method: none, SU, or SUPG
6743a8779fbSJames Wright     CeedScalar stab[5][3];
6753a8779fbSJames Wright     switch (context->stabilization) {
6763a8779fbSJames Wright     case STAB_NONE:        // Galerkin
6773a8779fbSJames Wright       break;
6783a8779fbSJames Wright     case STAB_SU:        // SU
6793a8779fbSJames Wright       for (int j=0; j<3; j++)
6803a8779fbSJames Wright         for (int k=0; k<5; k++)
6813a8779fbSJames Wright           for (int l=0; l<5; l++)
6823a8779fbSJames Wright             stab[k][j] = jacob_F_conv_T[j][k][l] * Tau_x[j] * strong_conv[l];
6833a8779fbSJames Wright 
6843a8779fbSJames Wright       for (int j=0; j<5; j++)
6853a8779fbSJames Wright         for (int k=0; k<3; k++)
6863a8779fbSJames Wright           dv[k][j][i] += wdetJ*(stab[j][0] * dXdx[k][0] +
6873a8779fbSJames Wright                                 stab[j][1] * dXdx[k][1] +
6883a8779fbSJames Wright                                 stab[j][2] * dXdx[k][2]);
6893a8779fbSJames Wright       break;
6903a8779fbSJames Wright     case STAB_SUPG:        // SUPG
6913a8779fbSJames Wright       for (int j=0; j<3; j++)
6923a8779fbSJames Wright         for (int k=0; k<5; k++)
6933a8779fbSJames Wright           for (int l=0; l<5; l++)
6943a8779fbSJames Wright             stab[k][j] = jacob_F_conv_T[j][k][l] * Tau_x[j] * strong_res[l];
6953a8779fbSJames Wright 
6963a8779fbSJames Wright       for (int j=0; j<5; j++)
6973a8779fbSJames Wright         for (int k=0; k<3; k++)
6983a8779fbSJames Wright           dv[k][j][i] += wdetJ*(stab[j][0] * dXdx[k][0] +
6993a8779fbSJames Wright                                 stab[j][1] * dXdx[k][1] +
7003a8779fbSJames Wright                                 stab[j][2] * dXdx[k][2]);
7013a8779fbSJames Wright       break;
7023a8779fbSJames Wright     }
7033a8779fbSJames Wright 
7043a8779fbSJames Wright   } // End Quadrature Point Loop
7053a8779fbSJames Wright 
7063a8779fbSJames Wright   // Return
7073a8779fbSJames Wright   return 0;
7083a8779fbSJames Wright }
7093a8779fbSJames Wright // *****************************************************************************
7103a8779fbSJames Wright #endif // newtonian_h
711