1727da7e7SJeremy L Thompson // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors. 2727da7e7SJeremy L Thompson // All Rights Reserved. See the top-level LICENSE and NOTICE files for details. 33a8779fbSJames Wright // 4727da7e7SJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause 53a8779fbSJames Wright // 6727da7e7SJeremy L Thompson // This file is part of CEED: http://github.com/ceed 73a8779fbSJames Wright 83a8779fbSJames Wright /// @file 93a8779fbSJames Wright /// Operator for Navier-Stokes example using PETSc 103a8779fbSJames Wright 113a8779fbSJames Wright #ifndef newtonian_h 123a8779fbSJames Wright #define newtonian_h 133a8779fbSJames Wright 143a8779fbSJames Wright #include <ceed.h> 15d0cce58aSJeremy L Thompson #include <math.h> 167b530f2aSAdelekeBankole #include <stdlib.h> 172b916ea7SJeremy L Thompson 18475b2820SJames Wright #include "newtonian_state.h" 19d0cce58aSJeremy L Thompson #include "newtonian_types.h" 20d1b9ef12SLeila Ghaffari #include "stabilization.h" 21d0cce58aSJeremy L Thompson #include "utils.h" 22bb8a0c61SJames Wright 23e7754af5SKenneth E. Jansen CEED_QFUNCTION_HELPER void InternalDampingLayer(const NewtonianIdealGasContext context, const State s, const CeedScalar x_i[3], CeedScalar damp_Y[5], 24e7754af5SKenneth E. Jansen CeedScalar damp_residual[5]) { 25e7754af5SKenneth E. Jansen const CeedScalar sigma = LinearRampCoefficient(context->idl_amplitude, context->idl_length, context->idl_start, x_i[0]); 26e7754af5SKenneth E. Jansen ScaleN(damp_Y, sigma, 5); 27*edcfef1bSKenneth E. Jansen State damp_s = StateFromY_fwd(context, s, damp_Y); 28e7754af5SKenneth E. Jansen 29e7754af5SKenneth E. Jansen CeedScalar U[5]; 30e7754af5SKenneth E. Jansen UnpackState_U(damp_s.U, U); 31e7754af5SKenneth E. Jansen for (int i = 0; i < 5; i++) damp_residual[i] += U[i]; 32e7754af5SKenneth E. Jansen } 33e7754af5SKenneth E. Jansen 34bb8a0c61SJames Wright // ***************************************************************************** 353a8779fbSJames Wright // This QFunction sets a "still" initial condition for generic Newtonian IG problems 363a8779fbSJames Wright // ***************************************************************************** 378fff8293SJames Wright CEED_QFUNCTION_HELPER int ICsNewtonianIG(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateVariable state_var) { 383a8779fbSJames Wright // Inputs 393a8779fbSJames Wright const CeedScalar(*X)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 403a8779fbSJames Wright 413a8779fbSJames Wright // Outputs 423a8779fbSJames Wright CeedScalar(*q0)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 433a8779fbSJames Wright 44bb8a0c61SJames Wright // Context 45bb8a0c61SJames Wright const SetupContext context = (SetupContext)ctx; 46bb8a0c61SJames Wright 473a8779fbSJames Wright // Quadrature Point Loop 482b916ea7SJeremy L Thompson CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 49b8fb7609SAdeleke O. Bankole CeedScalar x[3] = {X[0][i], X[1][i], X[2][i]}; 503a8779fbSJames Wright CeedScalar q[5] = {0.}; 51*edcfef1bSKenneth E. Jansen State s = StateFromPrimitive(&context->gas, context->reference); 528fff8293SJames Wright StateToQ(&context->gas, s, q, state_var); 532b916ea7SJeremy L Thompson for (CeedInt j = 0; j < 5; j++) q0[j][i] = q[j]; 543a8779fbSJames Wright } // End of Quadrature Point Loop 553a8779fbSJames Wright return 0; 563a8779fbSJames Wright } 573a8779fbSJames Wright 582b916ea7SJeremy L Thompson CEED_QFUNCTION(ICsNewtonianIG_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 598fff8293SJames Wright return ICsNewtonianIG(ctx, Q, in, out, STATEVAR_PRIMITIVE); 60b8fb7609SAdeleke O. Bankole } 61b8fb7609SAdeleke O. Bankole CEED_QFUNCTION(ICsNewtonianIG_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 628fff8293SJames Wright return ICsNewtonianIG(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 63cbe60e31SLeila Ghaffari } 64cbe60e31SLeila Ghaffari 65cbe60e31SLeila Ghaffari // ***************************************************************************** 6604e40bb6SJeremy L Thompson // This QFunction implements the following formulation of Navier-Stokes with explicit time stepping method 673a8779fbSJames Wright // 6804e40bb6SJeremy L Thompson // This is 3D compressible Navier-Stokes in conservation form with state variables of density, momentum density, and total energy density. 693a8779fbSJames Wright // 703a8779fbSJames Wright // State Variables: q = ( rho, U1, U2, U3, E ) 713a8779fbSJames Wright // rho - Mass Density 723a8779fbSJames Wright // Ui - Momentum Density, Ui = rho ui 733a8779fbSJames Wright // E - Total Energy Density, E = rho (cv T + (u u)/2 + g z) 743a8779fbSJames Wright // 753a8779fbSJames Wright // Navier-Stokes Equations: 763a8779fbSJames Wright // drho/dt + div( U ) = 0 773a8779fbSJames Wright // dU/dt + div( rho (u x u) + P I3 ) + rho g khat = div( Fu ) 783a8779fbSJames Wright // dE/dt + div( (E + P) u ) = div( Fe ) 793a8779fbSJames Wright // 803a8779fbSJames Wright // Viscous Stress: 813a8779fbSJames Wright // Fu = mu (grad( u ) + grad( u )^T + lambda div ( u ) I3) 823a8779fbSJames Wright // 833a8779fbSJames Wright // Thermal Stress: 843a8779fbSJames Wright // Fe = u Fu + k grad( T ) 85bb8a0c61SJames Wright // Equation of State 863a8779fbSJames Wright // P = (gamma - 1) (E - rho (u u) / 2 - rho g z) 873a8779fbSJames Wright // 883a8779fbSJames Wright // Stabilization: 893a8779fbSJames Wright // Tau = diag(TauC, TauM, TauM, TauM, TauE) 903a8779fbSJames Wright // f1 = rho sqrt(ui uj gij) 913a8779fbSJames Wright // gij = dXi/dX * dXi/dX 923a8779fbSJames Wright // TauC = Cc f1 / (8 gii) 933a8779fbSJames Wright // TauM = min( 1 , 1 / f1 ) 943a8779fbSJames Wright // TauE = TauM / (Ce cv) 953a8779fbSJames Wright // 963a8779fbSJames Wright // SU = Galerkin + grad(v) . ( Ai^T * Tau * (Aj q,j) ) 973a8779fbSJames Wright // 983a8779fbSJames Wright // Constants: 993a8779fbSJames Wright // lambda = - 2 / 3, From Stokes hypothesis 1003a8779fbSJames Wright // mu , Dynamic viscosity 1013a8779fbSJames Wright // k , Thermal conductivity 1023a8779fbSJames Wright // cv , Specific heat, constant volume 1033a8779fbSJames Wright // cp , Specific heat, constant pressure 1043a8779fbSJames Wright // g , Gravity 1053a8779fbSJames Wright // gamma = cp / cv, Specific heat ratio 1063a8779fbSJames Wright // 10704e40bb6SJeremy 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 10804e40bb6SJeremy L Thompson // gradu ) 1093a8779fbSJames Wright // ***************************************************************************** 1102b916ea7SJeremy L Thompson CEED_QFUNCTION(RHSFunction_Newtonian)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 1113a8779fbSJames Wright // Inputs 1123d65b166SJames Wright const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 11387bd45e7SJames Wright const CeedScalar(*Grad_q) = in[1]; 114ade49511SJames Wright const CeedScalar(*q_data) = in[2]; 1153d65b166SJames Wright const CeedScalar(*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; 1163d65b166SJames Wright 1173a8779fbSJames Wright // Outputs 1183d65b166SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 1193d65b166SJames Wright CeedScalar(*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 1203a8779fbSJames Wright 1213a8779fbSJames Wright // Context 1223a8779fbSJames Wright NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 123bb8a0c61SJames Wright const CeedScalar *g = context->g; 124bb8a0c61SJames Wright const CeedScalar dt = context->dt; 1253a8779fbSJames Wright 1263a8779fbSJames Wright // Quadrature Point Loop 1273d65b166SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 128ade49511SJames Wright CeedScalar U[5], wdetJ, dXdx[3][3]; 129c1a52365SJed Brown for (int j = 0; j < 5; j++) U[j] = q[j][i]; 130ade49511SJames Wright StoredValuesUnpack(Q, i, 0, 1, q_data, &wdetJ); 131ade49511SJames Wright StoredValuesUnpack(Q, i, 1, 9, q_data, (CeedScalar *)dXdx); 132c1a52365SJed Brown const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 133*edcfef1bSKenneth E. Jansen State s = StateFromU(context, U); 134c1a52365SJed Brown 135c1a52365SJed Brown State grad_s[3]; 136*edcfef1bSKenneth E. Jansen StatePhysicalGradientFromReference(Q, i, context, s, STATEVAR_CONSERVATIVE, Grad_q, dXdx, grad_s); 137c1a52365SJed Brown 138c1a52365SJed Brown CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 13940a33f2dSJames Wright KMStrainRate_State(grad_s, strain_rate); 140c1a52365SJed Brown NewtonianStress(context, strain_rate, kmstress); 141c1a52365SJed Brown KMUnpack(kmstress, stress); 142c1a52365SJed Brown ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 143c1a52365SJed Brown 144c1a52365SJed Brown StateConservative F_inviscid[3]; 145c1a52365SJed Brown FluxInviscid(context, s, F_inviscid); 146c1a52365SJed Brown 147c1a52365SJed Brown // Total flux 148c1a52365SJed Brown CeedScalar Flux[5][3]; 149d1b9ef12SLeila Ghaffari FluxTotal(F_inviscid, stress, Fe, Flux); 150c1a52365SJed Brown 1517523f6aaSJames Wright for (CeedInt j = 0; j < 5; j++) { 1527523f6aaSJames 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]); 1532b916ea7SJeremy L Thompson } 154c1a52365SJed Brown 155c1a52365SJed Brown const CeedScalar body_force[5] = {0, s.U.density * g[0], s.U.density * g[1], s.U.density * g[2], 0}; 1562b916ea7SJeremy L Thompson for (int j = 0; j < 5; j++) v[j][i] = wdetJ * body_force[j]; 1573a8779fbSJames Wright 158d1b9ef12SLeila Ghaffari // -- Stabilization method: none (Galerkin), SU, or SUPG 159d1b9ef12SLeila Ghaffari CeedScalar Tau_d[3], stab[5][3], U_dot[5] = {0}; 160d1b9ef12SLeila Ghaffari Tau_diagPrim(context, s, dXdx, dt, Tau_d); 161*edcfef1bSKenneth E. Jansen Stabilization(context, s, Tau_d, grad_s, U_dot, body_force, stab); 1623a8779fbSJames Wright 1632b916ea7SJeremy L Thompson for (CeedInt j = 0; j < 5; j++) { 1642b916ea7SJeremy 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]); 1652b916ea7SJeremy L Thompson } 1663a8779fbSJames Wright } // End Quadrature Point Loop 1673a8779fbSJames Wright 1683a8779fbSJames Wright // Return 1693a8779fbSJames Wright return 0; 1703a8779fbSJames Wright } 1713a8779fbSJames Wright 1723a8779fbSJames Wright // ***************************************************************************** 17304e40bb6SJeremy L Thompson // This QFunction implements the Navier-Stokes equations (mentioned above) with implicit time stepping method 1743a8779fbSJames Wright // 1753a8779fbSJames Wright // SU = Galerkin + grad(v) . ( Ai^T * Tau * (Aj q,j) ) 1763a8779fbSJames Wright // SUPG = Galerkin + grad(v) . ( Ai^T * Tau * (q_dot + Aj q,j - body force) ) 17704e40bb6SJeremy L Thompson // (diffusive terms will be added later) 1783a8779fbSJames Wright // ***************************************************************************** 1798fff8293SJames Wright CEED_QFUNCTION_HELPER int IFunction_Newtonian(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateVariable state_var) { 1803a8779fbSJames Wright // Inputs 1813d65b166SJames Wright const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 18287bd45e7SJames Wright const CeedScalar(*Grad_q) = in[1]; 1833d65b166SJames Wright const CeedScalar(*q_dot)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2]; 184ade49511SJames Wright const CeedScalar(*q_data) = in[3]; 1853d65b166SJames Wright const CeedScalar(*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 1863d65b166SJames Wright 1873a8779fbSJames Wright // Outputs 1883d65b166SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 1893d65b166SJames Wright CeedScalar(*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 190ade49511SJames Wright CeedScalar(*jac_data) = out[2]; 1913d65b166SJames Wright 1923a8779fbSJames Wright // Context 1933a8779fbSJames Wright NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 194bb8a0c61SJames Wright const CeedScalar *g = context->g; 195bb8a0c61SJames Wright const CeedScalar dt = context->dt; 196e7754af5SKenneth E. Jansen const CeedScalar P0 = context->P0; 1973a8779fbSJames Wright 1983a8779fbSJames Wright // Quadrature Point Loop 1993d65b166SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 2003d65b166SJames Wright const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 201c1a52365SJed Brown const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 202*edcfef1bSKenneth E. Jansen const State s = StateFromQ(context, qi, state_var); 203c1a52365SJed Brown 204ade49511SJames Wright CeedScalar wdetJ, dXdx[3][3]; 205ade49511SJames Wright QdataUnpack_3D(Q, i, q_data, &wdetJ, dXdx); 206c1a52365SJed Brown State grad_s[3]; 207*edcfef1bSKenneth E. Jansen StatePhysicalGradientFromReference(Q, i, context, s, state_var, Grad_q, dXdx, grad_s); 208c1a52365SJed Brown 209c1a52365SJed Brown CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 21040a33f2dSJames Wright KMStrainRate_State(grad_s, strain_rate); 211c1a52365SJed Brown NewtonianStress(context, strain_rate, kmstress); 212c1a52365SJed Brown KMUnpack(kmstress, stress); 213c1a52365SJed Brown ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 214c1a52365SJed Brown 215c1a52365SJed Brown StateConservative F_inviscid[3]; 216c1a52365SJed Brown FluxInviscid(context, s, F_inviscid); 217c1a52365SJed Brown 218c1a52365SJed Brown // Total flux 219c1a52365SJed Brown CeedScalar Flux[5][3]; 220d1b9ef12SLeila Ghaffari FluxTotal(F_inviscid, stress, Fe, Flux); 221c1a52365SJed Brown 2227523f6aaSJames Wright for (CeedInt j = 0; j < 5; j++) { 2237523f6aaSJames Wright for (CeedInt k = 0; k < 3; k++) { 2247523f6aaSJames Wright Grad_v[k][j][i] = -wdetJ * (dXdx[k][0] * Flux[j][0] + dXdx[k][1] * Flux[j][1] + dXdx[k][2] * Flux[j][2]); 2253d65b166SJames Wright } 2262b916ea7SJeremy L Thompson } 227c1a52365SJed Brown 228c1a52365SJed Brown const CeedScalar body_force[5] = {0, s.U.density * g[0], s.U.density * g[1], s.U.density * g[2], 0}; 2293a8779fbSJames Wright 230d1b9ef12SLeila Ghaffari // -- Stabilization method: none (Galerkin), SU, or SUPG 231*edcfef1bSKenneth E. Jansen CeedScalar Tau_d[3], stab[5][3], U_dot[5] = {0}, qi_dot[5]; 23276555becSJames Wright for (int j = 0; j < 5; j++) qi_dot[j] = q_dot[j][i]; 233*edcfef1bSKenneth E. Jansen State s_dot = StateFromQ_fwd(context, s, qi_dot, state_var); 23476555becSJames Wright UnpackState_U(s_dot.U, U_dot); 23576555becSJames Wright 2362b916ea7SJeremy L Thompson for (CeedInt j = 0; j < 5; j++) v[j][i] = wdetJ * (U_dot[j] - body_force[j]); 237e7754af5SKenneth E. Jansen if (context->idl_enable) { 238e7754af5SKenneth E. Jansen CeedScalar damp_state[5] = {s.Y.pressure - P0, 0, 0, 0, 0}, idl_residual[5] = {0.}; 239e7754af5SKenneth E. Jansen InternalDampingLayer(context, s, x_i, damp_state, idl_residual); 240e7754af5SKenneth E. Jansen for (int j = 0; j < 5; j++) v[j][i] += wdetJ * idl_residual[j]; 241e7754af5SKenneth E. Jansen } 242e7754af5SKenneth E. Jansen 243d1b9ef12SLeila Ghaffari Tau_diagPrim(context, s, dXdx, dt, Tau_d); 244*edcfef1bSKenneth E. Jansen Stabilization(context, s, Tau_d, grad_s, U_dot, body_force, stab); 2453a8779fbSJames Wright 2462b916ea7SJeremy L Thompson for (CeedInt j = 0; j < 5; j++) { 2473d65b166SJames Wright for (CeedInt k = 0; k < 3; k++) { 2483d65b166SJames 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]); 2493d65b166SJames Wright } 2502b916ea7SJeremy L Thompson } 251ade49511SJames Wright StoredValuesPack(Q, i, 0, 5, qi, jac_data); 252ade49511SJames Wright StoredValuesPack(Q, i, 5, 6, kmstress, jac_data); 253ade49511SJames Wright StoredValuesPack(Q, i, 11, 3, Tau_d, jac_data); 2543a8779fbSJames Wright 2553a8779fbSJames Wright } // End Quadrature Point Loop 2563a8779fbSJames Wright 2573a8779fbSJames Wright // Return 2583a8779fbSJames Wright return 0; 2593a8779fbSJames Wright } 260f0b65372SJed Brown 2612b916ea7SJeremy L Thompson CEED_QFUNCTION(IFunction_Newtonian_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 2628fff8293SJames Wright return IFunction_Newtonian(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 26376555becSJames Wright } 26476555becSJames Wright 2652b916ea7SJeremy L Thompson CEED_QFUNCTION(IFunction_Newtonian_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 2668fff8293SJames Wright return IFunction_Newtonian(ctx, Q, in, out, STATEVAR_PRIMITIVE); 26776555becSJames Wright } 26876555becSJames Wright 269cbe60e31SLeila Ghaffari // ***************************************************************************** 27004e40bb6SJeremy L Thompson // This QFunction implements the jacobian of the Navier-Stokes equations for implicit time stepping method. 271cbe60e31SLeila Ghaffari // ***************************************************************************** 2728fff8293SJames Wright CEED_QFUNCTION_HELPER int IJacobian_Newtonian(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateVariable state_var) { 273f0b65372SJed Brown // Inputs 2743d65b166SJames Wright const CeedScalar(*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 27587bd45e7SJames Wright const CeedScalar(*Grad_dq) = in[1]; 276ade49511SJames Wright const CeedScalar(*q_data) = in[2]; 2773d65b166SJames Wright const CeedScalar(*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; 278ade49511SJames Wright const CeedScalar(*jac_data) = in[4]; 2793d65b166SJames Wright 280f0b65372SJed Brown // Outputs 2813d65b166SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 2823d65b166SJames Wright CeedScalar(*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 2833d65b166SJames Wright 284f0b65372SJed Brown // Context 285f0b65372SJed Brown NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 286f0b65372SJed Brown const CeedScalar *g = context->g; 287f0b65372SJed Brown 288f0b65372SJed Brown // Quadrature Point Loop 2893d65b166SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 290ade49511SJames Wright CeedScalar wdetJ, dXdx[3][3]; 291ade49511SJames Wright QdataUnpack_3D(Q, i, q_data, &wdetJ, dXdx); 292f0b65372SJed Brown 2938789e95fSJames Wright CeedScalar qi[5], kmstress[6], Tau_d[3]; 294ade49511SJames Wright StoredValuesUnpack(Q, i, 0, 5, jac_data, qi); 295ade49511SJames Wright StoredValuesUnpack(Q, i, 5, 6, jac_data, kmstress); 296ade49511SJames Wright StoredValuesUnpack(Q, i, 11, 3, jac_data, Tau_d); 297f0b65372SJed Brown const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 298*edcfef1bSKenneth E. Jansen State s = StateFromQ(context, qi, state_var); 299f0b65372SJed Brown 300*edcfef1bSKenneth E. Jansen CeedScalar dqi[5]; 30176555becSJames Wright for (int j = 0; j < 5; j++) dqi[j] = dq[j][i]; 302*edcfef1bSKenneth E. Jansen State ds = StateFromQ_fwd(context, s, dqi, state_var); 303f0b65372SJed Brown 304f0b65372SJed Brown State grad_ds[3]; 305*edcfef1bSKenneth E. Jansen StatePhysicalGradientFromReference(Q, i, context, s, state_var, Grad_dq, dXdx, grad_ds); 306f0b65372SJed Brown 307f0b65372SJed Brown CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 30840a33f2dSJames Wright KMStrainRate_State(grad_ds, dstrain_rate); 309f0b65372SJed Brown NewtonianStress(context, dstrain_rate, dkmstress); 310f0b65372SJed Brown KMUnpack(dkmstress, dstress); 311f0b65372SJed Brown KMUnpack(kmstress, stress); 312f0b65372SJed Brown ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 313f0b65372SJed Brown 314f0b65372SJed Brown StateConservative dF_inviscid[3]; 315f0b65372SJed Brown FluxInviscid_fwd(context, s, ds, dF_inviscid); 316f0b65372SJed Brown 317f0b65372SJed Brown // Total flux 318f0b65372SJed Brown CeedScalar dFlux[5][3]; 319d1b9ef12SLeila Ghaffari FluxTotal(dF_inviscid, dstress, dFe, dFlux); 320f0b65372SJed Brown 32122387d3aSJames Wright for (int j = 0; j < 5; j++) { 32222387d3aSJames Wright for (int k = 0; k < 3; k++) Grad_v[k][j][i] = -wdetJ * (dXdx[k][0] * dFlux[j][0] + dXdx[k][1] * dFlux[j][1] + dXdx[k][2] * dFlux[j][2]); 3232b916ea7SJeremy L Thompson } 324f0b65372SJed Brown 325f0b65372SJed Brown const CeedScalar dbody_force[5] = {0, ds.U.density * g[0], ds.U.density * g[1], ds.U.density * g[2], 0}; 32676555becSJames Wright CeedScalar dU[5] = {0.}; 32776555becSJames Wright UnpackState_U(ds.U, dU); 3282b916ea7SJeremy L Thompson for (int j = 0; j < 5; j++) v[j][i] = wdetJ * (context->ijacobian_time_shift * dU[j] - dbody_force[j]); 329f0b65372SJed Brown 330e7754af5SKenneth E. Jansen if (context->idl_enable) { 331e7754af5SKenneth E. Jansen CeedScalar damp_state[5] = {ds.Y.pressure, 0, 0, 0, 0}, idl_residual[5] = {0.}; 332e7754af5SKenneth E. Jansen // This is a Picard-type linearization of the damping and could be replaced by an InternalDampingLayer_fwd that uses s and ds. 333e7754af5SKenneth E. Jansen InternalDampingLayer(context, s, x_i, damp_state, idl_residual); 334e7754af5SKenneth E. Jansen for (int j = 0; j < 5; j++) v[j][i] += wdetJ * idl_residual[j]; 335e7754af5SKenneth E. Jansen } 336e7754af5SKenneth E. Jansen 337d1b9ef12SLeila Ghaffari // -- Stabilization method: none (Galerkin), SU, or SUPG 338d1b9ef12SLeila Ghaffari CeedScalar dstab[5][3], U_dot[5] = {0}; 339d1b9ef12SLeila Ghaffari for (CeedInt j = 0; j < 5; j++) U_dot[j] = context->ijacobian_time_shift * dU[j]; 340*edcfef1bSKenneth E. Jansen Stabilization(context, s, Tau_d, grad_ds, U_dot, dbody_force, dstab); 341d1b9ef12SLeila Ghaffari 3422b916ea7SJeremy L Thompson for (int j = 0; j < 5; j++) { 3432b916ea7SJeremy L Thompson for (int k = 0; k < 3; k++) Grad_v[k][j][i] += wdetJ * (dstab[j][0] * dXdx[k][0] + dstab[j][1] * dXdx[k][1] + dstab[j][2] * dXdx[k][2]); 3442b916ea7SJeremy L Thompson } 345f0b65372SJed Brown } // End Quadrature Point Loop 346f0b65372SJed Brown return 0; 347f0b65372SJed Brown } 3488085925cSJames Wright 3492b916ea7SJeremy L Thompson CEED_QFUNCTION(IJacobian_Newtonian_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 3508fff8293SJames Wright return IJacobian_Newtonian(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 35176555becSJames Wright } 35276555becSJames Wright 3532b916ea7SJeremy L Thompson CEED_QFUNCTION(IJacobian_Newtonian_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 3548fff8293SJames Wright return IJacobian_Newtonian(ctx, Q, in, out, STATEVAR_PRIMITIVE); 35576555becSJames Wright } 35676555becSJames Wright 357d1b9ef12SLeila Ghaffari // ***************************************************************************** 3588085925cSJames Wright // Compute boundary integral (ie. for strongly set inflows) 359d1b9ef12SLeila Ghaffari // ***************************************************************************** 3608fff8293SJames Wright CEED_QFUNCTION_HELPER int BoundaryIntegral(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateVariable state_var) { 3613d65b166SJames Wright const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 36287bd45e7SJames Wright const CeedScalar(*Grad_q) = in[1]; 363ade49511SJames Wright const CeedScalar(*q_data_sur) = in[2]; 3648085925cSJames Wright 3653d65b166SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 366ade49511SJames Wright CeedScalar(*jac_data_sur) = out[1]; 3678085925cSJames Wright 368d3b25f3aSJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 369d3b25f3aSJames Wright const bool is_implicit = context->is_implicit; 3708085925cSJames Wright 3712b916ea7SJeremy L Thompson CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 37241e73928SJames Wright const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 373*edcfef1bSKenneth E. Jansen State s = StateFromQ(context, qi, state_var); 3748085925cSJames Wright 375ade49511SJames Wright CeedScalar wdetJb, dXdx[2][3], norm[3]; 376ade49511SJames Wright QdataBoundaryUnpack_3D(Q, i, q_data_sur, &wdetJb, dXdx, norm); 377ade49511SJames Wright wdetJb *= is_implicit ? -1. : 1.; 3788085925cSJames Wright 379d3b25f3aSJames Wright State grad_s[3]; 380*edcfef1bSKenneth E. Jansen StatePhysicalGradientFromReference_Boundary(Q, i, context, s, state_var, Grad_q, dXdx, grad_s); 3818085925cSJames Wright 382d3b25f3aSJames Wright CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 38340a33f2dSJames Wright KMStrainRate_State(grad_s, strain_rate); 384d3b25f3aSJames Wright NewtonianStress(context, strain_rate, kmstress); 385d3b25f3aSJames Wright KMUnpack(kmstress, stress); 386d3b25f3aSJames Wright ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 387d3b25f3aSJames Wright 388d3b25f3aSJames Wright StateConservative F_inviscid[3]; 389d3b25f3aSJames Wright FluxInviscid(context, s, F_inviscid); 390d3b25f3aSJames Wright 391c5740391SJames Wright CeedScalar Flux[5]; 392c5740391SJames Wright FluxTotal_Boundary(F_inviscid, stress, Fe, norm, Flux); 393d3b25f3aSJames Wright 394c5740391SJames Wright for (CeedInt j = 0; j < 5; j++) v[j][i] = -wdetJb * Flux[j]; 3958085925cSJames Wright 396ade49511SJames Wright StoredValuesPack(Q, i, 0, 5, qi, jac_data_sur); 397ade49511SJames Wright StoredValuesPack(Q, i, 5, 6, kmstress, jac_data_sur); 3988085925cSJames Wright } 3998085925cSJames Wright return 0; 4008085925cSJames Wright } 4018085925cSJames Wright 4022b916ea7SJeremy L Thompson CEED_QFUNCTION(BoundaryIntegral_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 4038fff8293SJames Wright return BoundaryIntegral(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 404d4559bbeSJames Wright } 405d4559bbeSJames Wright 4062b916ea7SJeremy L Thompson CEED_QFUNCTION(BoundaryIntegral_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 4078fff8293SJames Wright return BoundaryIntegral(ctx, Q, in, out, STATEVAR_PRIMITIVE); 408d4559bbeSJames Wright } 409d4559bbeSJames Wright 410d1b9ef12SLeila Ghaffari // ***************************************************************************** 41168ae065aSJames Wright // Jacobian for "set nothing" boundary integral 412d1b9ef12SLeila Ghaffari // ***************************************************************************** 4132b916ea7SJeremy L Thompson CEED_QFUNCTION_HELPER int BoundaryIntegral_Jacobian(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, 4148fff8293SJames Wright StateVariable state_var) { 41568ae065aSJames Wright // Inputs 4163d65b166SJames Wright const CeedScalar(*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 41787bd45e7SJames Wright const CeedScalar(*Grad_dq) = in[1]; 418ade49511SJames Wright const CeedScalar(*q_data_sur) = in[2]; 419*edcfef1bSKenneth E. Jansen const CeedScalar(*jac_data_sur) = in[3]; 4203d65b166SJames Wright 42168ae065aSJames Wright // Outputs 42268ae065aSJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 42368ae065aSJames Wright 42468ae065aSJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 425ade49511SJames Wright const bool is_implicit = context->is_implicit; 42668ae065aSJames Wright 42768ae065aSJames Wright // Quadrature Point Loop 4283d65b166SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 429ade49511SJames Wright CeedScalar wdetJb, dXdx[2][3], norm[3]; 430ade49511SJames Wright QdataBoundaryUnpack_3D(Q, i, q_data_sur, &wdetJb, dXdx, norm); 431ade49511SJames Wright wdetJb *= is_implicit ? -1. : 1.; 43268ae065aSJames Wright 433*edcfef1bSKenneth E. Jansen CeedScalar qi[5], kmstress[6], dqi[5]; 434ade49511SJames Wright StoredValuesUnpack(Q, i, 0, 5, jac_data_sur, qi); 435ade49511SJames Wright StoredValuesUnpack(Q, i, 5, 6, jac_data_sur, kmstress); 43641e73928SJames Wright for (int j = 0; j < 5; j++) dqi[j] = dq[j][i]; 4373934e2b1SJames Wright 438*edcfef1bSKenneth E. Jansen State s = StateFromQ(context, qi, state_var); 439*edcfef1bSKenneth E. Jansen State ds = StateFromQ_fwd(context, s, dqi, state_var); 44068ae065aSJames Wright 44168ae065aSJames Wright State grad_ds[3]; 442*edcfef1bSKenneth E. Jansen StatePhysicalGradientFromReference_Boundary(Q, i, context, s, state_var, Grad_dq, dXdx, grad_ds); 44368ae065aSJames Wright 44468ae065aSJames Wright CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 44540a33f2dSJames Wright KMStrainRate_State(grad_ds, dstrain_rate); 44668ae065aSJames Wright NewtonianStress(context, dstrain_rate, dkmstress); 44768ae065aSJames Wright KMUnpack(dkmstress, dstress); 44868ae065aSJames Wright KMUnpack(kmstress, stress); 44968ae065aSJames Wright ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 45068ae065aSJames Wright 45168ae065aSJames Wright StateConservative dF_inviscid[3]; 45268ae065aSJames Wright FluxInviscid_fwd(context, s, ds, dF_inviscid); 45368ae065aSJames Wright 454c5740391SJames Wright CeedScalar dFlux[5]; 455c5740391SJames Wright FluxTotal_Boundary(dF_inviscid, dstress, dFe, norm, dFlux); 45668ae065aSJames Wright 457c5740391SJames Wright for (int j = 0; j < 5; j++) v[j][i] = -wdetJb * dFlux[j]; 45868ae065aSJames Wright } // End Quadrature Point Loop 45968ae065aSJames Wright return 0; 46068ae065aSJames Wright } 46168ae065aSJames Wright 4622b916ea7SJeremy L Thompson CEED_QFUNCTION(BoundaryIntegral_Jacobian_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 4638fff8293SJames Wright return BoundaryIntegral_Jacobian(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 464d4559bbeSJames Wright } 465d4559bbeSJames Wright 4662b916ea7SJeremy L Thompson CEED_QFUNCTION(BoundaryIntegral_Jacobian_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 4678fff8293SJames Wright return BoundaryIntegral_Jacobian(ctx, Q, in, out, STATEVAR_PRIMITIVE); 468d4559bbeSJames Wright } 469d4559bbeSJames Wright 4703a8779fbSJames Wright #endif // newtonian_h 471