xref: /honee/qfunctions/newtonian.h (revision 7ecf6641c340caefd7fa9f7fc7a6efebf89ae19d)
1ae2b091fSJames Wright // SPDX-FileCopyrightText: Copyright (c) 2017-2024, HONEE contributors.
2ae2b091fSJames Wright // SPDX-License-Identifier: Apache-2.0 OR BSD-2-Clause
33a8779fbSJames Wright 
43a8779fbSJames Wright /// @file
5ea615d4cSJames Wright /// Newtonian fluids operator for HONEE
63e17a7a1SJames Wright #include <ceed/types.h>
72b916ea7SJeremy L Thompson 
8475b2820SJames Wright #include "newtonian_state.h"
9d0cce58aSJeremy L Thompson #include "newtonian_types.h"
10d1b9ef12SLeila Ghaffari #include "stabilization.h"
11d0cce58aSJeremy L Thompson #include "utils.h"
12bb8a0c61SJames Wright 
13bb8a0c61SJames Wright // *****************************************************************************
143a8779fbSJames Wright // This QFunction sets a "still" initial condition for generic Newtonian IG problems
153a8779fbSJames Wright // *****************************************************************************
ICsNewtonianIG(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out,StateVariable state_var)168fff8293SJames Wright CEED_QFUNCTION_HELPER int ICsNewtonianIG(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateVariable state_var) {
173a8779fbSJames Wright   CeedScalar(*q0)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0];
183a8779fbSJames Wright 
19bb8a0c61SJames Wright   const SetupContext    context = (SetupContext)ctx;
20*cde3d787SJames Wright   NewtonianIGProperties gas     = context->newt_ctx.gas;
21bb8a0c61SJames Wright 
222b916ea7SJeremy L Thompson   CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) {
23a541e550SJames Wright     CeedScalar q[5];
24*cde3d787SJames Wright     State      s = StateFromPrimitive(gas, context->reference);
25*cde3d787SJames Wright     StateToQ(gas, s, q, state_var);
262b916ea7SJeremy L Thompson     for (CeedInt j = 0; j < 5; j++) q0[j][i] = q[j];
27b193fadcSJames Wright   }
283a8779fbSJames Wright   return 0;
293a8779fbSJames Wright }
303a8779fbSJames Wright 
ICsNewtonianIG_Conserv(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)319b103f75SJames Wright CEED_QFUNCTION(ICsNewtonianIG_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
329b103f75SJames Wright   return ICsNewtonianIG(ctx, Q, in, out, STATEVAR_CONSERVATIVE);
339b103f75SJames Wright }
349b103f75SJames Wright 
ICsNewtonianIG_Prim(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)352b916ea7SJeremy L Thompson CEED_QFUNCTION(ICsNewtonianIG_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
368fff8293SJames Wright   return ICsNewtonianIG(ctx, Q, in, out, STATEVAR_PRIMITIVE);
37b8fb7609SAdeleke O. Bankole }
389b103f75SJames Wright 
ICsNewtonianIG_Entropy(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)399b103f75SJames Wright CEED_QFUNCTION(ICsNewtonianIG_Entropy)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
409b103f75SJames Wright   return ICsNewtonianIG(ctx, Q, in, out, STATEVAR_ENTROPY);
41cbe60e31SLeila Ghaffari }
42cbe60e31SLeila Ghaffari 
MassFunction_Newtonian(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out,StateVariable state_var)4397cfd714SJames Wright CEED_QFUNCTION_HELPER int MassFunction_Newtonian(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateVariable state_var) {
4465dee3d2SJames Wright   const CeedScalar(*q_dot)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0];
4565dee3d2SJames Wright   const CeedScalar(*q)[CEED_Q_VLA]     = (const CeedScalar(*)[CEED_Q_VLA])in[1];
4665dee3d2SJames Wright   const CeedScalar(*q_data)            = in[2];
4765dee3d2SJames Wright   CeedScalar(*v)[CEED_Q_VLA]           = (CeedScalar(*)[CEED_Q_VLA])out[0];
4865dee3d2SJames Wright   CeedScalar(*Grad_v)[5][CEED_Q_VLA]   = (CeedScalar(*)[5][CEED_Q_VLA])out[1];
4965dee3d2SJames Wright 
5065dee3d2SJames Wright   NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx;
51*cde3d787SJames Wright   NewtonianIGProperties    gas     = context->gas;
5265dee3d2SJames Wright 
5365dee3d2SJames Wright   CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) {
5465dee3d2SJames Wright     const CeedScalar qi[5]     = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]};
5565dee3d2SJames Wright     const CeedScalar qi_dot[5] = {q_dot[0][i], q_dot[1][i], q_dot[2][i], q_dot[3][i], q_dot[4][i]};
56*cde3d787SJames Wright     const State      s         = StateFromQ(gas, qi, state_var);
57*cde3d787SJames Wright     const State      s_dot     = StateFromQ(gas, qi_dot, state_var);
5865dee3d2SJames Wright     CeedScalar       wdetJ, dXdx[3][3];
5965dee3d2SJames Wright     QdataUnpack_3D(Q, i, q_data, &wdetJ, dXdx);
6065dee3d2SJames Wright 
6165dee3d2SJames Wright     // Standard mass matrix term
6265dee3d2SJames Wright     for (CeedInt f = 0; f < 5; f++) {
6365dee3d2SJames Wright       v[f][i] = wdetJ * qi_dot[f];
6465dee3d2SJames Wright     }
6565dee3d2SJames Wright 
6665dee3d2SJames Wright     // Stabilization method: none (Galerkin), SU, or SUPG
6765dee3d2SJames Wright     State      grad_s[3] = {{{0.}}};
688c85b835SJames Wright     CeedScalar Tau_d[3], stab[5][3], body_force[5] = {0.}, divFdiff[5] = {0.}, U_dot[5];
6965dee3d2SJames Wright     UnpackState_U(s_dot.U, U_dot);
70*cde3d787SJames Wright     Tau_diagPrim(context->tau_coeffs, gas, s, dXdx, context->dt, Tau_d);
71*cde3d787SJames Wright     Stabilization(context->stabilization, gas, s, Tau_d, grad_s, U_dot, body_force, divFdiff, stab);
7265dee3d2SJames Wright 
7365dee3d2SJames Wright     // Stabilized mass term
7465dee3d2SJames Wright     for (CeedInt j = 0; j < 5; j++) {
7565dee3d2SJames Wright       for (CeedInt k = 0; k < 3; k++) {
7665dee3d2SJames Wright         Grad_v[k][j][i] = wdetJ * (stab[j][0] * dXdx[k][0] + stab[j][1] * dXdx[k][1] + stab[j][2] * dXdx[k][2]);
7765dee3d2SJames Wright       }
7865dee3d2SJames Wright     }
7965dee3d2SJames Wright   }
8097cfd714SJames Wright   return 0;
8165dee3d2SJames Wright }
8265dee3d2SJames Wright 
MassFunction_Newtonian_Conserv(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)8365dee3d2SJames Wright CEED_QFUNCTION(MassFunction_Newtonian_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
8497cfd714SJames Wright   return MassFunction_Newtonian(ctx, Q, in, out, STATEVAR_CONSERVATIVE);
8565dee3d2SJames Wright }
8665dee3d2SJames Wright 
87e57b52dbSJames Wright // @brief Computes the residual created by IDL
InternalDampingLayer_Residual(const NewtonianIGProperties gas,const State s,const CeedScalar sigma,CeedScalar damp_Y[5],CeedScalar damp_residual[5])88*cde3d787SJames Wright CEED_QFUNCTION_HELPER void InternalDampingLayer_Residual(const NewtonianIGProperties gas, const State s, const CeedScalar sigma, CeedScalar damp_Y[5],
89*cde3d787SJames Wright                                                          CeedScalar damp_residual[5]) {
9030b5892fSJames Wright   ScaleN(damp_Y, sigma, 5);
91*cde3d787SJames Wright   State damp_s = StateFromY_fwd(gas, s, damp_Y);
9230b5892fSJames Wright 
9330b5892fSJames Wright   CeedScalar U[5];
9430b5892fSJames Wright   UnpackState_U(damp_s.U, U);
9530b5892fSJames Wright   for (int i = 0; i < 5; i++) damp_residual[i] += U[i];
9630b5892fSJames Wright }
9730b5892fSJames Wright 
98e57b52dbSJames Wright /**
99e57b52dbSJames Wright   @brief IFunction integrand for Internal Damping Layer
100e57b52dbSJames Wright 
101e57b52dbSJames Wright   `location` refers to whatever scalar distance is desired for IDL to ramp from.
102e57b52dbSJames Wright   See `LinearRampCoefficient()` for details on the `amplitude`, `length`, `start`, and `location` arguments.
103e57b52dbSJames Wright 
104e57b52dbSJames Wright   @param[in]    s         Solution `State`
105*cde3d787SJames Wright   @param[in]    gas       Newtonian ideal gas properties
106e57b52dbSJames Wright   @param[in]    amplitude Amplitude of the IDL ramp
107e57b52dbSJames Wright   @param[in]    length    Length of the IDL ramp
108e57b52dbSJames Wright   @param[in]    start     Start of the IDL ramp
109e57b52dbSJames Wright   @param[in]    location  Quadrature point location (relative to IDL ramp specification)
110e57b52dbSJames Wright   @param[in]    pressure  Pressure used to damp to
111e57b52dbSJames Wright   @param[inout] v_i       Output to be multiplied by weight function, summed into
112e57b52dbSJames Wright   @param[out]   sigma     IDL ramp coefficient
113e57b52dbSJames Wright **/
InternalDampingLayer_IFunction_Integrand(const State s,const NewtonianIGProperties gas,CeedScalar amplitude,CeedScalar length,CeedScalar start,CeedScalar location,CeedScalar pressure,CeedScalar v_i[5],CeedScalar * sigma)114*cde3d787SJames Wright CEED_QFUNCTION_HELPER void InternalDampingLayer_IFunction_Integrand(const State s, const NewtonianIGProperties gas, CeedScalar amplitude,
11530b5892fSJames Wright                                                                     CeedScalar length, CeedScalar start, CeedScalar location, CeedScalar pressure,
11630b5892fSJames Wright                                                                     CeedScalar v_i[5], CeedScalar *sigma) {
11730b5892fSJames Wright   const CeedScalar sigma_        = LinearRampCoefficient(amplitude, length, start, location);
11830b5892fSJames Wright   CeedScalar       damp_state[5] = {s.Y.pressure - pressure, 0, 0, 0, 0}, idl_residual[5] = {0.};
119*cde3d787SJames Wright   InternalDampingLayer_Residual(gas, s, sigma_, damp_state, idl_residual);
12030b5892fSJames Wright   AXPY(1, idl_residual, v_i, 5);
12130b5892fSJames Wright   *sigma = sigma_;
12230b5892fSJames Wright }
12330b5892fSJames Wright 
1248fd72709SJames Wright /**
1258fd72709SJames Wright   @brief IJacobian integrand for Internal Damping Layer
1268fd72709SJames Wright 
1278fd72709SJames Wright   @note This uses a Picard-type linearization of the damping and could be replaced by an `InternalDampingLayer_fwd` that uses s and ds.
1288fd72709SJames Wright 
1298fd72709SJames Wright   @param[in]    s         Solution `State`
1308fd72709SJames Wright   @param[in]    ds        Change in `State` of solution
131*cde3d787SJames Wright   @param[in]    gas       Newtonian ideal gas properties
1328fd72709SJames Wright   @param[in]    sigma     IDL ramp coefficient
1338fd72709SJames Wright   @param[inout] v_i       Output to be multiplied by weight function, summed into
1348fd72709SJames Wright **/
InternalDampingLayer_IJacobian_Integrand(const State s,const State ds,const NewtonianIGProperties gas,CeedScalar sigma,CeedScalar v_i[5])135*cde3d787SJames Wright CEED_QFUNCTION_HELPER void InternalDampingLayer_IJacobian_Integrand(const State s, const State ds, const NewtonianIGProperties gas, CeedScalar sigma,
136*cde3d787SJames Wright                                                                     CeedScalar v_i[5]) {
1378fd72709SJames Wright   CeedScalar damp_state[5] = {ds.Y.pressure, 0, 0, 0, 0}, idl_residual[5] = {0.};
138*cde3d787SJames Wright   InternalDampingLayer_Residual(gas, s, sigma, damp_state, idl_residual);
1398fd72709SJames Wright   AXPY(1, idl_residual, v_i, 5);
1408fd72709SJames Wright }
1418fd72709SJames Wright 
142cbe60e31SLeila Ghaffari // *****************************************************************************
14304e40bb6SJeremy L Thompson // This QFunction implements the following formulation of Navier-Stokes with explicit time stepping method
1443a8779fbSJames Wright //
14504e40bb6SJeremy L Thompson // This is 3D compressible Navier-Stokes in conservation form with state variables of density, momentum density, and total energy density.
1463a8779fbSJames Wright //
1473a8779fbSJames Wright // State Variables: q = ( rho, U1, U2, U3, E )
1483a8779fbSJames Wright //   rho - Mass Density
1493a8779fbSJames Wright //   Ui  - Momentum Density,      Ui = rho ui
1503a8779fbSJames Wright //   E   - Total Energy Density,  E  = rho (cv T + (u u)/2 + g z)
1513a8779fbSJames Wright //
1523a8779fbSJames Wright // Navier-Stokes Equations:
1533a8779fbSJames Wright //   drho/dt + div( U )                               = 0
1543a8779fbSJames Wright //   dU/dt   + div( rho (u x u) + P I3 ) + rho g khat = div( Fu )
1553a8779fbSJames Wright //   dE/dt   + div( (E + P) u )                       = div( Fe )
1563a8779fbSJames Wright //
1573a8779fbSJames Wright // Viscous Stress:
1583a8779fbSJames Wright //   Fu = mu (grad( u ) + grad( u )^T + lambda div ( u ) I3)
1593a8779fbSJames Wright //
1603a8779fbSJames Wright // Thermal Stress:
1613a8779fbSJames Wright //   Fe = u Fu + k grad( T )
162bb8a0c61SJames Wright // Equation of State
1633a8779fbSJames Wright //   P = (gamma - 1) (E - rho (u u) / 2 - rho g z)
1643a8779fbSJames Wright //
1653a8779fbSJames Wright // Stabilization:
1663a8779fbSJames Wright //   Tau = diag(TauC, TauM, TauM, TauM, TauE)
1673a8779fbSJames Wright //     f1 = rho  sqrt(ui uj gij)
1683a8779fbSJames Wright //     gij = dXi/dX * dXi/dX
1693a8779fbSJames Wright //     TauC = Cc f1 / (8 gii)
1703a8779fbSJames Wright //     TauM = min( 1 , 1 / f1 )
1713a8779fbSJames Wright //     TauE = TauM / (Ce cv)
1723a8779fbSJames Wright //
1733a8779fbSJames Wright //  SU   = Galerkin + grad(v) . ( Ai^T * Tau * (Aj q,j) )
1743a8779fbSJames Wright //
1753a8779fbSJames Wright // Constants:
1763a8779fbSJames Wright //   lambda = - 2 / 3,  From Stokes hypothesis
1773a8779fbSJames Wright //   mu              ,  Dynamic viscosity
1783a8779fbSJames Wright //   k               ,  Thermal conductivity
1793a8779fbSJames Wright //   cv              ,  Specific heat, constant volume
1803a8779fbSJames Wright //   cp              ,  Specific heat, constant pressure
1813a8779fbSJames Wright //   g               ,  Gravity
1823a8779fbSJames Wright //   gamma  = cp / cv,  Specific heat ratio
1833a8779fbSJames Wright //
18404e40bb6SJeremy L Thompson // We require the product of the inverse of the Jacobian (dXdx_j,k) and its transpose (dXdx_k,j) to properly compute integrals of the form: int( gradv
18504e40bb6SJeremy L Thompson // gradu )
1863a8779fbSJames Wright // *****************************************************************************
RHSFunction_Newtonian(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)1872b916ea7SJeremy L Thompson CEED_QFUNCTION(RHSFunction_Newtonian)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
188b3b24828SJames Wright   NewtonianIdealGasContext context      = (NewtonianIdealGasContext)ctx;
189b3b24828SJames Wright   const bool               use_divFdiff = context->divFdiff_method != DIV_DIFF_FLUX_PROJ_NONE;
190b3b24828SJames Wright 
1913d65b166SJames Wright   const CeedScalar(*q)[CEED_Q_VLA]        = (const CeedScalar(*)[CEED_Q_VLA])in[0];
19287bd45e7SJames Wright   const CeedScalar(*Grad_q)               = in[1];
193ade49511SJames Wright   const CeedScalar(*q_data)               = in[2];
1940a32a5aaSJames Wright   const CeedScalar(*x)[CEED_Q_VLA]        = (const CeedScalar(*)[CEED_Q_VLA])in[3];
195b3b24828SJames Wright   const CeedScalar(*divFdiff)[CEED_Q_VLA] = use_divFdiff ? (const CeedScalar(*)[CEED_Q_VLA])in[4] : NULL;
1963d65b166SJames Wright   CeedScalar(*v)[CEED_Q_VLA]              = (CeedScalar(*)[CEED_Q_VLA])out[0];
1973d65b166SJames Wright   CeedScalar(*Grad_v)[5][CEED_Q_VLA]      = (CeedScalar(*)[5][CEED_Q_VLA])out[1];
1983a8779fbSJames Wright 
199bb8a0c61SJames Wright   const CeedScalar           *g   = context->g;
200bb8a0c61SJames Wright   const CeedScalar            dt  = context->dt;
201*cde3d787SJames Wright   const NewtonianIGProperties gas = context->gas;
2023a8779fbSJames Wright 
2033d65b166SJames Wright   CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) {
204ade49511SJames Wright     CeedScalar       U[5], wdetJ, dXdx[3][3];
2050a32a5aaSJames Wright     const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]};
206c1a52365SJed Brown     for (int j = 0; j < 5; j++) U[j] = q[j][i];
2071be49596SJames Wright     QdataUnpack_3D(Q, i, q_data, &wdetJ, dXdx);
208*cde3d787SJames Wright     State s = StateFromU(gas, U);
209c1a52365SJed Brown 
210c1a52365SJed Brown     State grad_s[3];
211*cde3d787SJames Wright     StatePhysicalGradientFromReference(Q, i, gas, s, STATEVAR_CONSERVATIVE, Grad_q, dXdx, grad_s);
212c1a52365SJed Brown 
213c1a52365SJed Brown     CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3];
21440a33f2dSJames Wright     KMStrainRate_State(grad_s, strain_rate);
215*cde3d787SJames Wright     NewtonianStress(gas, strain_rate, kmstress);
216c1a52365SJed Brown     KMUnpack(kmstress, stress);
217*cde3d787SJames Wright     ViscousEnergyFlux(gas, s.Y, grad_s, stress, Fe);
218c1a52365SJed Brown 
219c1a52365SJed Brown     StateConservative F_inviscid[3];
220*cde3d787SJames Wright     FluxInviscid(gas, s, F_inviscid);
221c1a52365SJed Brown 
222c1a52365SJed Brown     // Total flux
223c1a52365SJed Brown     CeedScalar Flux[5][3];
224d1b9ef12SLeila Ghaffari     FluxTotal(F_inviscid, stress, Fe, Flux);
225c1a52365SJed Brown 
2267523f6aaSJames Wright     for (CeedInt j = 0; j < 5; j++) {
2277523f6aaSJames Wright       for (CeedInt k = 0; k < 3; k++) Grad_v[k][j][i] = wdetJ * (dXdx[k][0] * Flux[j][0] + dXdx[k][1] * Flux[j][1] + dXdx[k][2] * Flux[j][2]);
2282b916ea7SJeremy L Thompson     }
229c1a52365SJed Brown 
23060dbb574SKenneth E. Jansen     const CeedScalar body_force[5] = {0, s.U.density * g[0], s.U.density * g[1], s.U.density * g[2], Dot3(s.U.momentum, g)};
2312b916ea7SJeremy L Thompson     for (int j = 0; j < 5; j++) v[j][i] = wdetJ * body_force[j];
2323a8779fbSJames Wright 
2330a32a5aaSJames Wright     if (context->idl_enable) {
234*cde3d787SJames Wright       const CeedScalar idl_pressure  = context->idl_pressure;
2350a32a5aaSJames Wright       const CeedScalar sigma         = LinearRampCoefficient(context->idl_amplitude, context->idl_length, context->idl_start, x_i[0]);
236b3b24828SJames Wright       CeedScalar       damp_state[5] = {s.Y.pressure - idl_pressure, 0, 0, 0, 0}, idl_residual[5] = {0.};
237*cde3d787SJames Wright       InternalDampingLayer_Residual(gas, s, sigma, damp_state, idl_residual);
2380a32a5aaSJames Wright       for (int j = 0; j < 5; j++) v[j][i] -= wdetJ * idl_residual[j];
2390a32a5aaSJames Wright     }
2400a32a5aaSJames Wright 
241b3b24828SJames Wright     CeedScalar divFdiff_i[5] = {0.};
242b3b24828SJames Wright     if (use_divFdiff)
243b3b24828SJames Wright       for (int j = 1; j < 5; j++) divFdiff_i[j] = divFdiff[j - 1][i];
244b3b24828SJames Wright 
245d1b9ef12SLeila Ghaffari     // -- Stabilization method: none (Galerkin), SU, or SUPG
246b3b24828SJames Wright     CeedScalar Tau_d[3], stab[5][3], U_dot[5] = {0};
247*cde3d787SJames Wright     Tau_diagPrim(context->tau_coeffs, gas, s, dXdx, dt, Tau_d);
248*cde3d787SJames Wright     Stabilization(context->stabilization, gas, s, Tau_d, grad_s, U_dot, body_force, divFdiff_i, stab);
2493a8779fbSJames Wright 
2502b916ea7SJeremy L Thompson     for (CeedInt j = 0; j < 5; j++) {
2512b916ea7SJeremy L Thompson       for (CeedInt k = 0; k < 3; k++) Grad_v[k][j][i] -= wdetJ * (stab[j][0] * dXdx[k][0] + stab[j][1] * dXdx[k][1] + stab[j][2] * dXdx[k][2]);
2522b916ea7SJeremy L Thompson     }
253b193fadcSJames Wright   }
2543a8779fbSJames Wright   return 0;
2553a8779fbSJames Wright }
2563a8779fbSJames Wright 
257e57b52dbSJames Wright /**
258e57b52dbSJames Wright   @brief IFunction integrand of Navier-Stokes for Newtonian ideal gas
259e57b52dbSJames Wright 
260e57b52dbSJames Wright   This is used in the quadrature point loop within a larger QFunction.
261e57b52dbSJames Wright   `v_i` and `dv_i` are summed into (meaning they must be some initialized value).
262e57b52dbSJames Wright   `kmstress` and `Tau_d` are given to be included as Jacobian data.
263e57b52dbSJames Wright 
264e57b52dbSJames Wright   @param[in]    s          `State` of solution
265e57b52dbSJames Wright   @param[in]    grad_s     Physical gradient of solution
266e57b52dbSJames Wright   @param[in]    s_dot      Time derivative of solution
267e57b52dbSJames Wright   @param[in]    divFdiff_i Divergence of diffusive flux
268e57b52dbSJames Wright   @param[in]    x_i        Coordinate location of quadrature point
269*cde3d787SJames Wright   @param[in]    gas        Ideal gas properties
270e57b52dbSJames Wright   @param[in]    context    Newtonian context
271e57b52dbSJames Wright   @param[in]    dXdx       Inverse of element mapping Jacobian (d\xi / dx)
272e57b52dbSJames Wright   @param[inout] v_i        Output to be multiplied by weight function, summed into
273e57b52dbSJames Wright   @param[inout] grad_v_i   Output to be multiplied by gradient of weight function, summed into
274e57b52dbSJames Wright   @param[out]   kmstress   Viscous stress, in Kelvin-Mandel ordering
275e57b52dbSJames Wright   @param[out]   Tau_d      Diagonal Tau coefficients
276e57b52dbSJames Wright **/
IFunction_Newtonian_Integrand(const State s,const State grad_s[3],const State s_dot,const CeedScalar divFdiff_i[5],const CeedScalar x_i[3],const NewtonianIGProperties gas,const NewtonianIdealGasContext context,const CeedScalar dXdx[3][3],CeedScalar v_i[5],CeedScalar grad_v_i[5][3],CeedScalar kmstress[6],CeedScalar Tau_d[3])27730b5892fSJames Wright CEED_QFUNCTION_HELPER void IFunction_Newtonian_Integrand(const State s, const State grad_s[3], const State s_dot, const CeedScalar divFdiff_i[5],
278*cde3d787SJames Wright                                                          const CeedScalar x_i[3], const NewtonianIGProperties gas,
279*cde3d787SJames Wright                                                          const NewtonianIdealGasContext context, const CeedScalar dXdx[3][3], CeedScalar v_i[5],
280*cde3d787SJames Wright                                                          CeedScalar grad_v_i[5][3], CeedScalar kmstress[6], CeedScalar Tau_d[3]) {
281e57b52dbSJames Wright   CeedScalar        strain_rate[6], stress[3][3], F_visc_energy[3], F_total[5][3];
282e57b52dbSJames Wright   StateConservative F_inviscid[3];
283e57b52dbSJames Wright   const CeedScalar *g = context->g, dt = context->dt;
28430b5892fSJames Wright 
285e57b52dbSJames Wright   // Advective and viscous fluxes
28630b5892fSJames Wright   KMStrainRate_State(grad_s, strain_rate);
287*cde3d787SJames Wright   NewtonianStress(gas, strain_rate, kmstress);
28830b5892fSJames Wright   KMUnpack(kmstress, stress);
289*cde3d787SJames Wright   ViscousEnergyFlux(gas, s.Y, grad_s, stress, F_visc_energy);
290*cde3d787SJames Wright   FluxInviscid(gas, s, F_inviscid);
291e57b52dbSJames Wright   FluxTotal(F_inviscid, stress, F_visc_energy, F_total);
292e57b52dbSJames Wright   AXPY(-1, (CeedScalar *)F_total, (CeedScalar *)grad_v_i, 15);
29330b5892fSJames Wright 
294e57b52dbSJames Wright   // Body force and time derivative
29530b5892fSJames Wright   const CeedScalar body_force[5] = {0, s.U.density * g[0], s.U.density * g[1], s.U.density * g[2], Dot3(s.U.momentum, g)};
296e57b52dbSJames Wright   CeedScalar       U_dot[5];
29730b5892fSJames Wright   UnpackState_U(s_dot.U, U_dot);
29830b5892fSJames Wright   for (CeedInt j = 0; j < 5; j++) v_i[j] += U_dot[j] - body_force[j];
299e57b52dbSJames Wright 
300e57b52dbSJames Wright   // Stabilization
301e57b52dbSJames Wright   CeedScalar stab[5][3];
302*cde3d787SJames Wright   Tau_diagPrim(context->tau_coeffs, gas, s, dXdx, dt, Tau_d);
303*cde3d787SJames Wright   Stabilization(context->stabilization, gas, s, Tau_d, grad_s, U_dot, body_force, divFdiff_i, stab);
304e57b52dbSJames Wright   AXPY(1, (CeedScalar *)stab, (CeedScalar *)grad_v_i, 15);
30530b5892fSJames Wright }
30630b5892fSJames Wright 
307e57b52dbSJames Wright // @brief State-independent IFunction of Navier-Stokes for Newtonian ideal gas
IFunction_Newtonian(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out,StateVariable state_var)3088fff8293SJames Wright CEED_QFUNCTION_HELPER int IFunction_Newtonian(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateVariable state_var) {
3098c85b835SJames Wright   NewtonianIdealGasContext context      = (NewtonianIdealGasContext)ctx;
310ff684e42SJames Wright   const bool               use_divFdiff = context->divFdiff_method != DIV_DIFF_FLUX_PROJ_NONE;
3118c85b835SJames Wright 
3123d65b166SJames Wright   const CeedScalar(*q)[CEED_Q_VLA]        = (const CeedScalar(*)[CEED_Q_VLA])in[0];
313e57b52dbSJames Wright   const CeedScalar(*grad_q)               = in[1];
3143d65b166SJames Wright   const CeedScalar(*q_dot)[CEED_Q_VLA]    = (const CeedScalar(*)[CEED_Q_VLA])in[2];
315ade49511SJames Wright   const CeedScalar(*q_data)               = in[3];
3163d65b166SJames Wright   const CeedScalar(*x)[CEED_Q_VLA]        = (const CeedScalar(*)[CEED_Q_VLA])in[4];
317ff684e42SJames Wright   const CeedScalar(*divFdiff)[CEED_Q_VLA] = use_divFdiff ? (const CeedScalar(*)[CEED_Q_VLA])in[5] : NULL;
3183d65b166SJames Wright   CeedScalar(*v)[CEED_Q_VLA]              = (CeedScalar(*)[CEED_Q_VLA])out[0];
319e57b52dbSJames Wright   CeedScalar(*grad_v)[5][CEED_Q_VLA]      = (CeedScalar(*)[5][CEED_Q_VLA])out[1];
320ade49511SJames Wright   CeedScalar(*jac_data)                   = out[2];
3213d65b166SJames Wright 
322*cde3d787SJames Wright   const NewtonianIGProperties gas = context->gas;
323*cde3d787SJames Wright 
3243d65b166SJames Wright   CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) {
325e57b52dbSJames Wright     const CeedScalar q_i[5]     = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]};
326e57b52dbSJames Wright     const CeedScalar q_i_dot[5] = {q_dot[0][i], q_dot[1][i], q_dot[2][i], q_dot[3][i], q_dot[4][i]};
327c1a52365SJed Brown     const CeedScalar x_i[3]     = {x[0][i], x[1][i], x[2][i]};
328*cde3d787SJames Wright     const State      s          = StateFromQ(gas, q_i, state_var);
329*cde3d787SJames Wright     const State      s_dot      = StateFromQ_fwd(gas, s, q_i_dot, state_var);
330c1a52365SJed Brown 
331ade49511SJames Wright     CeedScalar wdetJ, dXdx[3][3];
332ade49511SJames Wright     QdataUnpack_3D(Q, i, q_data, &wdetJ, dXdx);
333c1a52365SJed Brown     State grad_s[3];
334*cde3d787SJames Wright     StatePhysicalGradientFromReference(Q, i, gas, s, state_var, grad_q, dXdx, grad_s);
3358c85b835SJames Wright     CeedScalar divFdiff_i[5] = {0.};
33630b5892fSJames Wright     if (use_divFdiff)
3378c85b835SJames Wright       for (int j = 1; j < 5; j++) divFdiff_i[j] = divFdiff[j - 1][i];
3383a8779fbSJames Wright 
339ab18f1e5SJames Wright     CeedScalar v_i[5] = {0.}, grad_v_i[5][3] = {{0.}}, kmstress[6], Tau_d[3], sigma = 0;
340*cde3d787SJames Wright     IFunction_Newtonian_Integrand(s, grad_s, s_dot, divFdiff_i, x_i, gas, context, dXdx, v_i, grad_v_i, kmstress, Tau_d);
34130b5892fSJames Wright     if (context->idl_enable)
342*cde3d787SJames Wright       InternalDampingLayer_IFunction_Integrand(s, gas, context->idl_amplitude, context->idl_length, context->idl_start, x_i[0], context->idl_pressure,
343*cde3d787SJames Wright                                                v_i, &sigma);
34430b5892fSJames Wright 
34530b5892fSJames Wright     for (CeedInt j = 0; j < 5; j++) v[j][i] = wdetJ * v_i[j];
3462b916ea7SJeremy L Thompson     for (CeedInt j = 0; j < 5; j++) {
3478fd72709SJames Wright       for (CeedInt k = 0; k < 3; k++)
348e57b52dbSJames Wright         grad_v[k][j][i] = wdetJ * (grad_v_i[j][0] * dXdx[k][0] + grad_v_i[j][1] * dXdx[k][1] + grad_v_i[j][2] * dXdx[k][2]);
3493d65b166SJames Wright     }
35030b5892fSJames Wright 
351e57b52dbSJames Wright     StoredValuesPack(Q, i, 0, 5, q_i, jac_data);
352ade49511SJames Wright     StoredValuesPack(Q, i, 5, 6, kmstress, jac_data);
353ade49511SJames Wright     StoredValuesPack(Q, i, 11, 3, Tau_d, jac_data);
35430b5892fSJames Wright     if (context->idl_enable) StoredValuesPack(Q, i, 14, 1, &sigma, jac_data);
355b193fadcSJames Wright   }
3563a8779fbSJames Wright   return 0;
3573a8779fbSJames Wright }
358f0b65372SJed Brown 
IFunction_Newtonian_Conserv(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)3592b916ea7SJeremy L Thompson CEED_QFUNCTION(IFunction_Newtonian_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
3608fff8293SJames Wright   return IFunction_Newtonian(ctx, Q, in, out, STATEVAR_CONSERVATIVE);
36176555becSJames Wright }
36276555becSJames Wright 
IFunction_Newtonian_Prim(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)3632b916ea7SJeremy L Thompson CEED_QFUNCTION(IFunction_Newtonian_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
3648fff8293SJames Wright   return IFunction_Newtonian(ctx, Q, in, out, STATEVAR_PRIMITIVE);
36576555becSJames Wright }
36676555becSJames Wright 
IFunction_Newtonian_Entropy(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)3679b103f75SJames Wright CEED_QFUNCTION(IFunction_Newtonian_Entropy)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
3689b103f75SJames Wright   return IFunction_Newtonian(ctx, Q, in, out, STATEVAR_ENTROPY);
3699b103f75SJames Wright }
3709b103f75SJames Wright 
3718fd72709SJames Wright /**
3728fd72709SJames Wright   @brief IJacobian integrand of Navier-Stokes for Newtonian ideal gas
3733d65b166SJames Wright 
3748fd72709SJames Wright   This is used in the quadrature point loop within a larger QFunction.
3758fd72709SJames Wright   `v_i` and `dv_i` are summed into (meaning they must be some initialized value).
3768fd72709SJames Wright   `kmstress` and `Tau_d` are (generally) calculated and stored by the IFunction.
3778fd72709SJames Wright 
3788fd72709SJames Wright   @param[in]    s          `State` of solution
3798fd72709SJames Wright   @param[in]    ds         Change in `State` of solution
3808fd72709SJames Wright   @param[in]    grad_ds    Physical gradient of change in `State` of solution
381*cde3d787SJames Wright   @param[in]    gas        Ideal gas properties
3828fd72709SJames Wright   @param[in]    context    Newtonian context
3838fd72709SJames Wright   @param[in]    kmstress   Viscous stress, in Kelvin-Mandel ordering
3848fd72709SJames Wright   @param[in]    Tau_d      Diagonal Tau coefficients
3858fd72709SJames Wright   @param[inout] v_i        Output to be multiplied by weight function, summed into
3868fd72709SJames Wright   @param[inout] grad_v_i   Output to be multiplied by gradient of weight function, summed into
3878fd72709SJames Wright **/
IJacobian_Newtonian_Integrand(const State s,const State ds,const State grad_ds[3],const NewtonianIGProperties gas,const NewtonianIdealGasContext context,const CeedScalar kmstress[6],const CeedScalar Tau_d[3],CeedScalar v_i[5],CeedScalar grad_v_i[5][3])388*cde3d787SJames Wright CEED_QFUNCTION_HELPER void IJacobian_Newtonian_Integrand(const State s, const State ds, const State grad_ds[3], const NewtonianIGProperties gas,
3898fd72709SJames Wright                                                          const NewtonianIdealGasContext context, const CeedScalar kmstress[6],
3908fd72709SJames Wright                                                          const CeedScalar Tau_d[3], CeedScalar v_i[5], CeedScalar grad_v_i[5][3]) {
391f0b65372SJed Brown   const CeedScalar *g = context->g;
3928fd72709SJames Wright   CeedScalar        dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dF_visc_energy[3], dF_total[5][3];
3938fd72709SJames Wright   StateConservative dF_inviscid[3];
394f0b65372SJed Brown 
3958fd72709SJames Wright   // Advective and viscous fluxes
39640a33f2dSJames Wright   KMStrainRate_State(grad_ds, dstrain_rate);
397*cde3d787SJames Wright   NewtonianStress(gas, dstrain_rate, dkmstress);
398f0b65372SJed Brown   KMUnpack(dkmstress, dstress);
399f0b65372SJed Brown   KMUnpack(kmstress, stress);
400*cde3d787SJames Wright   ViscousEnergyFlux_fwd(gas, s.Y, ds.Y, grad_ds, stress, dstress, dF_visc_energy);
401*cde3d787SJames Wright   FluxInviscid_fwd(gas, s, ds, dF_inviscid);
4028fd72709SJames Wright   FluxTotal(dF_inviscid, dstress, dF_visc_energy, dF_total);
4038fd72709SJames Wright   AXPY(-1, (CeedScalar *)dF_total, (CeedScalar *)grad_v_i, 15);
404f0b65372SJed Brown 
4058fd72709SJames Wright   // Body force and time derivative
40660dbb574SKenneth E. Jansen   const CeedScalar dbody_force[5] = {0, ds.U.density * g[0], ds.U.density * g[1], ds.U.density * g[2], Dot3(ds.U.momentum, g)};
4078fd72709SJames Wright   CeedScalar       dU[5], dU_dot[5];
40876555becSJames Wright   UnpackState_U(ds.U, dU);
4098fd72709SJames Wright   for (CeedInt j = 0; j < 5; j++) {
4108fd72709SJames Wright     dU_dot[j] = context->ijacobian_time_shift * dU[j];
4118fd72709SJames Wright     v_i[j]    = dU_dot[j] - dbody_force[j];
412e7754af5SKenneth E. Jansen   }
413e7754af5SKenneth E. Jansen 
4148fd72709SJames Wright   // Stabilization
4158fd72709SJames Wright   CeedScalar       dstab[5][3];
4168c85b835SJames Wright   const CeedScalar zeroFlux[5] = {0.};
417*cde3d787SJames Wright   Stabilization(context->stabilization, gas, s, Tau_d, grad_ds, dU_dot, dbody_force, zeroFlux, dstab);
4188fd72709SJames Wright   AXPY(1, (CeedScalar *)dstab, (CeedScalar *)grad_v_i, 15);
4198fd72709SJames Wright }
420d1b9ef12SLeila Ghaffari 
4218fd72709SJames Wright // @brief State-independent IJacobian of Navier-Stokes for Newtonian ideal gas
IJacobian_Newtonian(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out,StateVariable state_var)4228fd72709SJames Wright CEED_QFUNCTION_HELPER int IJacobian_Newtonian(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateVariable state_var) {
4238fd72709SJames Wright   const CeedScalar(*dq)[CEED_Q_VLA]  = (const CeedScalar(*)[CEED_Q_VLA])in[0];
4248fd72709SJames Wright   const CeedScalar(*grad_dq)         = in[1];
4258fd72709SJames Wright   const CeedScalar(*q_data)          = in[2];
4268fd72709SJames Wright   const CeedScalar(*jac_data)        = in[3];
4278fd72709SJames Wright   CeedScalar(*v)[CEED_Q_VLA]         = (CeedScalar(*)[CEED_Q_VLA])out[0];
4288fd72709SJames Wright   CeedScalar(*grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1];
4298fd72709SJames Wright 
430*cde3d787SJames Wright   const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx;
431*cde3d787SJames Wright   const NewtonianIGProperties    gas     = context->gas;
4328fd72709SJames Wright 
4338fd72709SJames Wright   CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) {
4348fd72709SJames Wright     const CeedScalar dq_i[5] = {dq[0][i], dq[1][i], dq[2][i], dq[3][i], dq[4][i]};
4358fd72709SJames Wright     CeedScalar       qi[5], kmstress[6], Tau_d[3];
4368fd72709SJames Wright     StoredValuesUnpack(Q, i, 0, 5, jac_data, qi);
4378fd72709SJames Wright     StoredValuesUnpack(Q, i, 5, 6, jac_data, kmstress);
4388fd72709SJames Wright     StoredValuesUnpack(Q, i, 11, 3, jac_data, Tau_d);
439*cde3d787SJames Wright     const State s  = StateFromQ(gas, qi, state_var);
440*cde3d787SJames Wright     const State ds = StateFromQ_fwd(gas, s, dq_i, state_var);
4418fd72709SJames Wright 
4428fd72709SJames Wright     CeedScalar wdetJ, dXdx[3][3];
4438fd72709SJames Wright     QdataUnpack_3D(Q, i, q_data, &wdetJ, dXdx);
4448fd72709SJames Wright     State grad_ds[3];
445*cde3d787SJames Wright     StatePhysicalGradientFromReference(Q, i, gas, s, state_var, grad_dq, dXdx, grad_ds);
4468fd72709SJames Wright 
4478fd72709SJames Wright     CeedScalar v_i[5] = {0.}, grad_v_i[5][3] = {{0.}};
448*cde3d787SJames Wright     IJacobian_Newtonian_Integrand(s, ds, grad_ds, gas, context, kmstress, Tau_d, v_i, grad_v_i);
4498fd72709SJames Wright     if (context->idl_enable) {
4508fd72709SJames Wright       CeedScalar sigma;
4518fd72709SJames Wright       StoredValuesUnpack(Q, i, 14, 1, jac_data, &sigma);
452*cde3d787SJames Wright       InternalDampingLayer_IJacobian_Integrand(s, ds, gas, sigma, v_i);
4538fd72709SJames Wright       for (int j = 0; j < 5; j++) v[j][i] += wdetJ * v_i[j];
4548fd72709SJames Wright     }
4558fd72709SJames Wright 
4568fd72709SJames Wright     for (CeedInt j = 0; j < 5; j++) v[j][i] = wdetJ * v_i[j];
4572b916ea7SJeremy L Thompson     for (int j = 0; j < 5; j++) {
4588fd72709SJames Wright       for (int k = 0; k < 3; k++) grad_v[k][j][i] = wdetJ * (grad_v_i[j][0] * dXdx[k][0] + grad_v_i[j][1] * dXdx[k][1] + grad_v_i[j][2] * dXdx[k][2]);
4592b916ea7SJeremy L Thompson     }
460b193fadcSJames Wright   }
461f0b65372SJed Brown   return 0;
462f0b65372SJed Brown }
4638085925cSJames Wright 
IJacobian_Newtonian_Conserv(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)4642b916ea7SJeremy L Thompson CEED_QFUNCTION(IJacobian_Newtonian_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
4658fff8293SJames Wright   return IJacobian_Newtonian(ctx, Q, in, out, STATEVAR_CONSERVATIVE);
46676555becSJames Wright }
46776555becSJames Wright 
IJacobian_Newtonian_Prim(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)4682b916ea7SJeremy L Thompson CEED_QFUNCTION(IJacobian_Newtonian_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
4698fff8293SJames Wright   return IJacobian_Newtonian(ctx, Q, in, out, STATEVAR_PRIMITIVE);
47076555becSJames Wright }
47176555becSJames Wright 
IJacobian_Newtonian_Entropy(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)4729b103f75SJames Wright CEED_QFUNCTION(IJacobian_Newtonian_Entropy)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
4739b103f75SJames Wright   return IJacobian_Newtonian(ctx, Q, in, out, STATEVAR_ENTROPY);
4749b103f75SJames Wright }
4759b103f75SJames Wright 
476d1b9ef12SLeila Ghaffari // *****************************************************************************
4778085925cSJames Wright // Compute boundary integral (ie. for strongly set inflows)
478d1b9ef12SLeila Ghaffari // *****************************************************************************
BoundaryIntegral(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out,StateVariable state_var)4798fff8293SJames Wright CEED_QFUNCTION_HELPER int BoundaryIntegral(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateVariable state_var) {
4804b96a86bSJames Wright   const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx;
4813d65b166SJames Wright   const CeedScalar(*q)[CEED_Q_VLA]       = (const CeedScalar(*)[CEED_Q_VLA])in[0];
48287bd45e7SJames Wright   const CeedScalar(*Grad_q)              = in[1];
483ade49511SJames Wright   const CeedScalar(*q_data_sur)          = in[2];
4843d65b166SJames Wright   CeedScalar(*v)[CEED_Q_VLA]             = (CeedScalar(*)[CEED_Q_VLA])out[0];
4854b96a86bSJames Wright   CeedScalar(*jac_data_sur)              = context->is_implicit ? out[1] : NULL;
4868085925cSJames Wright 
487d3b25f3aSJames Wright   const bool                  is_implicit = context->is_implicit;
488*cde3d787SJames Wright   const NewtonianIGProperties gas         = context->gas;
4898085925cSJames Wright 
4902b916ea7SJeremy L Thompson   CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) {
49141e73928SJames Wright     const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]};
492*cde3d787SJames Wright     State            s     = StateFromQ(gas, qi, state_var);
4938085925cSJames Wright 
49478e8b7daSJames Wright     CeedScalar wdetJb, dXdx[2][3], normal[3];
49578e8b7daSJames Wright     QdataBoundaryUnpack_3D(Q, i, q_data_sur, &wdetJb, dXdx, normal);
496ade49511SJames Wright     wdetJb *= is_implicit ? -1. : 1.;
4978085925cSJames Wright 
498d3b25f3aSJames Wright     State grad_s[3];
499*cde3d787SJames Wright     StatePhysicalGradientFromReference_Boundary(Q, i, gas, s, state_var, Grad_q, dXdx, grad_s);
5008085925cSJames Wright 
501d3b25f3aSJames Wright     CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3];
50240a33f2dSJames Wright     KMStrainRate_State(grad_s, strain_rate);
503*cde3d787SJames Wright     NewtonianStress(gas, strain_rate, kmstress);
504d3b25f3aSJames Wright     KMUnpack(kmstress, stress);
505*cde3d787SJames Wright     ViscousEnergyFlux(gas, s.Y, grad_s, stress, Fe);
506d3b25f3aSJames Wright 
507d3b25f3aSJames Wright     StateConservative F_inviscid[3];
508*cde3d787SJames Wright     FluxInviscid(gas, s, F_inviscid);
509d3b25f3aSJames Wright 
510c5740391SJames Wright     CeedScalar Flux[5];
51178e8b7daSJames Wright     FluxTotal_Boundary(F_inviscid, stress, Fe, normal, Flux);
512d3b25f3aSJames Wright 
513c5740391SJames Wright     for (CeedInt j = 0; j < 5; j++) v[j][i] = -wdetJb * Flux[j];
5148085925cSJames Wright 
5154b96a86bSJames Wright     if (is_implicit) {
516ade49511SJames Wright       StoredValuesPack(Q, i, 0, 5, qi, jac_data_sur);
517ade49511SJames Wright       StoredValuesPack(Q, i, 5, 6, kmstress, jac_data_sur);
5188085925cSJames Wright     }
5194b96a86bSJames Wright   }
5208085925cSJames Wright   return 0;
5218085925cSJames Wright }
5228085925cSJames Wright 
BoundaryIntegral_Conserv(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)5232b916ea7SJeremy L Thompson CEED_QFUNCTION(BoundaryIntegral_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
5248fff8293SJames Wright   return BoundaryIntegral(ctx, Q, in, out, STATEVAR_CONSERVATIVE);
525d4559bbeSJames Wright }
526d4559bbeSJames Wright 
BoundaryIntegral_Prim(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)5272b916ea7SJeremy L Thompson CEED_QFUNCTION(BoundaryIntegral_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
5288fff8293SJames Wright   return BoundaryIntegral(ctx, Q, in, out, STATEVAR_PRIMITIVE);
529d4559bbeSJames Wright }
530d4559bbeSJames Wright 
BoundaryIntegral_Entropy(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)5319b103f75SJames Wright CEED_QFUNCTION(BoundaryIntegral_Entropy)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
5329b103f75SJames Wright   return BoundaryIntegral(ctx, Q, in, out, STATEVAR_ENTROPY);
5339b103f75SJames Wright }
5349b103f75SJames Wright 
535d1b9ef12SLeila Ghaffari // *****************************************************************************
53668ae065aSJames Wright // Jacobian for "set nothing" boundary integral
537d1b9ef12SLeila Ghaffari // *****************************************************************************
BoundaryIntegral_Jacobian(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out,StateVariable state_var)5382b916ea7SJeremy L Thompson CEED_QFUNCTION_HELPER int BoundaryIntegral_Jacobian(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out,
5398fff8293SJames Wright                                                     StateVariable state_var) {
5403d65b166SJames Wright   const CeedScalar(*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0];
54187bd45e7SJames Wright   const CeedScalar(*Grad_dq)        = in[1];
542ade49511SJames Wright   const CeedScalar(*q_data_sur)     = in[2];
543c1484fadSKenneth E. Jansen   const CeedScalar(*jac_data_sur)   = in[4];
54468ae065aSJames Wright   CeedScalar(*v)[CEED_Q_VLA]        = (CeedScalar(*)[CEED_Q_VLA])out[0];
54568ae065aSJames Wright 
54668ae065aSJames Wright   const NewtonianIdealGasContext context     = (NewtonianIdealGasContext)ctx;
547*cde3d787SJames Wright   const NewtonianIGProperties    gas         = context->gas;
548ade49511SJames Wright   const bool                     is_implicit = context->is_implicit;
54968ae065aSJames Wright 
5503d65b166SJames Wright   CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) {
55178e8b7daSJames Wright     CeedScalar wdetJb, dXdx[2][3], normal[3];
55278e8b7daSJames Wright     QdataBoundaryUnpack_3D(Q, i, q_data_sur, &wdetJb, dXdx, normal);
553ade49511SJames Wright     wdetJb *= is_implicit ? -1. : 1.;
55468ae065aSJames Wright 
555edcfef1bSKenneth E. Jansen     CeedScalar qi[5], kmstress[6], dqi[5];
556ade49511SJames Wright     StoredValuesUnpack(Q, i, 0, 5, jac_data_sur, qi);
557ade49511SJames Wright     StoredValuesUnpack(Q, i, 5, 6, jac_data_sur, kmstress);
55841e73928SJames Wright     for (int j = 0; j < 5; j++) dqi[j] = dq[j][i];
5593934e2b1SJames Wright 
560*cde3d787SJames Wright     State s  = StateFromQ(gas, qi, state_var);
561*cde3d787SJames Wright     State ds = StateFromQ_fwd(gas, s, dqi, state_var);
56268ae065aSJames Wright 
56368ae065aSJames Wright     State grad_ds[3];
564*cde3d787SJames Wright     StatePhysicalGradientFromReference_Boundary(Q, i, gas, s, state_var, Grad_dq, dXdx, grad_ds);
56568ae065aSJames Wright 
56668ae065aSJames Wright     CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3];
56740a33f2dSJames Wright     KMStrainRate_State(grad_ds, dstrain_rate);
568*cde3d787SJames Wright     NewtonianStress(gas, dstrain_rate, dkmstress);
56968ae065aSJames Wright     KMUnpack(dkmstress, dstress);
57068ae065aSJames Wright     KMUnpack(kmstress, stress);
571*cde3d787SJames Wright     ViscousEnergyFlux_fwd(gas, s.Y, ds.Y, grad_ds, stress, dstress, dFe);
57268ae065aSJames Wright 
57368ae065aSJames Wright     StateConservative dF_inviscid[3];
574*cde3d787SJames Wright     FluxInviscid_fwd(gas, s, ds, dF_inviscid);
57568ae065aSJames Wright 
576c5740391SJames Wright     CeedScalar dFlux[5];
57778e8b7daSJames Wright     FluxTotal_Boundary(dF_inviscid, dstress, dFe, normal, dFlux);
57868ae065aSJames Wright 
579c5740391SJames Wright     for (int j = 0; j < 5; j++) v[j][i] = -wdetJb * dFlux[j];
580512c8ec7SJames Wright   }
58168ae065aSJames Wright   return 0;
58268ae065aSJames Wright }
58368ae065aSJames Wright 
BoundaryIntegral_Jacobian_Conserv(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)5842b916ea7SJeremy L Thompson CEED_QFUNCTION(BoundaryIntegral_Jacobian_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
5858fff8293SJames Wright   return BoundaryIntegral_Jacobian(ctx, Q, in, out, STATEVAR_CONSERVATIVE);
586d4559bbeSJames Wright }
587d4559bbeSJames Wright 
BoundaryIntegral_Jacobian_Prim(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)5882b916ea7SJeremy L Thompson CEED_QFUNCTION(BoundaryIntegral_Jacobian_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
5898fff8293SJames Wright   return BoundaryIntegral_Jacobian(ctx, Q, in, out, STATEVAR_PRIMITIVE);
590d4559bbeSJames Wright }
5919b103f75SJames Wright 
BoundaryIntegral_Jacobian_Entropy(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)5929b103f75SJames Wright CEED_QFUNCTION(BoundaryIntegral_Jacobian_Entropy)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
5939b103f75SJames Wright   return BoundaryIntegral_Jacobian(ctx, Q, in, out, STATEVAR_ENTROPY);
5949b103f75SJames Wright }
59536038bbcSJames Wright 
5968561fee2SJames Wright // @brief Volume integral for RHS of divergence of diffusive flux direct projection
DivDiffusiveFluxVolumeRHS_NS(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out,StateVariable state_var)59736038bbcSJames Wright CEED_QFUNCTION_HELPER int DivDiffusiveFluxVolumeRHS_NS(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out,
59836038bbcSJames Wright                                                        StateVariable state_var) {
59936038bbcSJames Wright   const CeedScalar(*q)[CEED_Q_VLA]   = (const CeedScalar(*)[CEED_Q_VLA])in[0];
60036038bbcSJames Wright   const CeedScalar(*Grad_q)          = in[1];
60136038bbcSJames Wright   const CeedScalar(*q_data)          = in[2];
60236038bbcSJames Wright   CeedScalar(*Grad_v)[4][CEED_Q_VLA] = (CeedScalar(*)[4][CEED_Q_VLA])out[0];
60336038bbcSJames Wright 
60436038bbcSJames Wright   const NewtonianIdealGasContext context               = (NewtonianIdealGasContext)ctx;
605*cde3d787SJames Wright   const NewtonianIGProperties    gas                   = context->gas;
60636038bbcSJames Wright   const StateConservative        ZeroInviscidFluxes[3] = {{0}};
60736038bbcSJames Wright 
60836038bbcSJames Wright   CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) {
60936038bbcSJames Wright     const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]};
610*cde3d787SJames Wright     const State      s     = StateFromQ(gas, qi, state_var);
61136038bbcSJames Wright     CeedScalar       wdetJ, dXdx[3][3];
61236038bbcSJames Wright     CeedScalar       stress[3][3], Fe[3], Fdiff[5][3];
61336038bbcSJames Wright 
61436038bbcSJames Wright     QdataUnpack_3D(Q, i, q_data, &wdetJ, dXdx);
61536038bbcSJames Wright     {  // Get stress and Fe
61636038bbcSJames Wright       State      grad_s[3];
61736038bbcSJames Wright       CeedScalar strain_rate[6], kmstress[6];
61836038bbcSJames Wright 
619*cde3d787SJames Wright       StatePhysicalGradientFromReference(Q, i, gas, s, state_var, Grad_q, dXdx, grad_s);
62036038bbcSJames Wright       KMStrainRate_State(grad_s, strain_rate);
621*cde3d787SJames Wright       NewtonianStress(gas, strain_rate, kmstress);
62236038bbcSJames Wright       KMUnpack(kmstress, stress);
623*cde3d787SJames Wright       ViscousEnergyFlux(gas, s.Y, grad_s, stress, Fe);
62436038bbcSJames Wright     }
62536038bbcSJames Wright 
62636038bbcSJames Wright     FluxTotal(ZeroInviscidFluxes, stress, Fe, Fdiff);
62736038bbcSJames Wright 
62836038bbcSJames Wright     for (CeedInt j = 1; j < 5; j++) {  // Continuity has no diffusive flux, therefore skip
62936038bbcSJames Wright       for (CeedInt k = 0; k < 3; k++) {
63036038bbcSJames Wright         Grad_v[k][j - 1][i] = -wdetJ * Dot3(dXdx[k], Fdiff[j]);
63136038bbcSJames Wright       }
63236038bbcSJames Wright     }
63336038bbcSJames Wright   }
63436038bbcSJames Wright   return 0;
63536038bbcSJames Wright }
63636038bbcSJames Wright 
DivDiffusiveFluxVolumeRHS_NS_Conserv(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)63736038bbcSJames Wright CEED_QFUNCTION(DivDiffusiveFluxVolumeRHS_NS_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
63836038bbcSJames Wright   return DivDiffusiveFluxVolumeRHS_NS(ctx, Q, in, out, STATEVAR_CONSERVATIVE);
63936038bbcSJames Wright }
64036038bbcSJames Wright 
DivDiffusiveFluxVolumeRHS_NS_Prim(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)64136038bbcSJames Wright CEED_QFUNCTION(DivDiffusiveFluxVolumeRHS_NS_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
64236038bbcSJames Wright   return DivDiffusiveFluxVolumeRHS_NS(ctx, Q, in, out, STATEVAR_PRIMITIVE);
64336038bbcSJames Wright }
64436038bbcSJames Wright 
DivDiffusiveFluxVolumeRHS_NS_Entropy(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)64536038bbcSJames Wright CEED_QFUNCTION(DivDiffusiveFluxVolumeRHS_NS_Entropy)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
64636038bbcSJames Wright   return DivDiffusiveFluxVolumeRHS_NS(ctx, Q, in, out, STATEVAR_ENTROPY);
64736038bbcSJames Wright }
64836038bbcSJames Wright 
6498561fee2SJames Wright // @brief Boundary integral for RHS of divergence of diffusive flux direct projection
DivDiffusiveFluxBoundaryRHS_NS(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out,StateVariable state_var)65036038bbcSJames Wright CEED_QFUNCTION_HELPER int DivDiffusiveFluxBoundaryRHS_NS(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out,
65136038bbcSJames Wright                                                          StateVariable state_var) {
65236038bbcSJames Wright   const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0];
65336038bbcSJames Wright   const CeedScalar(*Grad_q)        = in[1];
65436038bbcSJames Wright   const CeedScalar(*q_data)        = in[2];
65536038bbcSJames Wright   CeedScalar(*v)[CEED_Q_VLA]       = (CeedScalar(*)[CEED_Q_VLA])out[0];
65636038bbcSJames Wright 
65736038bbcSJames Wright   const NewtonianIdealGasContext context               = (NewtonianIdealGasContext)ctx;
658*cde3d787SJames Wright   const NewtonianIGProperties    gas                   = context->gas;
65936038bbcSJames Wright   const StateConservative        ZeroInviscidFluxes[3] = {{0}};
66036038bbcSJames Wright 
66136038bbcSJames Wright   CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) {
66236038bbcSJames Wright     const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]};
663*cde3d787SJames Wright     const State      s     = StateFromQ(gas, qi, state_var);
66436038bbcSJames Wright     CeedScalar       wdetJ, dXdx[3][3], normal[3];
66536038bbcSJames Wright     CeedScalar       stress[3][3], Fe[3], Fdiff[5];
66636038bbcSJames Wright 
66736038bbcSJames Wright     QdataBoundaryGradientUnpack_3D(Q, i, q_data, &wdetJ, dXdx, normal);
66836038bbcSJames Wright     {  // Get stress and Fe
66936038bbcSJames Wright       State      grad_s[3];
67036038bbcSJames Wright       CeedScalar strain_rate[6], kmstress[6];
67136038bbcSJames Wright 
672*cde3d787SJames Wright       StatePhysicalGradientFromReference(Q, i, gas, s, state_var, Grad_q, dXdx, grad_s);
67336038bbcSJames Wright       KMStrainRate_State(grad_s, strain_rate);
674*cde3d787SJames Wright       NewtonianStress(gas, strain_rate, kmstress);
67536038bbcSJames Wright       KMUnpack(kmstress, stress);
676*cde3d787SJames Wright       ViscousEnergyFlux(gas, s.Y, grad_s, stress, Fe);
67736038bbcSJames Wright     }
67836038bbcSJames Wright 
67936038bbcSJames Wright     FluxTotal_Boundary(ZeroInviscidFluxes, stress, Fe, normal, Fdiff);
68036038bbcSJames Wright 
68136038bbcSJames Wright     // Continuity has no diffusive flux, therefore skip
68236038bbcSJames Wright     for (CeedInt j = 1; j < 5; j++) v[j - 1][i] = wdetJ * Fdiff[j];
68336038bbcSJames Wright   }
68436038bbcSJames Wright   return 0;
68536038bbcSJames Wright }
68636038bbcSJames Wright 
DivDiffusiveFluxBoundaryRHS_NS_Conserv(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)68736038bbcSJames Wright CEED_QFUNCTION(DivDiffusiveFluxBoundaryRHS_NS_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
68836038bbcSJames Wright   return DivDiffusiveFluxBoundaryRHS_NS(ctx, Q, in, out, STATEVAR_CONSERVATIVE);
68936038bbcSJames Wright }
69036038bbcSJames Wright 
DivDiffusiveFluxBoundaryRHS_NS_Prim(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)69136038bbcSJames Wright CEED_QFUNCTION(DivDiffusiveFluxBoundaryRHS_NS_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
69236038bbcSJames Wright   return DivDiffusiveFluxBoundaryRHS_NS(ctx, Q, in, out, STATEVAR_PRIMITIVE);
69336038bbcSJames Wright }
69436038bbcSJames Wright 
DivDiffusiveFluxBoundaryRHS_NS_Entropy(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)69536038bbcSJames Wright CEED_QFUNCTION(DivDiffusiveFluxBoundaryRHS_NS_Entropy)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
69636038bbcSJames Wright   return DivDiffusiveFluxBoundaryRHS_NS(ctx, Q, in, out, STATEVAR_ENTROPY);
69736038bbcSJames Wright }
69836038bbcSJames Wright 
6998561fee2SJames Wright // @brief Integral for RHS of diffusive flux indirect projection
DiffusiveFluxRHS_NS(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out,StateVariable state_var)70036038bbcSJames Wright CEED_QFUNCTION_HELPER int DiffusiveFluxRHS_NS(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateVariable state_var) {
70136038bbcSJames Wright   const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0];
70236038bbcSJames Wright   const CeedScalar(*Grad_q)        = in[1];
70336038bbcSJames Wright   const CeedScalar(*q_data)        = in[2];
70436038bbcSJames Wright   CeedScalar(*v)[CEED_Q_VLA]       = (CeedScalar(*)[CEED_Q_VLA])out[0];
70536038bbcSJames Wright 
70636038bbcSJames Wright   const NewtonianIdealGasContext context               = (NewtonianIdealGasContext)ctx;
707*cde3d787SJames Wright   const NewtonianIGProperties    gas                   = context->gas;
70836038bbcSJames Wright   const StateConservative        ZeroInviscidFluxes[3] = {{0}};
70936038bbcSJames Wright 
71036038bbcSJames Wright   CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) {
71136038bbcSJames Wright     const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]};
712*cde3d787SJames Wright     const State      s     = StateFromQ(gas, qi, state_var);
71336038bbcSJames Wright     CeedScalar       wdetJ, dXdx[3][3];
71436038bbcSJames Wright     CeedScalar       stress[3][3], Fe[3], Fdiff[5][3];
71536038bbcSJames Wright 
71636038bbcSJames Wright     QdataUnpack_3D(Q, i, q_data, &wdetJ, dXdx);
71736038bbcSJames Wright     {  // Get stress and Fe
71836038bbcSJames Wright       State      grad_s[3];
71936038bbcSJames Wright       CeedScalar strain_rate[6], kmstress[6];
72036038bbcSJames Wright 
721*cde3d787SJames Wright       StatePhysicalGradientFromReference(Q, i, gas, s, state_var, Grad_q, dXdx, grad_s);
72236038bbcSJames Wright       KMStrainRate_State(grad_s, strain_rate);
723*cde3d787SJames Wright       NewtonianStress(gas, strain_rate, kmstress);
72436038bbcSJames Wright       KMUnpack(kmstress, stress);
725*cde3d787SJames Wright       ViscousEnergyFlux(gas, s.Y, grad_s, stress, Fe);
72636038bbcSJames Wright     }
72736038bbcSJames Wright 
72836038bbcSJames Wright     FluxTotal(ZeroInviscidFluxes, stress, Fe, Fdiff);
72936038bbcSJames Wright 
73036038bbcSJames Wright     for (CeedInt j = 1; j < 5; j++) {  // Continuity has no diffusive flux, therefore skip
73136038bbcSJames Wright       for (CeedInt k = 0; k < 3; k++) {
73236038bbcSJames Wright         v[(j - 1) * 3 + k][i] = wdetJ * Fdiff[j][k];
73336038bbcSJames Wright       }
73436038bbcSJames Wright     }
73536038bbcSJames Wright   }
73636038bbcSJames Wright   return 0;
73736038bbcSJames Wright }
73836038bbcSJames Wright 
DiffusiveFluxRHS_NS_Conserv(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)73936038bbcSJames Wright CEED_QFUNCTION(DiffusiveFluxRHS_NS_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
74036038bbcSJames Wright   return DiffusiveFluxRHS_NS(ctx, Q, in, out, STATEVAR_CONSERVATIVE);
74136038bbcSJames Wright }
74236038bbcSJames Wright 
DiffusiveFluxRHS_NS_Prim(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)74336038bbcSJames Wright CEED_QFUNCTION(DiffusiveFluxRHS_NS_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
74436038bbcSJames Wright   return DiffusiveFluxRHS_NS(ctx, Q, in, out, STATEVAR_PRIMITIVE);
74536038bbcSJames Wright }
74636038bbcSJames Wright 
DiffusiveFluxRHS_NS_Entropy(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)74736038bbcSJames Wright CEED_QFUNCTION(DiffusiveFluxRHS_NS_Entropy)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
74836038bbcSJames Wright   return DiffusiveFluxRHS_NS(ctx, Q, in, out, STATEVAR_ENTROPY);
74936038bbcSJames Wright }
750