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 // ***************************************************************************** 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 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 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 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 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 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 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 **/ 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 **/ 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 // ***************************************************************************** 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 **/ 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 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 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 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 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 **/ 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 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 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 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 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 // ***************************************************************************** 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 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 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 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 // ***************************************************************************** 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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