15aed82e4SJeremy L Thompson // Copyright (c) 2017-2024, 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 #include <ceed.h> 11c9c2c079SJeremy L Thompson #include <math.h> 12738af36cSAdelekeBankole #include <stdlib.h> 132b730f8bSJeremy L Thompson 14c6e8c570SJames Wright #include "newtonian_state.h" 15c9c2c079SJeremy L Thompson #include "newtonian_types.h" 162b89d87eSLeila Ghaffari #include "stabilization.h" 17c9c2c079SJeremy L Thompson #include "utils.h" 1888626eedSJames Wright 191d2a9659SKenneth E. Jansen CEED_QFUNCTION_HELPER void InternalDampingLayer(const NewtonianIdealGasContext context, const State s, const CeedScalar sigma, CeedScalar damp_Y[5], 20530ad8c4SKenneth E. Jansen CeedScalar damp_residual[5]) { 21530ad8c4SKenneth E. Jansen ScaleN(damp_Y, sigma, 5); 223bd61617SKenneth E. Jansen State damp_s = StateFromY_fwd(context, s, damp_Y); 23530ad8c4SKenneth E. Jansen 24530ad8c4SKenneth E. Jansen CeedScalar U[5]; 25530ad8c4SKenneth E. Jansen UnpackState_U(damp_s.U, U); 26530ad8c4SKenneth E. Jansen for (int i = 0; i < 5; i++) damp_residual[i] += U[i]; 27530ad8c4SKenneth E. Jansen } 28530ad8c4SKenneth E. Jansen 2988626eedSJames Wright // ***************************************************************************** 3088b783a1SJames Wright // This QFunction sets a "still" initial condition for generic Newtonian IG problems 3188b783a1SJames Wright // ***************************************************************************** 32be91e165SJames Wright CEED_QFUNCTION_HELPER int ICsNewtonianIG(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateVariable state_var) { 3388b783a1SJames Wright // Inputs 3488b783a1SJames Wright 3588b783a1SJames Wright // Outputs 3688b783a1SJames Wright CeedScalar(*q0)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 3788b783a1SJames Wright 3888626eedSJames Wright // Context 3988626eedSJames Wright const SetupContext context = (SetupContext)ctx; 4088626eedSJames Wright 4188b783a1SJames Wright // Quadrature Point Loop 422b730f8bSJeremy L Thompson CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 4388b783a1SJames Wright CeedScalar q[5] = {0.}; 443bd61617SKenneth E. Jansen State s = StateFromPrimitive(&context->gas, context->reference); 45be91e165SJames Wright StateToQ(&context->gas, s, q, state_var); 462b730f8bSJeremy L Thompson for (CeedInt j = 0; j < 5; j++) q0[j][i] = q[j]; 4788b783a1SJames Wright } // End of Quadrature Point Loop 4888b783a1SJames Wright return 0; 4988b783a1SJames Wright } 5088b783a1SJames Wright 512b730f8bSJeremy L Thompson CEED_QFUNCTION(ICsNewtonianIG_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 52be91e165SJames Wright return ICsNewtonianIG(ctx, Q, in, out, STATEVAR_PRIMITIVE); 53d310b3d3SAdeleke O. Bankole } 54d310b3d3SAdeleke O. Bankole CEED_QFUNCTION(ICsNewtonianIG_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 55be91e165SJames Wright return ICsNewtonianIG(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 56dc805cc4SLeila Ghaffari } 57dc805cc4SLeila Ghaffari 58dc805cc4SLeila Ghaffari // ***************************************************************************** 59ea61e9acSJeremy L Thompson // This QFunction implements the following formulation of Navier-Stokes with explicit time stepping method 6088b783a1SJames Wright // 61ea61e9acSJeremy L Thompson // This is 3D compressible Navier-Stokes in conservation form with state variables of density, momentum density, and total energy density. 6288b783a1SJames Wright // 6388b783a1SJames Wright // State Variables: q = ( rho, U1, U2, U3, E ) 6488b783a1SJames Wright // rho - Mass Density 6588b783a1SJames Wright // Ui - Momentum Density, Ui = rho ui 6688b783a1SJames Wright // E - Total Energy Density, E = rho (cv T + (u u)/2 + g z) 6788b783a1SJames Wright // 6888b783a1SJames Wright // Navier-Stokes Equations: 6988b783a1SJames Wright // drho/dt + div( U ) = 0 7088b783a1SJames Wright // dU/dt + div( rho (u x u) + P I3 ) + rho g khat = div( Fu ) 7188b783a1SJames Wright // dE/dt + div( (E + P) u ) = div( Fe ) 7288b783a1SJames Wright // 7388b783a1SJames Wright // Viscous Stress: 7488b783a1SJames Wright // Fu = mu (grad( u ) + grad( u )^T + lambda div ( u ) I3) 7588b783a1SJames Wright // 7688b783a1SJames Wright // Thermal Stress: 7788b783a1SJames Wright // Fe = u Fu + k grad( T ) 7888626eedSJames Wright // Equation of State 7988b783a1SJames Wright // P = (gamma - 1) (E - rho (u u) / 2 - rho g z) 8088b783a1SJames Wright // 8188b783a1SJames Wright // Stabilization: 8288b783a1SJames Wright // Tau = diag(TauC, TauM, TauM, TauM, TauE) 8388b783a1SJames Wright // f1 = rho sqrt(ui uj gij) 8488b783a1SJames Wright // gij = dXi/dX * dXi/dX 8588b783a1SJames Wright // TauC = Cc f1 / (8 gii) 8688b783a1SJames Wright // TauM = min( 1 , 1 / f1 ) 8788b783a1SJames Wright // TauE = TauM / (Ce cv) 8888b783a1SJames Wright // 8988b783a1SJames Wright // SU = Galerkin + grad(v) . ( Ai^T * Tau * (Aj q,j) ) 9088b783a1SJames Wright // 9188b783a1SJames Wright // Constants: 9288b783a1SJames Wright // lambda = - 2 / 3, From Stokes hypothesis 9388b783a1SJames Wright // mu , Dynamic viscosity 9488b783a1SJames Wright // k , Thermal conductivity 9588b783a1SJames Wright // cv , Specific heat, constant volume 9688b783a1SJames Wright // cp , Specific heat, constant pressure 9788b783a1SJames Wright // g , Gravity 9888b783a1SJames Wright // gamma = cp / cv, Specific heat ratio 9988b783a1SJames Wright // 100ea61e9acSJeremy 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 101ea61e9acSJeremy L Thompson // gradu ) 10288b783a1SJames Wright // ***************************************************************************** 1032b730f8bSJeremy L Thompson CEED_QFUNCTION(RHSFunction_Newtonian)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 10488b783a1SJames Wright // Inputs 10546603fc5SJames Wright const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 1069b6a821dSJames Wright const CeedScalar(*Grad_q) = in[1]; 107f3e15844SJames Wright const CeedScalar(*q_data) = in[2]; 10846603fc5SJames Wright 10988b783a1SJames Wright // Outputs 11046603fc5SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 11146603fc5SJames Wright CeedScalar(*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 11288b783a1SJames Wright 11388b783a1SJames Wright // Context 11488b783a1SJames Wright NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 11588626eedSJames Wright const CeedScalar *g = context->g; 11688626eedSJames Wright const CeedScalar dt = context->dt; 11788b783a1SJames Wright 11888b783a1SJames Wright // Quadrature Point Loop 11946603fc5SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 120f3e15844SJames Wright CeedScalar U[5], wdetJ, dXdx[3][3]; 1215c677226SJed Brown for (int j = 0; j < 5; j++) U[j] = q[j][i]; 122f3e15844SJames Wright StoredValuesUnpack(Q, i, 0, 1, q_data, &wdetJ); 123f3e15844SJames Wright StoredValuesUnpack(Q, i, 1, 9, q_data, (CeedScalar *)dXdx); 1243bd61617SKenneth E. Jansen State s = StateFromU(context, U); 1255c677226SJed Brown 1265c677226SJed Brown State grad_s[3]; 1273bd61617SKenneth E. Jansen StatePhysicalGradientFromReference(Q, i, context, s, STATEVAR_CONSERVATIVE, Grad_q, dXdx, grad_s); 1285c677226SJed Brown 1295c677226SJed Brown CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 130d08fcc28SJames Wright KMStrainRate_State(grad_s, strain_rate); 1315c677226SJed Brown NewtonianStress(context, strain_rate, kmstress); 1325c677226SJed Brown KMUnpack(kmstress, stress); 1335c677226SJed Brown ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 1345c677226SJed Brown 1355c677226SJed Brown StateConservative F_inviscid[3]; 1365c677226SJed Brown FluxInviscid(context, s, F_inviscid); 1375c677226SJed Brown 1385c677226SJed Brown // Total flux 1395c677226SJed Brown CeedScalar Flux[5][3]; 1402b89d87eSLeila Ghaffari FluxTotal(F_inviscid, stress, Fe, Flux); 1415c677226SJed Brown 1427b69c783SJames Wright for (CeedInt j = 0; j < 5; j++) { 1437b69c783SJames 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]); 1442b730f8bSJeremy L Thompson } 1455c677226SJed Brown 146858ec087SKenneth 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)}; 1472b730f8bSJeremy L Thompson for (int j = 0; j < 5; j++) v[j][i] = wdetJ * body_force[j]; 14888b783a1SJames Wright 1492b89d87eSLeila Ghaffari // -- Stabilization method: none (Galerkin), SU, or SUPG 1502b89d87eSLeila Ghaffari CeedScalar Tau_d[3], stab[5][3], U_dot[5] = {0}; 1512b89d87eSLeila Ghaffari Tau_diagPrim(context, s, dXdx, dt, Tau_d); 1523bd61617SKenneth E. Jansen Stabilization(context, s, Tau_d, grad_s, U_dot, body_force, stab); 15388b783a1SJames Wright 1542b730f8bSJeremy L Thompson for (CeedInt j = 0; j < 5; j++) { 1552b730f8bSJeremy 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]); 1562b730f8bSJeremy L Thompson } 15788b783a1SJames Wright } // End Quadrature Point Loop 15888b783a1SJames Wright 15988b783a1SJames Wright // Return 16088b783a1SJames Wright return 0; 16188b783a1SJames Wright } 16288b783a1SJames Wright 16388b783a1SJames Wright // ***************************************************************************** 164ea61e9acSJeremy L Thompson // This QFunction implements the Navier-Stokes equations (mentioned above) with implicit time stepping method 16588b783a1SJames Wright // 16688b783a1SJames Wright // SU = Galerkin + grad(v) . ( Ai^T * Tau * (Aj q,j) ) 16788b783a1SJames Wright // SUPG = Galerkin + grad(v) . ( Ai^T * Tau * (q_dot + Aj q,j - body force) ) 168ea61e9acSJeremy L Thompson // (diffusive terms will be added later) 16988b783a1SJames Wright // ***************************************************************************** 170be91e165SJames Wright CEED_QFUNCTION_HELPER int IFunction_Newtonian(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateVariable state_var) { 17188b783a1SJames Wright // Inputs 17246603fc5SJames Wright const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 1739b6a821dSJames Wright const CeedScalar(*Grad_q) = in[1]; 17446603fc5SJames Wright const CeedScalar(*q_dot)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2]; 175f3e15844SJames Wright const CeedScalar(*q_data) = in[3]; 17646603fc5SJames Wright const CeedScalar(*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 17746603fc5SJames Wright 17888b783a1SJames Wright // Outputs 17946603fc5SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 18046603fc5SJames Wright CeedScalar(*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 181f3e15844SJames Wright CeedScalar(*jac_data) = out[2]; 18246603fc5SJames Wright 18388b783a1SJames Wright // Context 18488b783a1SJames Wright NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 18588626eedSJames Wright const CeedScalar *g = context->g; 18688626eedSJames Wright const CeedScalar dt = context->dt; 187530ad8c4SKenneth E. Jansen const CeedScalar P0 = context->P0; 18888b783a1SJames Wright 18988b783a1SJames Wright // Quadrature Point Loop 19046603fc5SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 19146603fc5SJames Wright const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 1925c677226SJed Brown const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 1933bd61617SKenneth E. Jansen const State s = StateFromQ(context, qi, state_var); 1945c677226SJed Brown 195f3e15844SJames Wright CeedScalar wdetJ, dXdx[3][3]; 196f3e15844SJames Wright QdataUnpack_3D(Q, i, q_data, &wdetJ, dXdx); 1975c677226SJed Brown State grad_s[3]; 1983bd61617SKenneth E. Jansen StatePhysicalGradientFromReference(Q, i, context, s, state_var, Grad_q, dXdx, grad_s); 1995c677226SJed Brown 2005c677226SJed Brown CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 201d08fcc28SJames Wright KMStrainRate_State(grad_s, strain_rate); 2025c677226SJed Brown NewtonianStress(context, strain_rate, kmstress); 2035c677226SJed Brown KMUnpack(kmstress, stress); 2045c677226SJed Brown ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 2055c677226SJed Brown 2065c677226SJed Brown StateConservative F_inviscid[3]; 2075c677226SJed Brown FluxInviscid(context, s, F_inviscid); 2085c677226SJed Brown 2095c677226SJed Brown // Total flux 2105c677226SJed Brown CeedScalar Flux[5][3]; 2112b89d87eSLeila Ghaffari FluxTotal(F_inviscid, stress, Fe, Flux); 2125c677226SJed Brown 2137b69c783SJames Wright for (CeedInt j = 0; j < 5; j++) { 2147b69c783SJames Wright for (CeedInt k = 0; k < 3; k++) { 2157b69c783SJames 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]); 21646603fc5SJames Wright } 2172b730f8bSJeremy L Thompson } 2185c677226SJed Brown 219858ec087SKenneth 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)}; 22088b783a1SJames Wright 2212b89d87eSLeila Ghaffari // -- Stabilization method: none (Galerkin), SU, or SUPG 2223bd61617SKenneth E. Jansen CeedScalar Tau_d[3], stab[5][3], U_dot[5] = {0}, qi_dot[5]; 2233d02368aSJames Wright for (int j = 0; j < 5; j++) qi_dot[j] = q_dot[j][i]; 2243bd61617SKenneth E. Jansen State s_dot = StateFromQ_fwd(context, s, qi_dot, state_var); 2253d02368aSJames Wright UnpackState_U(s_dot.U, U_dot); 2263d02368aSJames Wright 2272b730f8bSJeremy L Thompson for (CeedInt j = 0; j < 5; j++) v[j][i] = wdetJ * (U_dot[j] - body_force[j]); 228530ad8c4SKenneth E. Jansen if (context->idl_enable) { 2291d2a9659SKenneth E. Jansen const CeedScalar sigma = LinearRampCoefficient(context->idl_amplitude, context->idl_length, context->idl_start, x_i[0]); 2301d2a9659SKenneth E. Jansen StoredValuesPack(Q, i, 14, 1, &sigma, jac_data); 231530ad8c4SKenneth E. Jansen CeedScalar damp_state[5] = {s.Y.pressure - P0, 0, 0, 0, 0}, idl_residual[5] = {0.}; 2321d2a9659SKenneth E. Jansen InternalDampingLayer(context, s, sigma, damp_state, idl_residual); 233530ad8c4SKenneth E. Jansen for (int j = 0; j < 5; j++) v[j][i] += wdetJ * idl_residual[j]; 234530ad8c4SKenneth E. Jansen } 235530ad8c4SKenneth E. Jansen 2362b89d87eSLeila Ghaffari Tau_diagPrim(context, s, dXdx, dt, Tau_d); 2373bd61617SKenneth E. Jansen Stabilization(context, s, Tau_d, grad_s, U_dot, body_force, stab); 23888b783a1SJames Wright 2392b730f8bSJeremy L Thompson for (CeedInt j = 0; j < 5; j++) { 24046603fc5SJames Wright for (CeedInt k = 0; k < 3; k++) { 24146603fc5SJames 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]); 24246603fc5SJames Wright } 2432b730f8bSJeremy L Thompson } 244f3e15844SJames Wright StoredValuesPack(Q, i, 0, 5, qi, jac_data); 245f3e15844SJames Wright StoredValuesPack(Q, i, 5, 6, kmstress, jac_data); 246f3e15844SJames Wright StoredValuesPack(Q, i, 11, 3, Tau_d, jac_data); 24788b783a1SJames Wright 24888b783a1SJames Wright } // End Quadrature Point Loop 24988b783a1SJames Wright 25088b783a1SJames Wright // Return 25188b783a1SJames Wright return 0; 25288b783a1SJames Wright } 253e334ad8fSJed Brown 2542b730f8bSJeremy L Thompson CEED_QFUNCTION(IFunction_Newtonian_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 255be91e165SJames Wright return IFunction_Newtonian(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 2563d02368aSJames Wright } 2573d02368aSJames Wright 2582b730f8bSJeremy L Thompson CEED_QFUNCTION(IFunction_Newtonian_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 259be91e165SJames Wright return IFunction_Newtonian(ctx, Q, in, out, STATEVAR_PRIMITIVE); 2603d02368aSJames Wright } 2613d02368aSJames Wright 262dc805cc4SLeila Ghaffari // ***************************************************************************** 263ea61e9acSJeremy L Thompson // This QFunction implements the jacobian of the Navier-Stokes equations for implicit time stepping method. 264dc805cc4SLeila Ghaffari // ***************************************************************************** 265be91e165SJames Wright CEED_QFUNCTION_HELPER int IJacobian_Newtonian(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateVariable state_var) { 266e334ad8fSJed Brown // Inputs 26746603fc5SJames Wright const CeedScalar(*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 2689b6a821dSJames Wright const CeedScalar(*Grad_dq) = in[1]; 269f3e15844SJames Wright const CeedScalar(*q_data) = in[2]; 2701d2a9659SKenneth E. Jansen const CeedScalar(*jac_data) = in[3]; 27146603fc5SJames Wright 272e334ad8fSJed Brown // Outputs 27346603fc5SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 27446603fc5SJames Wright CeedScalar(*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 27546603fc5SJames Wright 276e334ad8fSJed Brown // Context 277e334ad8fSJed Brown NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 278e334ad8fSJed Brown const CeedScalar *g = context->g; 279e334ad8fSJed Brown 280e334ad8fSJed Brown // Quadrature Point Loop 28146603fc5SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 282f3e15844SJames Wright CeedScalar wdetJ, dXdx[3][3]; 283f3e15844SJames Wright QdataUnpack_3D(Q, i, q_data, &wdetJ, dXdx); 284e334ad8fSJed Brown 285c98a0616SJames Wright CeedScalar qi[5], kmstress[6], Tau_d[3]; 286f3e15844SJames Wright StoredValuesUnpack(Q, i, 0, 5, jac_data, qi); 287f3e15844SJames Wright StoredValuesUnpack(Q, i, 5, 6, jac_data, kmstress); 288f3e15844SJames Wright StoredValuesUnpack(Q, i, 11, 3, jac_data, Tau_d); 2893bd61617SKenneth E. Jansen State s = StateFromQ(context, qi, state_var); 290e334ad8fSJed Brown 2913bd61617SKenneth E. Jansen CeedScalar dqi[5]; 2923d02368aSJames Wright for (int j = 0; j < 5; j++) dqi[j] = dq[j][i]; 2933bd61617SKenneth E. Jansen State ds = StateFromQ_fwd(context, s, dqi, state_var); 294e334ad8fSJed Brown 295e334ad8fSJed Brown State grad_ds[3]; 2963bd61617SKenneth E. Jansen StatePhysicalGradientFromReference(Q, i, context, s, state_var, Grad_dq, dXdx, grad_ds); 297e334ad8fSJed Brown 298e334ad8fSJed Brown CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 299d08fcc28SJames Wright KMStrainRate_State(grad_ds, dstrain_rate); 300e334ad8fSJed Brown NewtonianStress(context, dstrain_rate, dkmstress); 301e334ad8fSJed Brown KMUnpack(dkmstress, dstress); 302e334ad8fSJed Brown KMUnpack(kmstress, stress); 303e334ad8fSJed Brown ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 304e334ad8fSJed Brown 305e334ad8fSJed Brown StateConservative dF_inviscid[3]; 306e334ad8fSJed Brown FluxInviscid_fwd(context, s, ds, dF_inviscid); 307e334ad8fSJed Brown 308e334ad8fSJed Brown // Total flux 309e334ad8fSJed Brown CeedScalar dFlux[5][3]; 3102b89d87eSLeila Ghaffari FluxTotal(dF_inviscid, dstress, dFe, dFlux); 311e334ad8fSJed Brown 31251b00d91SJames Wright for (int j = 0; j < 5; j++) { 31351b00d91SJames 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]); 3142b730f8bSJeremy L Thompson } 315e334ad8fSJed Brown 316858ec087SKenneth 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)}; 3173d02368aSJames Wright CeedScalar dU[5] = {0.}; 3183d02368aSJames Wright UnpackState_U(ds.U, dU); 3192b730f8bSJeremy L Thompson for (int j = 0; j < 5; j++) v[j][i] = wdetJ * (context->ijacobian_time_shift * dU[j] - dbody_force[j]); 320e334ad8fSJed Brown 321530ad8c4SKenneth E. Jansen if (context->idl_enable) { 3221d2a9659SKenneth E. Jansen const CeedScalar sigma = jac_data[14 * Q + i]; 323530ad8c4SKenneth E. Jansen CeedScalar damp_state[5] = {ds.Y.pressure, 0, 0, 0, 0}, idl_residual[5] = {0.}; 324530ad8c4SKenneth E. Jansen // This is a Picard-type linearization of the damping and could be replaced by an InternalDampingLayer_fwd that uses s and ds. 3251d2a9659SKenneth E. Jansen InternalDampingLayer(context, s, sigma, damp_state, idl_residual); 326530ad8c4SKenneth E. Jansen for (int j = 0; j < 5; j++) v[j][i] += wdetJ * idl_residual[j]; 327530ad8c4SKenneth E. Jansen } 328530ad8c4SKenneth E. Jansen 3292b89d87eSLeila Ghaffari // -- Stabilization method: none (Galerkin), SU, or SUPG 3302b89d87eSLeila Ghaffari CeedScalar dstab[5][3], U_dot[5] = {0}; 3312b89d87eSLeila Ghaffari for (CeedInt j = 0; j < 5; j++) U_dot[j] = context->ijacobian_time_shift * dU[j]; 3323bd61617SKenneth E. Jansen Stabilization(context, s, Tau_d, grad_ds, U_dot, dbody_force, dstab); 3332b89d87eSLeila Ghaffari 3342b730f8bSJeremy L Thompson for (int j = 0; j < 5; j++) { 3352b730f8bSJeremy 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]); 3362b730f8bSJeremy L Thompson } 337e334ad8fSJed Brown } // End Quadrature Point Loop 338e334ad8fSJed Brown return 0; 339e334ad8fSJed Brown } 34065dd5cafSJames Wright 3412b730f8bSJeremy L Thompson CEED_QFUNCTION(IJacobian_Newtonian_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 342be91e165SJames Wright return IJacobian_Newtonian(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 3433d02368aSJames Wright } 3443d02368aSJames Wright 3452b730f8bSJeremy L Thompson CEED_QFUNCTION(IJacobian_Newtonian_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 346be91e165SJames Wright return IJacobian_Newtonian(ctx, Q, in, out, STATEVAR_PRIMITIVE); 3473d02368aSJames Wright } 3483d02368aSJames Wright 3492b89d87eSLeila Ghaffari // ***************************************************************************** 35065dd5cafSJames Wright // Compute boundary integral (ie. for strongly set inflows) 3512b89d87eSLeila Ghaffari // ***************************************************************************** 352be91e165SJames Wright CEED_QFUNCTION_HELPER int BoundaryIntegral(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateVariable state_var) { 353f21e6b1cSJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 35446603fc5SJames Wright const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 3559b6a821dSJames Wright const CeedScalar(*Grad_q) = in[1]; 356f3e15844SJames Wright const CeedScalar(*q_data_sur) = in[2]; 35746603fc5SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 358f21e6b1cSJames Wright CeedScalar(*jac_data_sur) = context->is_implicit ? out[1] : NULL; 35965dd5cafSJames Wright 3602c4e60d7SJames Wright const bool is_implicit = context->is_implicit; 36165dd5cafSJames Wright 3622b730f8bSJeremy L Thompson CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 363efe9d856SJames Wright const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 3643bd61617SKenneth E. Jansen State s = StateFromQ(context, qi, state_var); 36565dd5cafSJames Wright 366f3e15844SJames Wright CeedScalar wdetJb, dXdx[2][3], norm[3]; 367f3e15844SJames Wright QdataBoundaryUnpack_3D(Q, i, q_data_sur, &wdetJb, dXdx, norm); 368f3e15844SJames Wright wdetJb *= is_implicit ? -1. : 1.; 36965dd5cafSJames Wright 3702c4e60d7SJames Wright State grad_s[3]; 3713bd61617SKenneth E. Jansen StatePhysicalGradientFromReference_Boundary(Q, i, context, s, state_var, Grad_q, dXdx, grad_s); 37265dd5cafSJames Wright 3732c4e60d7SJames Wright CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 374d08fcc28SJames Wright KMStrainRate_State(grad_s, strain_rate); 3752c4e60d7SJames Wright NewtonianStress(context, strain_rate, kmstress); 3762c4e60d7SJames Wright KMUnpack(kmstress, stress); 3772c4e60d7SJames Wright ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 3782c4e60d7SJames Wright 3792c4e60d7SJames Wright StateConservative F_inviscid[3]; 3802c4e60d7SJames Wright FluxInviscid(context, s, F_inviscid); 3812c4e60d7SJames Wright 3825bce47c7SJames Wright CeedScalar Flux[5]; 3835bce47c7SJames Wright FluxTotal_Boundary(F_inviscid, stress, Fe, norm, Flux); 3842c4e60d7SJames Wright 3855bce47c7SJames Wright for (CeedInt j = 0; j < 5; j++) v[j][i] = -wdetJb * Flux[j]; 38665dd5cafSJames Wright 387f21e6b1cSJames Wright if (is_implicit) { 388f3e15844SJames Wright StoredValuesPack(Q, i, 0, 5, qi, jac_data_sur); 389f3e15844SJames Wright StoredValuesPack(Q, i, 5, 6, kmstress, jac_data_sur); 39065dd5cafSJames Wright } 391f21e6b1cSJames Wright } 39265dd5cafSJames Wright return 0; 39365dd5cafSJames Wright } 39465dd5cafSJames Wright 3952b730f8bSJeremy L Thompson CEED_QFUNCTION(BoundaryIntegral_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 396be91e165SJames Wright return BoundaryIntegral(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 39720840d50SJames Wright } 39820840d50SJames Wright 3992b730f8bSJeremy L Thompson CEED_QFUNCTION(BoundaryIntegral_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 400be91e165SJames Wright return BoundaryIntegral(ctx, Q, in, out, STATEVAR_PRIMITIVE); 40120840d50SJames Wright } 40220840d50SJames Wright 4032b89d87eSLeila Ghaffari // ***************************************************************************** 404b55ac660SJames Wright // Jacobian for "set nothing" boundary integral 4052b89d87eSLeila Ghaffari // ***************************************************************************** 4062b730f8bSJeremy L Thompson CEED_QFUNCTION_HELPER int BoundaryIntegral_Jacobian(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, 407be91e165SJames Wright StateVariable state_var) { 40846603fc5SJames Wright const CeedScalar(*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 4099b6a821dSJames Wright const CeedScalar(*Grad_dq) = in[1]; 410f3e15844SJames Wright const CeedScalar(*q_data_sur) = in[2]; 411c1d93bc4SKenneth E. Jansen const CeedScalar(*jac_data_sur) = in[4]; 412b55ac660SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 413b55ac660SJames Wright 414b55ac660SJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 415f3e15844SJames Wright const bool is_implicit = context->is_implicit; 416b55ac660SJames Wright 41746603fc5SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 418f3e15844SJames Wright CeedScalar wdetJb, dXdx[2][3], norm[3]; 419f3e15844SJames Wright QdataBoundaryUnpack_3D(Q, i, q_data_sur, &wdetJb, dXdx, norm); 420f3e15844SJames Wright wdetJb *= is_implicit ? -1. : 1.; 421b55ac660SJames Wright 4223bd61617SKenneth E. Jansen CeedScalar qi[5], kmstress[6], dqi[5]; 423f3e15844SJames Wright StoredValuesUnpack(Q, i, 0, 5, jac_data_sur, qi); 424f3e15844SJames Wright StoredValuesUnpack(Q, i, 5, 6, jac_data_sur, kmstress); 425efe9d856SJames Wright for (int j = 0; j < 5; j++) dqi[j] = dq[j][i]; 42657e55a1cSJames Wright 4273bd61617SKenneth E. Jansen State s = StateFromQ(context, qi, state_var); 4283bd61617SKenneth E. Jansen State ds = StateFromQ_fwd(context, s, dqi, state_var); 429b55ac660SJames Wright 430b55ac660SJames Wright State grad_ds[3]; 4313bd61617SKenneth E. Jansen StatePhysicalGradientFromReference_Boundary(Q, i, context, s, state_var, Grad_dq, dXdx, grad_ds); 432b55ac660SJames Wright 433b55ac660SJames Wright CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 434d08fcc28SJames Wright KMStrainRate_State(grad_ds, dstrain_rate); 435b55ac660SJames Wright NewtonianStress(context, dstrain_rate, dkmstress); 436b55ac660SJames Wright KMUnpack(dkmstress, dstress); 437b55ac660SJames Wright KMUnpack(kmstress, stress); 438b55ac660SJames Wright ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 439b55ac660SJames Wright 440b55ac660SJames Wright StateConservative dF_inviscid[3]; 441b55ac660SJames Wright FluxInviscid_fwd(context, s, ds, dF_inviscid); 442b55ac660SJames Wright 4435bce47c7SJames Wright CeedScalar dFlux[5]; 4445bce47c7SJames Wright FluxTotal_Boundary(dF_inviscid, dstress, dFe, norm, dFlux); 445b55ac660SJames Wright 4465bce47c7SJames Wright for (int j = 0; j < 5; j++) v[j][i] = -wdetJb * dFlux[j]; 447*4c0e8230SJames Wright } 448b55ac660SJames Wright return 0; 449b55ac660SJames Wright } 450b55ac660SJames Wright 4512b730f8bSJeremy L Thompson CEED_QFUNCTION(BoundaryIntegral_Jacobian_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 452be91e165SJames Wright return BoundaryIntegral_Jacobian(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 45320840d50SJames Wright } 45420840d50SJames Wright 4552b730f8bSJeremy L Thompson CEED_QFUNCTION(BoundaryIntegral_Jacobian_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 456be91e165SJames Wright return BoundaryIntegral_Jacobian(ctx, Q, in, out, STATEVAR_PRIMITIVE); 45720840d50SJames Wright } 458