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; 20bb8a0c61SJames Wright 212b916ea7SJeremy L Thompson CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 22a541e550SJames Wright CeedScalar q[5]; 23edcfef1bSKenneth E. Jansen State s = StateFromPrimitive(&context->gas, context->reference); 248fff8293SJames Wright StateToQ(&context->gas, s, q, state_var); 252b916ea7SJeremy L Thompson for (CeedInt j = 0; j < 5; j++) q0[j][i] = q[j]; 26b193fadcSJames Wright } 273a8779fbSJames Wright return 0; 283a8779fbSJames Wright } 293a8779fbSJames Wright 309b103f75SJames Wright CEED_QFUNCTION(ICsNewtonianIG_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 319b103f75SJames Wright return ICsNewtonianIG(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 329b103f75SJames Wright } 339b103f75SJames Wright 342b916ea7SJeremy L Thompson CEED_QFUNCTION(ICsNewtonianIG_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 358fff8293SJames Wright return ICsNewtonianIG(ctx, Q, in, out, STATEVAR_PRIMITIVE); 36b8fb7609SAdeleke O. Bankole } 379b103f75SJames Wright 389b103f75SJames Wright CEED_QFUNCTION(ICsNewtonianIG_Entropy)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 399b103f75SJames Wright return ICsNewtonianIG(ctx, Q, in, out, STATEVAR_ENTROPY); 40cbe60e31SLeila Ghaffari } 41cbe60e31SLeila Ghaffari 4297cfd714SJames Wright CEED_QFUNCTION_HELPER int MassFunction_Newtonian(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateVariable state_var) { 4365dee3d2SJames Wright const CeedScalar(*q_dot)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 4465dee3d2SJames Wright const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[1]; 4565dee3d2SJames Wright const CeedScalar(*q_data) = in[2]; 4665dee3d2SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 4765dee3d2SJames Wright CeedScalar(*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 4865dee3d2SJames Wright 4965dee3d2SJames Wright NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 5065dee3d2SJames Wright 5165dee3d2SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 5265dee3d2SJames Wright const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 5365dee3d2SJames 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]}; 5465dee3d2SJames Wright const State s = StateFromQ(context, qi, state_var); 5565dee3d2SJames Wright const State s_dot = StateFromQ(context, qi_dot, state_var); 5665dee3d2SJames Wright CeedScalar wdetJ, dXdx[3][3]; 5765dee3d2SJames Wright QdataUnpack_3D(Q, i, q_data, &wdetJ, dXdx); 5865dee3d2SJames Wright 5965dee3d2SJames Wright // Standard mass matrix term 6065dee3d2SJames Wright for (CeedInt f = 0; f < 5; f++) { 6165dee3d2SJames Wright v[f][i] = wdetJ * qi_dot[f]; 6265dee3d2SJames Wright } 6365dee3d2SJames Wright 6465dee3d2SJames Wright // Stabilization method: none (Galerkin), SU, or SUPG 6565dee3d2SJames Wright State grad_s[3] = {{{0.}}}; 668c85b835SJames Wright CeedScalar Tau_d[3], stab[5][3], body_force[5] = {0.}, divFdiff[5] = {0.}, U_dot[5]; 6765dee3d2SJames Wright UnpackState_U(s_dot.U, U_dot); 6865dee3d2SJames Wright Tau_diagPrim(context, s, dXdx, context->dt, Tau_d); 698c85b835SJames Wright Stabilization(context, s, Tau_d, grad_s, U_dot, body_force, divFdiff, stab); 7065dee3d2SJames Wright 7165dee3d2SJames Wright // Stabilized mass term 7265dee3d2SJames Wright for (CeedInt j = 0; j < 5; j++) { 7365dee3d2SJames Wright for (CeedInt k = 0; k < 3; k++) { 7465dee3d2SJames 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]); 7565dee3d2SJames Wright } 7665dee3d2SJames Wright } 7765dee3d2SJames Wright } 7897cfd714SJames Wright return 0; 7965dee3d2SJames Wright } 8065dee3d2SJames Wright 8165dee3d2SJames Wright CEED_QFUNCTION(MassFunction_Newtonian_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 8297cfd714SJames Wright return MassFunction_Newtonian(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 8365dee3d2SJames Wright } 8465dee3d2SJames Wright 85e57b52dbSJames Wright // @brief Computes the residual created by IDL 8630b5892fSJames Wright CEED_QFUNCTION_HELPER void InternalDampingLayer_Residual(const NewtonianIdealGasContext context, const State s, const CeedScalar sigma, 8730b5892fSJames Wright CeedScalar damp_Y[5], CeedScalar damp_residual[5]) { 8830b5892fSJames Wright ScaleN(damp_Y, sigma, 5); 8930b5892fSJames Wright State damp_s = StateFromY_fwd(context, s, damp_Y); 9030b5892fSJames Wright 9130b5892fSJames Wright CeedScalar U[5]; 9230b5892fSJames Wright UnpackState_U(damp_s.U, U); 9330b5892fSJames Wright for (int i = 0; i < 5; i++) damp_residual[i] += U[i]; 9430b5892fSJames Wright } 9530b5892fSJames Wright 96e57b52dbSJames Wright /** 97e57b52dbSJames Wright @brief IFunction integrand for Internal Damping Layer 98e57b52dbSJames Wright 99e57b52dbSJames Wright `location` refers to whatever scalar distance is desired for IDL to ramp from. 100e57b52dbSJames Wright See `LinearRampCoefficient()` for details on the `amplitude`, `length`, `start`, and `location` arguments. 101e57b52dbSJames Wright 102e57b52dbSJames Wright @param[in] s Solution `State` 103e57b52dbSJames Wright @param[in] context Newtonian context 104e57b52dbSJames Wright @param[in] amplitude Amplitude of the IDL ramp 105e57b52dbSJames Wright @param[in] length Length of the IDL ramp 106e57b52dbSJames Wright @param[in] start Start of the IDL ramp 107e57b52dbSJames Wright @param[in] location Quadrature point location (relative to IDL ramp specification) 108e57b52dbSJames Wright @param[in] pressure Pressure used to damp to 109e57b52dbSJames Wright @param[inout] v_i Output to be multiplied by weight function, summed into 110e57b52dbSJames Wright @param[out] sigma IDL ramp coefficient 111e57b52dbSJames Wright **/ 11230b5892fSJames Wright CEED_QFUNCTION_HELPER void InternalDampingLayer_IFunction_Integrand(const State s, const NewtonianIdealGasContext context, CeedScalar amplitude, 11330b5892fSJames Wright CeedScalar length, CeedScalar start, CeedScalar location, CeedScalar pressure, 11430b5892fSJames Wright CeedScalar v_i[5], CeedScalar *sigma) { 11530b5892fSJames Wright const CeedScalar sigma_ = LinearRampCoefficient(amplitude, length, start, location); 11630b5892fSJames Wright CeedScalar damp_state[5] = {s.Y.pressure - pressure, 0, 0, 0, 0}, idl_residual[5] = {0.}; 11730b5892fSJames Wright InternalDampingLayer_Residual(context, s, sigma_, damp_state, idl_residual); 11830b5892fSJames Wright AXPY(1, idl_residual, v_i, 5); 11930b5892fSJames Wright *sigma = sigma_; 12030b5892fSJames Wright } 12130b5892fSJames Wright 122*8fd72709SJames Wright /** 123*8fd72709SJames Wright @brief IJacobian integrand for Internal Damping Layer 124*8fd72709SJames Wright 125*8fd72709SJames Wright @note This uses a Picard-type linearization of the damping and could be replaced by an `InternalDampingLayer_fwd` that uses s and ds. 126*8fd72709SJames Wright 127*8fd72709SJames Wright @param[in] s Solution `State` 128*8fd72709SJames Wright @param[in] ds Change in `State` of solution 129*8fd72709SJames Wright @param[in] context Newtonian context 130*8fd72709SJames Wright @param[in] sigma IDL ramp coefficient 131*8fd72709SJames Wright @param[inout] v_i Output to be multiplied by weight function, summed into 132*8fd72709SJames Wright **/ 133*8fd72709SJames Wright CEED_QFUNCTION_HELPER void InternalDampingLayer_IJacobian_Integrand(const State s, const State ds, const NewtonianIdealGasContext context, 134*8fd72709SJames Wright CeedScalar sigma, CeedScalar v_i[5]) { 135*8fd72709SJames Wright CeedScalar damp_state[5] = {ds.Y.pressure, 0, 0, 0, 0}, idl_residual[5] = {0.}; 136*8fd72709SJames Wright InternalDampingLayer_Residual(context, s, sigma, damp_state, idl_residual); 137*8fd72709SJames Wright AXPY(1, idl_residual, v_i, 5); 138*8fd72709SJames Wright } 139*8fd72709SJames Wright 140cbe60e31SLeila Ghaffari // ***************************************************************************** 14104e40bb6SJeremy L Thompson // This QFunction implements the following formulation of Navier-Stokes with explicit time stepping method 1423a8779fbSJames Wright // 14304e40bb6SJeremy L Thompson // This is 3D compressible Navier-Stokes in conservation form with state variables of density, momentum density, and total energy density. 1443a8779fbSJames Wright // 1453a8779fbSJames Wright // State Variables: q = ( rho, U1, U2, U3, E ) 1463a8779fbSJames Wright // rho - Mass Density 1473a8779fbSJames Wright // Ui - Momentum Density, Ui = rho ui 1483a8779fbSJames Wright // E - Total Energy Density, E = rho (cv T + (u u)/2 + g z) 1493a8779fbSJames Wright // 1503a8779fbSJames Wright // Navier-Stokes Equations: 1513a8779fbSJames Wright // drho/dt + div( U ) = 0 1523a8779fbSJames Wright // dU/dt + div( rho (u x u) + P I3 ) + rho g khat = div( Fu ) 1533a8779fbSJames Wright // dE/dt + div( (E + P) u ) = div( Fe ) 1543a8779fbSJames Wright // 1553a8779fbSJames Wright // Viscous Stress: 1563a8779fbSJames Wright // Fu = mu (grad( u ) + grad( u )^T + lambda div ( u ) I3) 1573a8779fbSJames Wright // 1583a8779fbSJames Wright // Thermal Stress: 1593a8779fbSJames Wright // Fe = u Fu + k grad( T ) 160bb8a0c61SJames Wright // Equation of State 1613a8779fbSJames Wright // P = (gamma - 1) (E - rho (u u) / 2 - rho g z) 1623a8779fbSJames Wright // 1633a8779fbSJames Wright // Stabilization: 1643a8779fbSJames Wright // Tau = diag(TauC, TauM, TauM, TauM, TauE) 1653a8779fbSJames Wright // f1 = rho sqrt(ui uj gij) 1663a8779fbSJames Wright // gij = dXi/dX * dXi/dX 1673a8779fbSJames Wright // TauC = Cc f1 / (8 gii) 1683a8779fbSJames Wright // TauM = min( 1 , 1 / f1 ) 1693a8779fbSJames Wright // TauE = TauM / (Ce cv) 1703a8779fbSJames Wright // 1713a8779fbSJames Wright // SU = Galerkin + grad(v) . ( Ai^T * Tau * (Aj q,j) ) 1723a8779fbSJames Wright // 1733a8779fbSJames Wright // Constants: 1743a8779fbSJames Wright // lambda = - 2 / 3, From Stokes hypothesis 1753a8779fbSJames Wright // mu , Dynamic viscosity 1763a8779fbSJames Wright // k , Thermal conductivity 1773a8779fbSJames Wright // cv , Specific heat, constant volume 1783a8779fbSJames Wright // cp , Specific heat, constant pressure 1793a8779fbSJames Wright // g , Gravity 1803a8779fbSJames Wright // gamma = cp / cv, Specific heat ratio 1813a8779fbSJames Wright // 18204e40bb6SJeremy 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 18304e40bb6SJeremy L Thompson // gradu ) 1843a8779fbSJames Wright // ***************************************************************************** 1852b916ea7SJeremy L Thompson CEED_QFUNCTION(RHSFunction_Newtonian)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 186b3b24828SJames Wright NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 187b3b24828SJames Wright const bool use_divFdiff = context->divFdiff_method != DIV_DIFF_FLUX_PROJ_NONE; 188b3b24828SJames Wright 1893d65b166SJames Wright const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 19087bd45e7SJames Wright const CeedScalar(*Grad_q) = in[1]; 191ade49511SJames Wright const CeedScalar(*q_data) = in[2]; 1920a32a5aaSJames Wright const CeedScalar(*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; 193b3b24828SJames Wright const CeedScalar(*divFdiff)[CEED_Q_VLA] = use_divFdiff ? (const CeedScalar(*)[CEED_Q_VLA])in[4] : NULL; 1943d65b166SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 1953d65b166SJames Wright CeedScalar(*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 1963a8779fbSJames Wright 197bb8a0c61SJames Wright const CeedScalar *g = context->g; 198bb8a0c61SJames Wright const CeedScalar dt = context->dt; 199b3b24828SJames Wright const CeedScalar idl_pressure = context->idl_pressure; 2003a8779fbSJames Wright 2013d65b166SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 202ade49511SJames Wright CeedScalar U[5], wdetJ, dXdx[3][3]; 2030a32a5aaSJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 204c1a52365SJed Brown for (int j = 0; j < 5; j++) U[j] = q[j][i]; 2051be49596SJames Wright QdataUnpack_3D(Q, i, q_data, &wdetJ, dXdx); 206edcfef1bSKenneth E. Jansen State s = StateFromU(context, U); 207c1a52365SJed Brown 208c1a52365SJed Brown State grad_s[3]; 209edcfef1bSKenneth E. Jansen StatePhysicalGradientFromReference(Q, i, context, s, STATEVAR_CONSERVATIVE, Grad_q, dXdx, grad_s); 210c1a52365SJed Brown 211c1a52365SJed Brown CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 21240a33f2dSJames Wright KMStrainRate_State(grad_s, strain_rate); 213c1a52365SJed Brown NewtonianStress(context, strain_rate, kmstress); 214c1a52365SJed Brown KMUnpack(kmstress, stress); 215c1a52365SJed Brown ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 216c1a52365SJed Brown 217c1a52365SJed Brown StateConservative F_inviscid[3]; 218c1a52365SJed Brown FluxInviscid(context, s, F_inviscid); 219c1a52365SJed Brown 220c1a52365SJed Brown // Total flux 221c1a52365SJed Brown CeedScalar Flux[5][3]; 222d1b9ef12SLeila Ghaffari FluxTotal(F_inviscid, stress, Fe, Flux); 223c1a52365SJed Brown 2247523f6aaSJames Wright for (CeedInt j = 0; j < 5; j++) { 2257523f6aaSJames 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]); 2262b916ea7SJeremy L Thompson } 227c1a52365SJed Brown 22860dbb574SKenneth 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)}; 2292b916ea7SJeremy L Thompson for (int j = 0; j < 5; j++) v[j][i] = wdetJ * body_force[j]; 2303a8779fbSJames Wright 2310a32a5aaSJames Wright if (context->idl_enable) { 2320a32a5aaSJames Wright const CeedScalar sigma = LinearRampCoefficient(context->idl_amplitude, context->idl_length, context->idl_start, x_i[0]); 233b3b24828SJames Wright CeedScalar damp_state[5] = {s.Y.pressure - idl_pressure, 0, 0, 0, 0}, idl_residual[5] = {0.}; 23430b5892fSJames Wright InternalDampingLayer_Residual(context, s, sigma, damp_state, idl_residual); 2350a32a5aaSJames Wright for (int j = 0; j < 5; j++) v[j][i] -= wdetJ * idl_residual[j]; 2360a32a5aaSJames Wright } 2370a32a5aaSJames Wright 238b3b24828SJames Wright CeedScalar divFdiff_i[5] = {0.}; 239b3b24828SJames Wright if (use_divFdiff) 240b3b24828SJames Wright for (int j = 1; j < 5; j++) divFdiff_i[j] = divFdiff[j - 1][i]; 241b3b24828SJames Wright 242d1b9ef12SLeila Ghaffari // -- Stabilization method: none (Galerkin), SU, or SUPG 243b3b24828SJames Wright CeedScalar Tau_d[3], stab[5][3], U_dot[5] = {0}; 244d1b9ef12SLeila Ghaffari Tau_diagPrim(context, s, dXdx, dt, Tau_d); 245b3b24828SJames Wright Stabilization(context, s, Tau_d, grad_s, U_dot, body_force, divFdiff_i, stab); 2463a8779fbSJames Wright 2472b916ea7SJeremy L Thompson for (CeedInt j = 0; j < 5; j++) { 2482b916ea7SJeremy 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]); 2492b916ea7SJeremy L Thompson } 250b193fadcSJames Wright } 2513a8779fbSJames Wright return 0; 2523a8779fbSJames Wright } 2533a8779fbSJames Wright 254e57b52dbSJames Wright /** 255e57b52dbSJames Wright @brief IFunction integrand of Navier-Stokes for Newtonian ideal gas 256e57b52dbSJames Wright 257e57b52dbSJames Wright This is used in the quadrature point loop within a larger QFunction. 258e57b52dbSJames Wright `v_i` and `dv_i` are summed into (meaning they must be some initialized value). 259e57b52dbSJames Wright `kmstress` and `Tau_d` are given to be included as Jacobian data. 260e57b52dbSJames Wright 261e57b52dbSJames Wright @param[in] s `State` of solution 262e57b52dbSJames Wright @param[in] grad_s Physical gradient of solution 263e57b52dbSJames Wright @param[in] s_dot Time derivative of solution 264e57b52dbSJames Wright @param[in] divFdiff_i Divergence of diffusive flux 265e57b52dbSJames Wright @param[in] x_i Coordinate location of quadrature point 266e57b52dbSJames Wright @param[in] context Newtonian context 267e57b52dbSJames Wright @param[in] dXdx Inverse of element mapping Jacobian (d\xi / dx) 268e57b52dbSJames Wright @param[inout] v_i Output to be multiplied by weight function, summed into 269e57b52dbSJames Wright @param[inout] grad_v_i Output to be multiplied by gradient of weight function, summed into 270e57b52dbSJames Wright @param[out] kmstress Viscous stress, in Kelvin-Mandel ordering 271e57b52dbSJames Wright @param[out] Tau_d Diagonal Tau coefficients 272e57b52dbSJames Wright **/ 27330b5892fSJames 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], 27430b5892fSJames Wright const CeedScalar x_i[3], const NewtonianIdealGasContext context, const CeedScalar dXdx[3][3], 275e57b52dbSJames Wright CeedScalar v_i[5], CeedScalar grad_v_i[5][3], CeedScalar kmstress[6], CeedScalar Tau_d[3]) { 276e57b52dbSJames Wright CeedScalar strain_rate[6], stress[3][3], F_visc_energy[3], F_total[5][3]; 277e57b52dbSJames Wright StateConservative F_inviscid[3]; 278e57b52dbSJames Wright const CeedScalar *g = context->g, dt = context->dt; 27930b5892fSJames Wright 280e57b52dbSJames Wright // Advective and viscous fluxes 28130b5892fSJames Wright KMStrainRate_State(grad_s, strain_rate); 28230b5892fSJames Wright NewtonianStress(context, strain_rate, kmstress); 28330b5892fSJames Wright KMUnpack(kmstress, stress); 284e57b52dbSJames Wright ViscousEnergyFlux(context, s.Y, grad_s, stress, F_visc_energy); 28530b5892fSJames Wright FluxInviscid(context, s, F_inviscid); 286e57b52dbSJames Wright FluxTotal(F_inviscid, stress, F_visc_energy, F_total); 287e57b52dbSJames Wright AXPY(-1, (CeedScalar *)F_total, (CeedScalar *)grad_v_i, 15); 28830b5892fSJames Wright 289e57b52dbSJames Wright // Body force and time derivative 29030b5892fSJames 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)}; 291e57b52dbSJames Wright CeedScalar U_dot[5]; 29230b5892fSJames Wright UnpackState_U(s_dot.U, U_dot); 29330b5892fSJames Wright for (CeedInt j = 0; j < 5; j++) v_i[j] += U_dot[j] - body_force[j]; 294e57b52dbSJames Wright 295e57b52dbSJames Wright // Stabilization 296e57b52dbSJames Wright CeedScalar stab[5][3]; 29730b5892fSJames Wright Tau_diagPrim(context, s, dXdx, dt, Tau_d); 29830b5892fSJames Wright Stabilization(context, s, Tau_d, grad_s, U_dot, body_force, divFdiff_i, stab); 299e57b52dbSJames Wright AXPY(1, (CeedScalar *)stab, (CeedScalar *)grad_v_i, 15); 30030b5892fSJames Wright } 30130b5892fSJames Wright 302e57b52dbSJames Wright // @brief State-independent IFunction of Navier-Stokes for Newtonian ideal gas 3038fff8293SJames Wright CEED_QFUNCTION_HELPER int IFunction_Newtonian(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateVariable state_var) { 3048c85b835SJames Wright NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 305ff684e42SJames Wright const bool use_divFdiff = context->divFdiff_method != DIV_DIFF_FLUX_PROJ_NONE; 3068c85b835SJames Wright 3073d65b166SJames Wright const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 308e57b52dbSJames Wright const CeedScalar(*grad_q) = in[1]; 3093d65b166SJames Wright const CeedScalar(*q_dot)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2]; 310ade49511SJames Wright const CeedScalar(*q_data) = in[3]; 3113d65b166SJames Wright const CeedScalar(*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 312ff684e42SJames Wright const CeedScalar(*divFdiff)[CEED_Q_VLA] = use_divFdiff ? (const CeedScalar(*)[CEED_Q_VLA])in[5] : NULL; 3133d65b166SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 314e57b52dbSJames Wright CeedScalar(*grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 315ade49511SJames Wright CeedScalar(*jac_data) = out[2]; 3163d65b166SJames Wright 3173d65b166SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 318e57b52dbSJames Wright const CeedScalar q_i[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 319e57b52dbSJames 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]}; 320c1a52365SJed Brown const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 321e57b52dbSJames Wright const State s = StateFromQ(context, q_i, state_var); 322e57b52dbSJames Wright const State s_dot = StateFromQ_fwd(context, s, q_i_dot, state_var); 323c1a52365SJed Brown 324ade49511SJames Wright CeedScalar wdetJ, dXdx[3][3]; 325ade49511SJames Wright QdataUnpack_3D(Q, i, q_data, &wdetJ, dXdx); 326c1a52365SJed Brown State grad_s[3]; 327e57b52dbSJames Wright StatePhysicalGradientFromReference(Q, i, context, s, state_var, grad_q, dXdx, grad_s); 3288c85b835SJames Wright CeedScalar divFdiff_i[5] = {0.}; 32930b5892fSJames Wright if (use_divFdiff) 3308c85b835SJames Wright for (int j = 1; j < 5; j++) divFdiff_i[j] = divFdiff[j - 1][i]; 3313a8779fbSJames Wright 332e57b52dbSJames Wright CeedScalar v_i[5] = {0.}, grad_v_i[5][3] = {{0.}}, kmstress[6], Tau_d[3], sigma; 333e57b52dbSJames Wright IFunction_Newtonian_Integrand(s, grad_s, s_dot, divFdiff_i, x_i, context, dXdx, v_i, grad_v_i, kmstress, Tau_d); 33430b5892fSJames Wright if (context->idl_enable) 33530b5892fSJames Wright InternalDampingLayer_IFunction_Integrand(s, context, context->idl_amplitude, context->idl_length, context->idl_start, x_i[0], 33630b5892fSJames Wright context->idl_pressure, v_i, &sigma); 33730b5892fSJames Wright 33830b5892fSJames Wright for (CeedInt j = 0; j < 5; j++) v[j][i] = wdetJ * v_i[j]; 3392b916ea7SJeremy L Thompson for (CeedInt j = 0; j < 5; j++) { 340*8fd72709SJames Wright for (CeedInt k = 0; k < 3; k++) 341e57b52dbSJames 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]); 3423d65b166SJames Wright } 34330b5892fSJames Wright 344e57b52dbSJames Wright StoredValuesPack(Q, i, 0, 5, q_i, jac_data); 345ade49511SJames Wright StoredValuesPack(Q, i, 5, 6, kmstress, jac_data); 346ade49511SJames Wright StoredValuesPack(Q, i, 11, 3, Tau_d, jac_data); 34730b5892fSJames Wright if (context->idl_enable) StoredValuesPack(Q, i, 14, 1, &sigma, jac_data); 348b193fadcSJames Wright } 3493a8779fbSJames Wright return 0; 3503a8779fbSJames Wright } 351f0b65372SJed Brown 3522b916ea7SJeremy L Thompson CEED_QFUNCTION(IFunction_Newtonian_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 3538fff8293SJames Wright return IFunction_Newtonian(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 35476555becSJames Wright } 35576555becSJames Wright 3562b916ea7SJeremy L Thompson CEED_QFUNCTION(IFunction_Newtonian_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 3578fff8293SJames Wright return IFunction_Newtonian(ctx, Q, in, out, STATEVAR_PRIMITIVE); 35876555becSJames Wright } 35976555becSJames Wright 3609b103f75SJames Wright CEED_QFUNCTION(IFunction_Newtonian_Entropy)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 3619b103f75SJames Wright return IFunction_Newtonian(ctx, Q, in, out, STATEVAR_ENTROPY); 3629b103f75SJames Wright } 3639b103f75SJames Wright 364*8fd72709SJames Wright /** 365*8fd72709SJames Wright @brief IJacobian integrand of Navier-Stokes for Newtonian ideal gas 3663d65b166SJames Wright 367*8fd72709SJames Wright This is used in the quadrature point loop within a larger QFunction. 368*8fd72709SJames Wright `v_i` and `dv_i` are summed into (meaning they must be some initialized value). 369*8fd72709SJames Wright `kmstress` and `Tau_d` are (generally) calculated and stored by the IFunction. 370*8fd72709SJames Wright 371*8fd72709SJames Wright @param[in] s `State` of solution 372*8fd72709SJames Wright @param[in] ds Change in `State` of solution 373*8fd72709SJames Wright @param[in] grad_ds Physical gradient of change in `State` of solution 374*8fd72709SJames Wright @param[in] context Newtonian context 375*8fd72709SJames Wright @param[in] kmstress Viscous stress, in Kelvin-Mandel ordering 376*8fd72709SJames Wright @param[in] Tau_d Diagonal Tau coefficients 377*8fd72709SJames Wright @param[inout] v_i Output to be multiplied by weight function, summed into 378*8fd72709SJames Wright @param[inout] grad_v_i Output to be multiplied by gradient of weight function, summed into 379*8fd72709SJames Wright **/ 380*8fd72709SJames Wright CEED_QFUNCTION_HELPER void IJacobian_Newtonian_Integrand(const State s, const State ds, const State grad_ds[3], 381*8fd72709SJames Wright const NewtonianIdealGasContext context, const CeedScalar kmstress[6], 382*8fd72709SJames Wright const CeedScalar Tau_d[3], CeedScalar v_i[5], CeedScalar grad_v_i[5][3]) { 383f0b65372SJed Brown const CeedScalar *g = context->g; 384*8fd72709SJames Wright CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dF_visc_energy[3], dF_total[5][3]; 385*8fd72709SJames Wright StateConservative dF_inviscid[3]; 386f0b65372SJed Brown 387*8fd72709SJames Wright // Advective and viscous fluxes 38840a33f2dSJames Wright KMStrainRate_State(grad_ds, dstrain_rate); 389f0b65372SJed Brown NewtonianStress(context, dstrain_rate, dkmstress); 390f0b65372SJed Brown KMUnpack(dkmstress, dstress); 391f0b65372SJed Brown KMUnpack(kmstress, stress); 392*8fd72709SJames Wright ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dF_visc_energy); 393f0b65372SJed Brown FluxInviscid_fwd(context, s, ds, dF_inviscid); 394*8fd72709SJames Wright FluxTotal(dF_inviscid, dstress, dF_visc_energy, dF_total); 395*8fd72709SJames Wright AXPY(-1, (CeedScalar *)dF_total, (CeedScalar *)grad_v_i, 15); 396f0b65372SJed Brown 397*8fd72709SJames Wright // Body force and time derivative 39860dbb574SKenneth 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)}; 399*8fd72709SJames Wright CeedScalar dU[5], dU_dot[5]; 40076555becSJames Wright UnpackState_U(ds.U, dU); 401*8fd72709SJames Wright for (CeedInt j = 0; j < 5; j++) { 402*8fd72709SJames Wright dU_dot[j] = context->ijacobian_time_shift * dU[j]; 403*8fd72709SJames Wright v_i[j] = dU_dot[j] - dbody_force[j]; 404e7754af5SKenneth E. Jansen } 405e7754af5SKenneth E. Jansen 406*8fd72709SJames Wright // Stabilization 407*8fd72709SJames Wright CeedScalar dstab[5][3]; 4088c85b835SJames Wright const CeedScalar zeroFlux[5] = {0.}; 409*8fd72709SJames Wright Stabilization(context, s, Tau_d, grad_ds, dU_dot, dbody_force, zeroFlux, dstab); 410*8fd72709SJames Wright AXPY(1, (CeedScalar *)dstab, (CeedScalar *)grad_v_i, 15); 411*8fd72709SJames Wright } 412d1b9ef12SLeila Ghaffari 413*8fd72709SJames Wright // @brief State-independent IJacobian of Navier-Stokes for Newtonian ideal gas 414*8fd72709SJames Wright CEED_QFUNCTION_HELPER int IJacobian_Newtonian(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateVariable state_var) { 415*8fd72709SJames Wright const CeedScalar(*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 416*8fd72709SJames Wright const CeedScalar(*grad_dq) = in[1]; 417*8fd72709SJames Wright const CeedScalar(*q_data) = in[2]; 418*8fd72709SJames Wright const CeedScalar(*jac_data) = in[3]; 419*8fd72709SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 420*8fd72709SJames Wright CeedScalar(*grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 421*8fd72709SJames Wright 422*8fd72709SJames Wright NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 423*8fd72709SJames Wright 424*8fd72709SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 425*8fd72709SJames Wright const CeedScalar dq_i[5] = {dq[0][i], dq[1][i], dq[2][i], dq[3][i], dq[4][i]}; 426*8fd72709SJames Wright CeedScalar qi[5], kmstress[6], Tau_d[3]; 427*8fd72709SJames Wright StoredValuesUnpack(Q, i, 0, 5, jac_data, qi); 428*8fd72709SJames Wright StoredValuesUnpack(Q, i, 5, 6, jac_data, kmstress); 429*8fd72709SJames Wright StoredValuesUnpack(Q, i, 11, 3, jac_data, Tau_d); 430*8fd72709SJames Wright const State s = StateFromQ(context, qi, state_var); 431*8fd72709SJames Wright const State ds = StateFromQ_fwd(context, s, dq_i, state_var); 432*8fd72709SJames Wright 433*8fd72709SJames Wright CeedScalar wdetJ, dXdx[3][3]; 434*8fd72709SJames Wright QdataUnpack_3D(Q, i, q_data, &wdetJ, dXdx); 435*8fd72709SJames Wright State grad_ds[3]; 436*8fd72709SJames Wright StatePhysicalGradientFromReference(Q, i, context, s, state_var, grad_dq, dXdx, grad_ds); 437*8fd72709SJames Wright 438*8fd72709SJames Wright CeedScalar v_i[5] = {0.}, grad_v_i[5][3] = {{0.}}; 439*8fd72709SJames Wright IJacobian_Newtonian_Integrand(s, ds, grad_ds, context, kmstress, Tau_d, v_i, grad_v_i); 440*8fd72709SJames Wright if (context->idl_enable) { 441*8fd72709SJames Wright CeedScalar sigma; 442*8fd72709SJames Wright StoredValuesUnpack(Q, i, 14, 1, jac_data, &sigma); 443*8fd72709SJames Wright InternalDampingLayer_IJacobian_Integrand(s, ds, context, sigma, v_i); 444*8fd72709SJames Wright for (int j = 0; j < 5; j++) v[j][i] += wdetJ * v_i[j]; 445*8fd72709SJames Wright } 446*8fd72709SJames Wright 447*8fd72709SJames Wright for (CeedInt j = 0; j < 5; j++) v[j][i] = wdetJ * v_i[j]; 4482b916ea7SJeremy L Thompson for (int j = 0; j < 5; j++) { 449*8fd72709SJames 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]); 4502b916ea7SJeremy L Thompson } 451b193fadcSJames Wright } 452f0b65372SJed Brown return 0; 453f0b65372SJed Brown } 4548085925cSJames Wright 4552b916ea7SJeremy L Thompson CEED_QFUNCTION(IJacobian_Newtonian_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 4568fff8293SJames Wright return IJacobian_Newtonian(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 45776555becSJames Wright } 45876555becSJames Wright 4592b916ea7SJeremy L Thompson CEED_QFUNCTION(IJacobian_Newtonian_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 4608fff8293SJames Wright return IJacobian_Newtonian(ctx, Q, in, out, STATEVAR_PRIMITIVE); 46176555becSJames Wright } 46276555becSJames Wright 4639b103f75SJames Wright CEED_QFUNCTION(IJacobian_Newtonian_Entropy)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 4649b103f75SJames Wright return IJacobian_Newtonian(ctx, Q, in, out, STATEVAR_ENTROPY); 4659b103f75SJames Wright } 4669b103f75SJames Wright 467d1b9ef12SLeila Ghaffari // ***************************************************************************** 4688085925cSJames Wright // Compute boundary integral (ie. for strongly set inflows) 469d1b9ef12SLeila Ghaffari // ***************************************************************************** 4708fff8293SJames Wright CEED_QFUNCTION_HELPER int BoundaryIntegral(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateVariable state_var) { 4714b96a86bSJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 4723d65b166SJames Wright const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 47387bd45e7SJames Wright const CeedScalar(*Grad_q) = in[1]; 474ade49511SJames Wright const CeedScalar(*q_data_sur) = in[2]; 4753d65b166SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 4764b96a86bSJames Wright CeedScalar(*jac_data_sur) = context->is_implicit ? out[1] : NULL; 4778085925cSJames Wright 478d3b25f3aSJames Wright const bool is_implicit = context->is_implicit; 4798085925cSJames Wright 4802b916ea7SJeremy L Thompson CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 48141e73928SJames Wright const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 482edcfef1bSKenneth E. Jansen State s = StateFromQ(context, qi, state_var); 4838085925cSJames Wright 48478e8b7daSJames Wright CeedScalar wdetJb, dXdx[2][3], normal[3]; 48578e8b7daSJames Wright QdataBoundaryUnpack_3D(Q, i, q_data_sur, &wdetJb, dXdx, normal); 486ade49511SJames Wright wdetJb *= is_implicit ? -1. : 1.; 4878085925cSJames Wright 488d3b25f3aSJames Wright State grad_s[3]; 489edcfef1bSKenneth E. Jansen StatePhysicalGradientFromReference_Boundary(Q, i, context, s, state_var, Grad_q, dXdx, grad_s); 4908085925cSJames Wright 491d3b25f3aSJames Wright CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 49240a33f2dSJames Wright KMStrainRate_State(grad_s, strain_rate); 493d3b25f3aSJames Wright NewtonianStress(context, strain_rate, kmstress); 494d3b25f3aSJames Wright KMUnpack(kmstress, stress); 495d3b25f3aSJames Wright ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 496d3b25f3aSJames Wright 497d3b25f3aSJames Wright StateConservative F_inviscid[3]; 498d3b25f3aSJames Wright FluxInviscid(context, s, F_inviscid); 499d3b25f3aSJames Wright 500c5740391SJames Wright CeedScalar Flux[5]; 50178e8b7daSJames Wright FluxTotal_Boundary(F_inviscid, stress, Fe, normal, Flux); 502d3b25f3aSJames Wright 503c5740391SJames Wright for (CeedInt j = 0; j < 5; j++) v[j][i] = -wdetJb * Flux[j]; 5048085925cSJames Wright 5054b96a86bSJames Wright if (is_implicit) { 506ade49511SJames Wright StoredValuesPack(Q, i, 0, 5, qi, jac_data_sur); 507ade49511SJames Wright StoredValuesPack(Q, i, 5, 6, kmstress, jac_data_sur); 5088085925cSJames Wright } 5094b96a86bSJames Wright } 5108085925cSJames Wright return 0; 5118085925cSJames Wright } 5128085925cSJames Wright 5132b916ea7SJeremy L Thompson CEED_QFUNCTION(BoundaryIntegral_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 5148fff8293SJames Wright return BoundaryIntegral(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 515d4559bbeSJames Wright } 516d4559bbeSJames Wright 5172b916ea7SJeremy L Thompson CEED_QFUNCTION(BoundaryIntegral_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 5188fff8293SJames Wright return BoundaryIntegral(ctx, Q, in, out, STATEVAR_PRIMITIVE); 519d4559bbeSJames Wright } 520d4559bbeSJames Wright 5219b103f75SJames Wright CEED_QFUNCTION(BoundaryIntegral_Entropy)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 5229b103f75SJames Wright return BoundaryIntegral(ctx, Q, in, out, STATEVAR_ENTROPY); 5239b103f75SJames Wright } 5249b103f75SJames Wright 525d1b9ef12SLeila Ghaffari // ***************************************************************************** 52668ae065aSJames Wright // Jacobian for "set nothing" boundary integral 527d1b9ef12SLeila Ghaffari // ***************************************************************************** 5282b916ea7SJeremy L Thompson CEED_QFUNCTION_HELPER int BoundaryIntegral_Jacobian(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, 5298fff8293SJames Wright StateVariable state_var) { 5303d65b166SJames Wright const CeedScalar(*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 53187bd45e7SJames Wright const CeedScalar(*Grad_dq) = in[1]; 532ade49511SJames Wright const CeedScalar(*q_data_sur) = in[2]; 533c1484fadSKenneth E. Jansen const CeedScalar(*jac_data_sur) = in[4]; 53468ae065aSJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 53568ae065aSJames Wright 53668ae065aSJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 537ade49511SJames Wright const bool is_implicit = context->is_implicit; 53868ae065aSJames Wright 5393d65b166SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 54078e8b7daSJames Wright CeedScalar wdetJb, dXdx[2][3], normal[3]; 54178e8b7daSJames Wright QdataBoundaryUnpack_3D(Q, i, q_data_sur, &wdetJb, dXdx, normal); 542ade49511SJames Wright wdetJb *= is_implicit ? -1. : 1.; 54368ae065aSJames Wright 544edcfef1bSKenneth E. Jansen CeedScalar qi[5], kmstress[6], dqi[5]; 545ade49511SJames Wright StoredValuesUnpack(Q, i, 0, 5, jac_data_sur, qi); 546ade49511SJames Wright StoredValuesUnpack(Q, i, 5, 6, jac_data_sur, kmstress); 54741e73928SJames Wright for (int j = 0; j < 5; j++) dqi[j] = dq[j][i]; 5483934e2b1SJames Wright 549edcfef1bSKenneth E. Jansen State s = StateFromQ(context, qi, state_var); 550edcfef1bSKenneth E. Jansen State ds = StateFromQ_fwd(context, s, dqi, state_var); 55168ae065aSJames Wright 55268ae065aSJames Wright State grad_ds[3]; 553edcfef1bSKenneth E. Jansen StatePhysicalGradientFromReference_Boundary(Q, i, context, s, state_var, Grad_dq, dXdx, grad_ds); 55468ae065aSJames Wright 55568ae065aSJames Wright CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 55640a33f2dSJames Wright KMStrainRate_State(grad_ds, dstrain_rate); 55768ae065aSJames Wright NewtonianStress(context, dstrain_rate, dkmstress); 55868ae065aSJames Wright KMUnpack(dkmstress, dstress); 55968ae065aSJames Wright KMUnpack(kmstress, stress); 56068ae065aSJames Wright ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 56168ae065aSJames Wright 56268ae065aSJames Wright StateConservative dF_inviscid[3]; 56368ae065aSJames Wright FluxInviscid_fwd(context, s, ds, dF_inviscid); 56468ae065aSJames Wright 565c5740391SJames Wright CeedScalar dFlux[5]; 56678e8b7daSJames Wright FluxTotal_Boundary(dF_inviscid, dstress, dFe, normal, dFlux); 56768ae065aSJames Wright 568c5740391SJames Wright for (int j = 0; j < 5; j++) v[j][i] = -wdetJb * dFlux[j]; 569512c8ec7SJames Wright } 57068ae065aSJames Wright return 0; 57168ae065aSJames Wright } 57268ae065aSJames Wright 5732b916ea7SJeremy L Thompson CEED_QFUNCTION(BoundaryIntegral_Jacobian_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 5748fff8293SJames Wright return BoundaryIntegral_Jacobian(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 575d4559bbeSJames Wright } 576d4559bbeSJames Wright 5772b916ea7SJeremy L Thompson CEED_QFUNCTION(BoundaryIntegral_Jacobian_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 5788fff8293SJames Wright return BoundaryIntegral_Jacobian(ctx, Q, in, out, STATEVAR_PRIMITIVE); 579d4559bbeSJames Wright } 5809b103f75SJames Wright 5819b103f75SJames Wright CEED_QFUNCTION(BoundaryIntegral_Jacobian_Entropy)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 5829b103f75SJames Wright return BoundaryIntegral_Jacobian(ctx, Q, in, out, STATEVAR_ENTROPY); 5839b103f75SJames Wright } 58436038bbcSJames Wright 5858561fee2SJames Wright // @brief Volume integral for RHS of divergence of diffusive flux direct projection 58636038bbcSJames Wright CEED_QFUNCTION_HELPER int DivDiffusiveFluxVolumeRHS_NS(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, 58736038bbcSJames Wright StateVariable state_var) { 58836038bbcSJames Wright const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 58936038bbcSJames Wright const CeedScalar(*Grad_q) = in[1]; 59036038bbcSJames Wright const CeedScalar(*q_data) = in[2]; 59136038bbcSJames Wright CeedScalar(*Grad_v)[4][CEED_Q_VLA] = (CeedScalar(*)[4][CEED_Q_VLA])out[0]; 59236038bbcSJames Wright 59336038bbcSJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 59436038bbcSJames Wright const StateConservative ZeroInviscidFluxes[3] = {{0}}; 59536038bbcSJames Wright 59636038bbcSJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 59736038bbcSJames Wright const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 59836038bbcSJames Wright const State s = StateFromQ(context, qi, state_var); 59936038bbcSJames Wright CeedScalar wdetJ, dXdx[3][3]; 60036038bbcSJames Wright CeedScalar stress[3][3], Fe[3], Fdiff[5][3]; 60136038bbcSJames Wright 60236038bbcSJames Wright QdataUnpack_3D(Q, i, q_data, &wdetJ, dXdx); 60336038bbcSJames Wright { // Get stress and Fe 60436038bbcSJames Wright State grad_s[3]; 60536038bbcSJames Wright CeedScalar strain_rate[6], kmstress[6]; 60636038bbcSJames Wright 60736038bbcSJames Wright StatePhysicalGradientFromReference(Q, i, context, s, state_var, Grad_q, dXdx, grad_s); 60836038bbcSJames Wright KMStrainRate_State(grad_s, strain_rate); 60936038bbcSJames Wright NewtonianStress(context, strain_rate, kmstress); 61036038bbcSJames Wright KMUnpack(kmstress, stress); 61136038bbcSJames Wright ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 61236038bbcSJames Wright } 61336038bbcSJames Wright 61436038bbcSJames Wright FluxTotal(ZeroInviscidFluxes, stress, Fe, Fdiff); 61536038bbcSJames Wright 61636038bbcSJames Wright for (CeedInt j = 1; j < 5; j++) { // Continuity has no diffusive flux, therefore skip 61736038bbcSJames Wright for (CeedInt k = 0; k < 3; k++) { 61836038bbcSJames Wright Grad_v[k][j - 1][i] = -wdetJ * Dot3(dXdx[k], Fdiff[j]); 61936038bbcSJames Wright } 62036038bbcSJames Wright } 62136038bbcSJames Wright } 62236038bbcSJames Wright return 0; 62336038bbcSJames Wright } 62436038bbcSJames Wright 62536038bbcSJames Wright CEED_QFUNCTION(DivDiffusiveFluxVolumeRHS_NS_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 62636038bbcSJames Wright return DivDiffusiveFluxVolumeRHS_NS(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 62736038bbcSJames Wright } 62836038bbcSJames Wright 62936038bbcSJames Wright CEED_QFUNCTION(DivDiffusiveFluxVolumeRHS_NS_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 63036038bbcSJames Wright return DivDiffusiveFluxVolumeRHS_NS(ctx, Q, in, out, STATEVAR_PRIMITIVE); 63136038bbcSJames Wright } 63236038bbcSJames Wright 63336038bbcSJames Wright CEED_QFUNCTION(DivDiffusiveFluxVolumeRHS_NS_Entropy)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 63436038bbcSJames Wright return DivDiffusiveFluxVolumeRHS_NS(ctx, Q, in, out, STATEVAR_ENTROPY); 63536038bbcSJames Wright } 63636038bbcSJames Wright 6378561fee2SJames Wright // @brief Boundary integral for RHS of divergence of diffusive flux direct projection 63836038bbcSJames Wright CEED_QFUNCTION_HELPER int DivDiffusiveFluxBoundaryRHS_NS(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, 63936038bbcSJames Wright StateVariable state_var) { 64036038bbcSJames Wright const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 64136038bbcSJames Wright const CeedScalar(*Grad_q) = in[1]; 64236038bbcSJames Wright const CeedScalar(*q_data) = in[2]; 64336038bbcSJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 64436038bbcSJames Wright 64536038bbcSJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 64636038bbcSJames Wright const StateConservative ZeroInviscidFluxes[3] = {{0}}; 64736038bbcSJames Wright 64836038bbcSJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 64936038bbcSJames Wright const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 65036038bbcSJames Wright const State s = StateFromQ(context, qi, state_var); 65136038bbcSJames Wright CeedScalar wdetJ, dXdx[3][3], normal[3]; 65236038bbcSJames Wright CeedScalar stress[3][3], Fe[3], Fdiff[5]; 65336038bbcSJames Wright 65436038bbcSJames Wright QdataBoundaryGradientUnpack_3D(Q, i, q_data, &wdetJ, dXdx, normal); 65536038bbcSJames Wright { // Get stress and Fe 65636038bbcSJames Wright State grad_s[3]; 65736038bbcSJames Wright CeedScalar strain_rate[6], kmstress[6]; 65836038bbcSJames Wright 65936038bbcSJames Wright StatePhysicalGradientFromReference(Q, i, context, s, state_var, Grad_q, dXdx, grad_s); 66036038bbcSJames Wright KMStrainRate_State(grad_s, strain_rate); 66136038bbcSJames Wright NewtonianStress(context, strain_rate, kmstress); 66236038bbcSJames Wright KMUnpack(kmstress, stress); 66336038bbcSJames Wright ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 66436038bbcSJames Wright } 66536038bbcSJames Wright 66636038bbcSJames Wright FluxTotal_Boundary(ZeroInviscidFluxes, stress, Fe, normal, Fdiff); 66736038bbcSJames Wright 66836038bbcSJames Wright // Continuity has no diffusive flux, therefore skip 66936038bbcSJames Wright for (CeedInt j = 1; j < 5; j++) v[j - 1][i] = wdetJ * Fdiff[j]; 67036038bbcSJames Wright } 67136038bbcSJames Wright return 0; 67236038bbcSJames Wright } 67336038bbcSJames Wright 67436038bbcSJames Wright CEED_QFUNCTION(DivDiffusiveFluxBoundaryRHS_NS_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 67536038bbcSJames Wright return DivDiffusiveFluxBoundaryRHS_NS(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 67636038bbcSJames Wright } 67736038bbcSJames Wright 67836038bbcSJames Wright CEED_QFUNCTION(DivDiffusiveFluxBoundaryRHS_NS_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 67936038bbcSJames Wright return DivDiffusiveFluxBoundaryRHS_NS(ctx, Q, in, out, STATEVAR_PRIMITIVE); 68036038bbcSJames Wright } 68136038bbcSJames Wright 68236038bbcSJames Wright CEED_QFUNCTION(DivDiffusiveFluxBoundaryRHS_NS_Entropy)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 68336038bbcSJames Wright return DivDiffusiveFluxBoundaryRHS_NS(ctx, Q, in, out, STATEVAR_ENTROPY); 68436038bbcSJames Wright } 68536038bbcSJames Wright 6868561fee2SJames Wright // @brief Integral for RHS of diffusive flux indirect projection 68736038bbcSJames Wright CEED_QFUNCTION_HELPER int DiffusiveFluxRHS_NS(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateVariable state_var) { 68836038bbcSJames Wright const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 68936038bbcSJames Wright const CeedScalar(*Grad_q) = in[1]; 69036038bbcSJames Wright const CeedScalar(*q_data) = in[2]; 69136038bbcSJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 69236038bbcSJames Wright 69336038bbcSJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 69436038bbcSJames Wright const StateConservative ZeroInviscidFluxes[3] = {{0}}; 69536038bbcSJames Wright 69636038bbcSJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 69736038bbcSJames Wright const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 69836038bbcSJames Wright const State s = StateFromQ(context, qi, state_var); 69936038bbcSJames Wright CeedScalar wdetJ, dXdx[3][3]; 70036038bbcSJames Wright CeedScalar stress[3][3], Fe[3], Fdiff[5][3]; 70136038bbcSJames Wright 70236038bbcSJames Wright QdataUnpack_3D(Q, i, q_data, &wdetJ, dXdx); 70336038bbcSJames Wright { // Get stress and Fe 70436038bbcSJames Wright State grad_s[3]; 70536038bbcSJames Wright CeedScalar strain_rate[6], kmstress[6]; 70636038bbcSJames Wright 70736038bbcSJames Wright StatePhysicalGradientFromReference(Q, i, context, s, state_var, Grad_q, dXdx, grad_s); 70836038bbcSJames Wright KMStrainRate_State(grad_s, strain_rate); 70936038bbcSJames Wright NewtonianStress(context, strain_rate, kmstress); 71036038bbcSJames Wright KMUnpack(kmstress, stress); 71136038bbcSJames Wright ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 71236038bbcSJames Wright } 71336038bbcSJames Wright 71436038bbcSJames Wright FluxTotal(ZeroInviscidFluxes, stress, Fe, Fdiff); 71536038bbcSJames Wright 71636038bbcSJames Wright for (CeedInt j = 1; j < 5; j++) { // Continuity has no diffusive flux, therefore skip 71736038bbcSJames Wright for (CeedInt k = 0; k < 3; k++) { 71836038bbcSJames Wright v[(j - 1) * 3 + k][i] = wdetJ * Fdiff[j][k]; 71936038bbcSJames Wright } 72036038bbcSJames Wright } 72136038bbcSJames Wright } 72236038bbcSJames Wright return 0; 72336038bbcSJames Wright } 72436038bbcSJames Wright 72536038bbcSJames Wright CEED_QFUNCTION(DiffusiveFluxRHS_NS_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 72636038bbcSJames Wright return DiffusiveFluxRHS_NS(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 72736038bbcSJames Wright } 72836038bbcSJames Wright 72936038bbcSJames Wright CEED_QFUNCTION(DiffusiveFluxRHS_NS_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 73036038bbcSJames Wright return DiffusiveFluxRHS_NS(ctx, Q, in, out, STATEVAR_PRIMITIVE); 73136038bbcSJames Wright } 73236038bbcSJames Wright 73336038bbcSJames Wright CEED_QFUNCTION(DiffusiveFluxRHS_NS_Entropy)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 73436038bbcSJames Wright return DiffusiveFluxRHS_NS(ctx, Q, in, out, STATEVAR_ENTROPY); 73536038bbcSJames Wright } 736