13d8e8822SJeremy L Thompson // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors. 23d8e8822SJeremy L Thompson // All Rights Reserved. See the top-level LICENSE and NOTICE files for details. 388b783a1SJames Wright // 43d8e8822SJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause 588b783a1SJames Wright // 63d8e8822SJeremy L Thompson // This file is part of CEED: http://github.com/ceed 788b783a1SJames Wright 888b783a1SJames Wright /// @file 988b783a1SJames Wright /// Operator for Navier-Stokes example using PETSc 1088b783a1SJames Wright 1188b783a1SJames Wright #ifndef newtonian_h 1288b783a1SJames Wright #define newtonian_h 1388b783a1SJames Wright 1488b783a1SJames Wright #include <ceed.h> 15c9c2c079SJeremy L Thompson #include <math.h> 16738af36cSAdelekeBankole #include <stdlib.h> 172b730f8bSJeremy L Thompson 18c6e8c570SJames Wright #include "newtonian_state.h" 19c9c2c079SJeremy L Thompson #include "newtonian_types.h" 202b89d87eSLeila Ghaffari #include "stabilization.h" 21c9c2c079SJeremy L Thompson #include "utils.h" 2288626eedSJames Wright 23530ad8c4SKenneth E. Jansen CEED_QFUNCTION_HELPER void InternalDampingLayer(const NewtonianIdealGasContext context, const State s, const CeedScalar x_i[3], CeedScalar damp_Y[5], 24530ad8c4SKenneth E. Jansen CeedScalar damp_residual[5]) { 25530ad8c4SKenneth E. Jansen const CeedScalar sigma = LinearRampCoefficient(context->idl_amplitude, context->idl_length, context->idl_start, x_i[0]); 26530ad8c4SKenneth E. Jansen ScaleN(damp_Y, sigma, 5); 273bd61617SKenneth E. Jansen State damp_s = StateFromY_fwd(context, s, damp_Y); 28530ad8c4SKenneth E. Jansen 29530ad8c4SKenneth E. Jansen CeedScalar U[5]; 30530ad8c4SKenneth E. Jansen UnpackState_U(damp_s.U, U); 31530ad8c4SKenneth E. Jansen for (int i = 0; i < 5; i++) damp_residual[i] += U[i]; 32530ad8c4SKenneth E. Jansen } 33530ad8c4SKenneth E. Jansen 3488626eedSJames Wright // ***************************************************************************** 3588b783a1SJames Wright // This QFunction sets a "still" initial condition for generic Newtonian IG problems 3688b783a1SJames Wright // ***************************************************************************** 37be91e165SJames Wright CEED_QFUNCTION_HELPER int ICsNewtonianIG(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateVariable state_var) { 3888b783a1SJames Wright // Inputs 3988b783a1SJames Wright const CeedScalar(*X)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 4088b783a1SJames Wright 4188b783a1SJames Wright // Outputs 4288b783a1SJames Wright CeedScalar(*q0)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 4388b783a1SJames Wright 4488626eedSJames Wright // Context 4588626eedSJames Wright const SetupContext context = (SetupContext)ctx; 4688626eedSJames Wright 4788b783a1SJames Wright // Quadrature Point Loop 482b730f8bSJeremy L Thompson CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 49d310b3d3SAdeleke O. Bankole CeedScalar x[3] = {X[0][i], X[1][i], X[2][i]}; 5088b783a1SJames Wright CeedScalar q[5] = {0.}; 513bd61617SKenneth E. Jansen State s = StateFromPrimitive(&context->gas, context->reference); 52be91e165SJames Wright StateToQ(&context->gas, s, q, state_var); 532b730f8bSJeremy L Thompson for (CeedInt j = 0; j < 5; j++) q0[j][i] = q[j]; 5488b783a1SJames Wright } // End of Quadrature Point Loop 5588b783a1SJames Wright return 0; 5688b783a1SJames Wright } 5788b783a1SJames Wright 582b730f8bSJeremy L Thompson CEED_QFUNCTION(ICsNewtonianIG_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 59be91e165SJames Wright return ICsNewtonianIG(ctx, Q, in, out, STATEVAR_PRIMITIVE); 60d310b3d3SAdeleke O. Bankole } 61d310b3d3SAdeleke O. Bankole CEED_QFUNCTION(ICsNewtonianIG_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 62be91e165SJames Wright return ICsNewtonianIG(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 63dc805cc4SLeila Ghaffari } 64dc805cc4SLeila Ghaffari 65dc805cc4SLeila Ghaffari // ***************************************************************************** 66ea61e9acSJeremy L Thompson // This QFunction implements the following formulation of Navier-Stokes with explicit time stepping method 6788b783a1SJames Wright // 68ea61e9acSJeremy L Thompson // This is 3D compressible Navier-Stokes in conservation form with state variables of density, momentum density, and total energy density. 6988b783a1SJames Wright // 7088b783a1SJames Wright // State Variables: q = ( rho, U1, U2, U3, E ) 7188b783a1SJames Wright // rho - Mass Density 7288b783a1SJames Wright // Ui - Momentum Density, Ui = rho ui 7388b783a1SJames Wright // E - Total Energy Density, E = rho (cv T + (u u)/2 + g z) 7488b783a1SJames Wright // 7588b783a1SJames Wright // Navier-Stokes Equations: 7688b783a1SJames Wright // drho/dt + div( U ) = 0 7788b783a1SJames Wright // dU/dt + div( rho (u x u) + P I3 ) + rho g khat = div( Fu ) 7888b783a1SJames Wright // dE/dt + div( (E + P) u ) = div( Fe ) 7988b783a1SJames Wright // 8088b783a1SJames Wright // Viscous Stress: 8188b783a1SJames Wright // Fu = mu (grad( u ) + grad( u )^T + lambda div ( u ) I3) 8288b783a1SJames Wright // 8388b783a1SJames Wright // Thermal Stress: 8488b783a1SJames Wright // Fe = u Fu + k grad( T ) 8588626eedSJames Wright // Equation of State 8688b783a1SJames Wright // P = (gamma - 1) (E - rho (u u) / 2 - rho g z) 8788b783a1SJames Wright // 8888b783a1SJames Wright // Stabilization: 8988b783a1SJames Wright // Tau = diag(TauC, TauM, TauM, TauM, TauE) 9088b783a1SJames Wright // f1 = rho sqrt(ui uj gij) 9188b783a1SJames Wright // gij = dXi/dX * dXi/dX 9288b783a1SJames Wright // TauC = Cc f1 / (8 gii) 9388b783a1SJames Wright // TauM = min( 1 , 1 / f1 ) 9488b783a1SJames Wright // TauE = TauM / (Ce cv) 9588b783a1SJames Wright // 9688b783a1SJames Wright // SU = Galerkin + grad(v) . ( Ai^T * Tau * (Aj q,j) ) 9788b783a1SJames Wright // 9888b783a1SJames Wright // Constants: 9988b783a1SJames Wright // lambda = - 2 / 3, From Stokes hypothesis 10088b783a1SJames Wright // mu , Dynamic viscosity 10188b783a1SJames Wright // k , Thermal conductivity 10288b783a1SJames Wright // cv , Specific heat, constant volume 10388b783a1SJames Wright // cp , Specific heat, constant pressure 10488b783a1SJames Wright // g , Gravity 10588b783a1SJames Wright // gamma = cp / cv, Specific heat ratio 10688b783a1SJames Wright // 107ea61e9acSJeremy 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 108ea61e9acSJeremy L Thompson // gradu ) 10988b783a1SJames Wright // ***************************************************************************** 1102b730f8bSJeremy L Thompson CEED_QFUNCTION(RHSFunction_Newtonian)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 11188b783a1SJames Wright // Inputs 11246603fc5SJames Wright const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 1139b6a821dSJames Wright const CeedScalar(*Grad_q) = in[1]; 114f3e15844SJames Wright const CeedScalar(*q_data) = in[2]; 11546603fc5SJames Wright const CeedScalar(*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; 11646603fc5SJames Wright 11788b783a1SJames Wright // Outputs 11846603fc5SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 11946603fc5SJames Wright CeedScalar(*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 12088b783a1SJames Wright 12188b783a1SJames Wright // Context 12288b783a1SJames Wright NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 12388626eedSJames Wright const CeedScalar *g = context->g; 12488626eedSJames Wright const CeedScalar dt = context->dt; 12588b783a1SJames Wright 12688b783a1SJames Wright // Quadrature Point Loop 12746603fc5SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 128f3e15844SJames Wright CeedScalar U[5], wdetJ, dXdx[3][3]; 1295c677226SJed Brown for (int j = 0; j < 5; j++) U[j] = q[j][i]; 130f3e15844SJames Wright StoredValuesUnpack(Q, i, 0, 1, q_data, &wdetJ); 131f3e15844SJames Wright StoredValuesUnpack(Q, i, 1, 9, q_data, (CeedScalar *)dXdx); 1325c677226SJed Brown const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 1333bd61617SKenneth E. Jansen State s = StateFromU(context, U); 1345c677226SJed Brown 1355c677226SJed Brown State grad_s[3]; 1363bd61617SKenneth E. Jansen StatePhysicalGradientFromReference(Q, i, context, s, STATEVAR_CONSERVATIVE, Grad_q, dXdx, grad_s); 1375c677226SJed Brown 1385c677226SJed Brown CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 139d08fcc28SJames Wright KMStrainRate_State(grad_s, strain_rate); 1405c677226SJed Brown NewtonianStress(context, strain_rate, kmstress); 1415c677226SJed Brown KMUnpack(kmstress, stress); 1425c677226SJed Brown ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 1435c677226SJed Brown 1445c677226SJed Brown StateConservative F_inviscid[3]; 1455c677226SJed Brown FluxInviscid(context, s, F_inviscid); 1465c677226SJed Brown 1475c677226SJed Brown // Total flux 1485c677226SJed Brown CeedScalar Flux[5][3]; 1492b89d87eSLeila Ghaffari FluxTotal(F_inviscid, stress, Fe, Flux); 1505c677226SJed Brown 1517b69c783SJames Wright for (CeedInt j = 0; j < 5; j++) { 1527b69c783SJames 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]); 1532b730f8bSJeremy L Thompson } 1545c677226SJed Brown 155*858ec087SKenneth 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)}; 1562b730f8bSJeremy L Thompson for (int j = 0; j < 5; j++) v[j][i] = wdetJ * body_force[j]; 15788b783a1SJames Wright 1582b89d87eSLeila Ghaffari // -- Stabilization method: none (Galerkin), SU, or SUPG 1592b89d87eSLeila Ghaffari CeedScalar Tau_d[3], stab[5][3], U_dot[5] = {0}; 1602b89d87eSLeila Ghaffari Tau_diagPrim(context, s, dXdx, dt, Tau_d); 1613bd61617SKenneth E. Jansen Stabilization(context, s, Tau_d, grad_s, U_dot, body_force, stab); 16288b783a1SJames Wright 1632b730f8bSJeremy L Thompson for (CeedInt j = 0; j < 5; j++) { 1642b730f8bSJeremy 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]); 1652b730f8bSJeremy L Thompson } 16688b783a1SJames Wright } // End Quadrature Point Loop 16788b783a1SJames Wright 16888b783a1SJames Wright // Return 16988b783a1SJames Wright return 0; 17088b783a1SJames Wright } 17188b783a1SJames Wright 17288b783a1SJames Wright // ***************************************************************************** 173ea61e9acSJeremy L Thompson // This QFunction implements the Navier-Stokes equations (mentioned above) with implicit time stepping method 17488b783a1SJames Wright // 17588b783a1SJames Wright // SU = Galerkin + grad(v) . ( Ai^T * Tau * (Aj q,j) ) 17688b783a1SJames Wright // SUPG = Galerkin + grad(v) . ( Ai^T * Tau * (q_dot + Aj q,j - body force) ) 177ea61e9acSJeremy L Thompson // (diffusive terms will be added later) 17888b783a1SJames Wright // ***************************************************************************** 179be91e165SJames Wright CEED_QFUNCTION_HELPER int IFunction_Newtonian(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateVariable state_var) { 18088b783a1SJames Wright // Inputs 18146603fc5SJames Wright const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 1829b6a821dSJames Wright const CeedScalar(*Grad_q) = in[1]; 18346603fc5SJames Wright const CeedScalar(*q_dot)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2]; 184f3e15844SJames Wright const CeedScalar(*q_data) = in[3]; 18546603fc5SJames Wright const CeedScalar(*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 18646603fc5SJames Wright 18788b783a1SJames Wright // Outputs 18846603fc5SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 18946603fc5SJames Wright CeedScalar(*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 190f3e15844SJames Wright CeedScalar(*jac_data) = out[2]; 19146603fc5SJames Wright 19288b783a1SJames Wright // Context 19388b783a1SJames Wright NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 19488626eedSJames Wright const CeedScalar *g = context->g; 19588626eedSJames Wright const CeedScalar dt = context->dt; 196530ad8c4SKenneth E. Jansen const CeedScalar P0 = context->P0; 19788b783a1SJames Wright 19888b783a1SJames Wright // Quadrature Point Loop 19946603fc5SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 20046603fc5SJames Wright const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 2015c677226SJed Brown const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 2023bd61617SKenneth E. Jansen const State s = StateFromQ(context, qi, state_var); 2035c677226SJed Brown 204f3e15844SJames Wright CeedScalar wdetJ, dXdx[3][3]; 205f3e15844SJames Wright QdataUnpack_3D(Q, i, q_data, &wdetJ, dXdx); 2065c677226SJed Brown State grad_s[3]; 2073bd61617SKenneth E. Jansen StatePhysicalGradientFromReference(Q, i, context, s, state_var, Grad_q, dXdx, grad_s); 2085c677226SJed Brown 2095c677226SJed Brown CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 210d08fcc28SJames Wright KMStrainRate_State(grad_s, strain_rate); 2115c677226SJed Brown NewtonianStress(context, strain_rate, kmstress); 2125c677226SJed Brown KMUnpack(kmstress, stress); 2135c677226SJed Brown ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 2145c677226SJed Brown 2155c677226SJed Brown StateConservative F_inviscid[3]; 2165c677226SJed Brown FluxInviscid(context, s, F_inviscid); 2175c677226SJed Brown 2185c677226SJed Brown // Total flux 2195c677226SJed Brown CeedScalar Flux[5][3]; 2202b89d87eSLeila Ghaffari FluxTotal(F_inviscid, stress, Fe, Flux); 2215c677226SJed Brown 2227b69c783SJames Wright for (CeedInt j = 0; j < 5; j++) { 2237b69c783SJames Wright for (CeedInt k = 0; k < 3; k++) { 2247b69c783SJames 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]); 22546603fc5SJames Wright } 2262b730f8bSJeremy L Thompson } 2275c677226SJed Brown 228*858ec087SKenneth 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)}; 22988b783a1SJames Wright 2302b89d87eSLeila Ghaffari // -- Stabilization method: none (Galerkin), SU, or SUPG 2313bd61617SKenneth E. Jansen CeedScalar Tau_d[3], stab[5][3], U_dot[5] = {0}, qi_dot[5]; 2323d02368aSJames Wright for (int j = 0; j < 5; j++) qi_dot[j] = q_dot[j][i]; 2333bd61617SKenneth E. Jansen State s_dot = StateFromQ_fwd(context, s, qi_dot, state_var); 2343d02368aSJames Wright UnpackState_U(s_dot.U, U_dot); 2353d02368aSJames Wright 2362b730f8bSJeremy L Thompson for (CeedInt j = 0; j < 5; j++) v[j][i] = wdetJ * (U_dot[j] - body_force[j]); 237530ad8c4SKenneth E. Jansen if (context->idl_enable) { 238530ad8c4SKenneth E. Jansen CeedScalar damp_state[5] = {s.Y.pressure - P0, 0, 0, 0, 0}, idl_residual[5] = {0.}; 239530ad8c4SKenneth E. Jansen InternalDampingLayer(context, s, x_i, damp_state, idl_residual); 240530ad8c4SKenneth E. Jansen for (int j = 0; j < 5; j++) v[j][i] += wdetJ * idl_residual[j]; 241530ad8c4SKenneth E. Jansen } 242530ad8c4SKenneth E. Jansen 2432b89d87eSLeila Ghaffari Tau_diagPrim(context, s, dXdx, dt, Tau_d); 2443bd61617SKenneth E. Jansen Stabilization(context, s, Tau_d, grad_s, U_dot, body_force, stab); 24588b783a1SJames Wright 2462b730f8bSJeremy L Thompson for (CeedInt j = 0; j < 5; j++) { 24746603fc5SJames Wright for (CeedInt k = 0; k < 3; k++) { 24846603fc5SJames 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]); 24946603fc5SJames Wright } 2502b730f8bSJeremy L Thompson } 251f3e15844SJames Wright StoredValuesPack(Q, i, 0, 5, qi, jac_data); 252f3e15844SJames Wright StoredValuesPack(Q, i, 5, 6, kmstress, jac_data); 253f3e15844SJames Wright StoredValuesPack(Q, i, 11, 3, Tau_d, jac_data); 25488b783a1SJames Wright 25588b783a1SJames Wright } // End Quadrature Point Loop 25688b783a1SJames Wright 25788b783a1SJames Wright // Return 25888b783a1SJames Wright return 0; 25988b783a1SJames Wright } 260e334ad8fSJed Brown 2612b730f8bSJeremy L Thompson CEED_QFUNCTION(IFunction_Newtonian_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 262be91e165SJames Wright return IFunction_Newtonian(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 2633d02368aSJames Wright } 2643d02368aSJames Wright 2652b730f8bSJeremy L Thompson CEED_QFUNCTION(IFunction_Newtonian_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 266be91e165SJames Wright return IFunction_Newtonian(ctx, Q, in, out, STATEVAR_PRIMITIVE); 2673d02368aSJames Wright } 2683d02368aSJames Wright 269dc805cc4SLeila Ghaffari // ***************************************************************************** 270ea61e9acSJeremy L Thompson // This QFunction implements the jacobian of the Navier-Stokes equations for implicit time stepping method. 271dc805cc4SLeila Ghaffari // ***************************************************************************** 272be91e165SJames Wright CEED_QFUNCTION_HELPER int IJacobian_Newtonian(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateVariable state_var) { 273e334ad8fSJed Brown // Inputs 27446603fc5SJames Wright const CeedScalar(*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 2759b6a821dSJames Wright const CeedScalar(*Grad_dq) = in[1]; 276f3e15844SJames Wright const CeedScalar(*q_data) = in[2]; 27746603fc5SJames Wright const CeedScalar(*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; 278f3e15844SJames Wright const CeedScalar(*jac_data) = in[4]; 27946603fc5SJames Wright 280e334ad8fSJed Brown // Outputs 28146603fc5SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 28246603fc5SJames Wright CeedScalar(*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 28346603fc5SJames Wright 284e334ad8fSJed Brown // Context 285e334ad8fSJed Brown NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 286e334ad8fSJed Brown const CeedScalar *g = context->g; 287e334ad8fSJed Brown 288e334ad8fSJed Brown // Quadrature Point Loop 28946603fc5SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 290f3e15844SJames Wright CeedScalar wdetJ, dXdx[3][3]; 291f3e15844SJames Wright QdataUnpack_3D(Q, i, q_data, &wdetJ, dXdx); 292e334ad8fSJed Brown 293c98a0616SJames Wright CeedScalar qi[5], kmstress[6], Tau_d[3]; 294f3e15844SJames Wright StoredValuesUnpack(Q, i, 0, 5, jac_data, qi); 295f3e15844SJames Wright StoredValuesUnpack(Q, i, 5, 6, jac_data, kmstress); 296f3e15844SJames Wright StoredValuesUnpack(Q, i, 11, 3, jac_data, Tau_d); 297e334ad8fSJed Brown const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 2983bd61617SKenneth E. Jansen State s = StateFromQ(context, qi, state_var); 299e334ad8fSJed Brown 3003bd61617SKenneth E. Jansen CeedScalar dqi[5]; 3013d02368aSJames Wright for (int j = 0; j < 5; j++) dqi[j] = dq[j][i]; 3023bd61617SKenneth E. Jansen State ds = StateFromQ_fwd(context, s, dqi, state_var); 303e334ad8fSJed Brown 304e334ad8fSJed Brown State grad_ds[3]; 3053bd61617SKenneth E. Jansen StatePhysicalGradientFromReference(Q, i, context, s, state_var, Grad_dq, dXdx, grad_ds); 306e334ad8fSJed Brown 307e334ad8fSJed Brown CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 308d08fcc28SJames Wright KMStrainRate_State(grad_ds, dstrain_rate); 309e334ad8fSJed Brown NewtonianStress(context, dstrain_rate, dkmstress); 310e334ad8fSJed Brown KMUnpack(dkmstress, dstress); 311e334ad8fSJed Brown KMUnpack(kmstress, stress); 312e334ad8fSJed Brown ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 313e334ad8fSJed Brown 314e334ad8fSJed Brown StateConservative dF_inviscid[3]; 315e334ad8fSJed Brown FluxInviscid_fwd(context, s, ds, dF_inviscid); 316e334ad8fSJed Brown 317e334ad8fSJed Brown // Total flux 318e334ad8fSJed Brown CeedScalar dFlux[5][3]; 3192b89d87eSLeila Ghaffari FluxTotal(dF_inviscid, dstress, dFe, dFlux); 320e334ad8fSJed Brown 32151b00d91SJames Wright for (int j = 0; j < 5; j++) { 32251b00d91SJames 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]); 3232b730f8bSJeremy L Thompson } 324e334ad8fSJed Brown 325*858ec087SKenneth 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)}; 3263d02368aSJames Wright CeedScalar dU[5] = {0.}; 3273d02368aSJames Wright UnpackState_U(ds.U, dU); 3282b730f8bSJeremy L Thompson for (int j = 0; j < 5; j++) v[j][i] = wdetJ * (context->ijacobian_time_shift * dU[j] - dbody_force[j]); 329e334ad8fSJed Brown 330530ad8c4SKenneth E. Jansen if (context->idl_enable) { 331530ad8c4SKenneth E. Jansen CeedScalar damp_state[5] = {ds.Y.pressure, 0, 0, 0, 0}, idl_residual[5] = {0.}; 332530ad8c4SKenneth E. Jansen // This is a Picard-type linearization of the damping and could be replaced by an InternalDampingLayer_fwd that uses s and ds. 333530ad8c4SKenneth E. Jansen InternalDampingLayer(context, s, x_i, damp_state, idl_residual); 334530ad8c4SKenneth E. Jansen for (int j = 0; j < 5; j++) v[j][i] += wdetJ * idl_residual[j]; 335530ad8c4SKenneth E. Jansen } 336530ad8c4SKenneth E. Jansen 3372b89d87eSLeila Ghaffari // -- Stabilization method: none (Galerkin), SU, or SUPG 3382b89d87eSLeila Ghaffari CeedScalar dstab[5][3], U_dot[5] = {0}; 3392b89d87eSLeila Ghaffari for (CeedInt j = 0; j < 5; j++) U_dot[j] = context->ijacobian_time_shift * dU[j]; 3403bd61617SKenneth E. Jansen Stabilization(context, s, Tau_d, grad_ds, U_dot, dbody_force, dstab); 3412b89d87eSLeila Ghaffari 3422b730f8bSJeremy L Thompson for (int j = 0; j < 5; j++) { 3432b730f8bSJeremy 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]); 3442b730f8bSJeremy L Thompson } 345e334ad8fSJed Brown } // End Quadrature Point Loop 346e334ad8fSJed Brown return 0; 347e334ad8fSJed Brown } 34865dd5cafSJames Wright 3492b730f8bSJeremy L Thompson CEED_QFUNCTION(IJacobian_Newtonian_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 350be91e165SJames Wright return IJacobian_Newtonian(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 3513d02368aSJames Wright } 3523d02368aSJames Wright 3532b730f8bSJeremy L Thompson CEED_QFUNCTION(IJacobian_Newtonian_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 354be91e165SJames Wright return IJacobian_Newtonian(ctx, Q, in, out, STATEVAR_PRIMITIVE); 3553d02368aSJames Wright } 3563d02368aSJames Wright 3572b89d87eSLeila Ghaffari // ***************************************************************************** 35865dd5cafSJames Wright // Compute boundary integral (ie. for strongly set inflows) 3592b89d87eSLeila Ghaffari // ***************************************************************************** 360be91e165SJames Wright CEED_QFUNCTION_HELPER int BoundaryIntegral(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateVariable state_var) { 36146603fc5SJames Wright const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 3629b6a821dSJames Wright const CeedScalar(*Grad_q) = in[1]; 363f3e15844SJames Wright const CeedScalar(*q_data_sur) = in[2]; 36465dd5cafSJames Wright 36546603fc5SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 366f3e15844SJames Wright CeedScalar(*jac_data_sur) = out[1]; 36765dd5cafSJames Wright 3682c4e60d7SJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 3692c4e60d7SJames Wright const bool is_implicit = context->is_implicit; 37065dd5cafSJames Wright 3712b730f8bSJeremy L Thompson CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 372efe9d856SJames Wright const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 3733bd61617SKenneth E. Jansen State s = StateFromQ(context, qi, state_var); 37465dd5cafSJames Wright 375f3e15844SJames Wright CeedScalar wdetJb, dXdx[2][3], norm[3]; 376f3e15844SJames Wright QdataBoundaryUnpack_3D(Q, i, q_data_sur, &wdetJb, dXdx, norm); 377f3e15844SJames Wright wdetJb *= is_implicit ? -1. : 1.; 37865dd5cafSJames Wright 3792c4e60d7SJames Wright State grad_s[3]; 3803bd61617SKenneth E. Jansen StatePhysicalGradientFromReference_Boundary(Q, i, context, s, state_var, Grad_q, dXdx, grad_s); 38165dd5cafSJames Wright 3822c4e60d7SJames Wright CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 383d08fcc28SJames Wright KMStrainRate_State(grad_s, strain_rate); 3842c4e60d7SJames Wright NewtonianStress(context, strain_rate, kmstress); 3852c4e60d7SJames Wright KMUnpack(kmstress, stress); 3862c4e60d7SJames Wright ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 3872c4e60d7SJames Wright 3882c4e60d7SJames Wright StateConservative F_inviscid[3]; 3892c4e60d7SJames Wright FluxInviscid(context, s, F_inviscid); 3902c4e60d7SJames Wright 3915bce47c7SJames Wright CeedScalar Flux[5]; 3925bce47c7SJames Wright FluxTotal_Boundary(F_inviscid, stress, Fe, norm, Flux); 3932c4e60d7SJames Wright 3945bce47c7SJames Wright for (CeedInt j = 0; j < 5; j++) v[j][i] = -wdetJb * Flux[j]; 39565dd5cafSJames Wright 396f3e15844SJames Wright StoredValuesPack(Q, i, 0, 5, qi, jac_data_sur); 397f3e15844SJames Wright StoredValuesPack(Q, i, 5, 6, kmstress, jac_data_sur); 39865dd5cafSJames Wright } 39965dd5cafSJames Wright return 0; 40065dd5cafSJames Wright } 40165dd5cafSJames Wright 4022b730f8bSJeremy L Thompson CEED_QFUNCTION(BoundaryIntegral_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 403be91e165SJames Wright return BoundaryIntegral(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 40420840d50SJames Wright } 40520840d50SJames Wright 4062b730f8bSJeremy L Thompson CEED_QFUNCTION(BoundaryIntegral_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 407be91e165SJames Wright return BoundaryIntegral(ctx, Q, in, out, STATEVAR_PRIMITIVE); 40820840d50SJames Wright } 40920840d50SJames Wright 4102b89d87eSLeila Ghaffari // ***************************************************************************** 411b55ac660SJames Wright // Jacobian for "set nothing" boundary integral 4122b89d87eSLeila Ghaffari // ***************************************************************************** 4132b730f8bSJeremy L Thompson CEED_QFUNCTION_HELPER int BoundaryIntegral_Jacobian(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, 414be91e165SJames Wright StateVariable state_var) { 415b55ac660SJames Wright // Inputs 41646603fc5SJames Wright const CeedScalar(*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 4179b6a821dSJames Wright const CeedScalar(*Grad_dq) = in[1]; 418f3e15844SJames Wright const CeedScalar(*q_data_sur) = in[2]; 419c1d93bc4SKenneth E. Jansen const CeedScalar(*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; 420c1d93bc4SKenneth E. Jansen const CeedScalar(*jac_data_sur) = in[4]; 42146603fc5SJames Wright 422b55ac660SJames Wright // Outputs 423b55ac660SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 424b55ac660SJames Wright 425b55ac660SJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 426f3e15844SJames Wright const bool is_implicit = context->is_implicit; 427b55ac660SJames Wright 428b55ac660SJames Wright // Quadrature Point Loop 42946603fc5SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 430f3e15844SJames Wright CeedScalar wdetJb, dXdx[2][3], norm[3]; 431f3e15844SJames Wright QdataBoundaryUnpack_3D(Q, i, q_data_sur, &wdetJb, dXdx, norm); 432f3e15844SJames Wright wdetJb *= is_implicit ? -1. : 1.; 433b55ac660SJames Wright 4343bd61617SKenneth E. Jansen CeedScalar qi[5], kmstress[6], dqi[5]; 435f3e15844SJames Wright StoredValuesUnpack(Q, i, 0, 5, jac_data_sur, qi); 436f3e15844SJames Wright StoredValuesUnpack(Q, i, 5, 6, jac_data_sur, kmstress); 437efe9d856SJames Wright for (int j = 0; j < 5; j++) dqi[j] = dq[j][i]; 43857e55a1cSJames Wright 4393bd61617SKenneth E. Jansen State s = StateFromQ(context, qi, state_var); 4403bd61617SKenneth E. Jansen State ds = StateFromQ_fwd(context, s, dqi, state_var); 441b55ac660SJames Wright 442b55ac660SJames Wright State grad_ds[3]; 4433bd61617SKenneth E. Jansen StatePhysicalGradientFromReference_Boundary(Q, i, context, s, state_var, Grad_dq, dXdx, grad_ds); 444b55ac660SJames Wright 445b55ac660SJames Wright CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 446d08fcc28SJames Wright KMStrainRate_State(grad_ds, dstrain_rate); 447b55ac660SJames Wright NewtonianStress(context, dstrain_rate, dkmstress); 448b55ac660SJames Wright KMUnpack(dkmstress, dstress); 449b55ac660SJames Wright KMUnpack(kmstress, stress); 450b55ac660SJames Wright ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 451b55ac660SJames Wright 452b55ac660SJames Wright StateConservative dF_inviscid[3]; 453b55ac660SJames Wright FluxInviscid_fwd(context, s, ds, dF_inviscid); 454b55ac660SJames Wright 4555bce47c7SJames Wright CeedScalar dFlux[5]; 4565bce47c7SJames Wright FluxTotal_Boundary(dF_inviscid, dstress, dFe, norm, dFlux); 457b55ac660SJames Wright 4585bce47c7SJames Wright for (int j = 0; j < 5; j++) v[j][i] = -wdetJb * dFlux[j]; 459b55ac660SJames Wright } // End Quadrature Point Loop 460b55ac660SJames Wright return 0; 461b55ac660SJames Wright } 462b55ac660SJames Wright 4632b730f8bSJeremy L Thompson CEED_QFUNCTION(BoundaryIntegral_Jacobian_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 464be91e165SJames Wright return BoundaryIntegral_Jacobian(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 46520840d50SJames Wright } 46620840d50SJames Wright 4672b730f8bSJeremy L Thompson CEED_QFUNCTION(BoundaryIntegral_Jacobian_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 468be91e165SJames Wright return BoundaryIntegral_Jacobian(ctx, Q, in, out, STATEVAR_PRIMITIVE); 46920840d50SJames Wright } 47020840d50SJames Wright 47188b783a1SJames Wright #endif // newtonian_h 472