xref: /honee/qfunctions/newtonian.h (revision 3a8779fb8e72401b674c72ccc39afb69a615a91a)
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