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 23*94a7b3d2SKenneth E. Jansen CEED_QFUNCTION_HELPER void InternalDampingLayer(const NewtonianIdealGasContext context, const State s, const CeedScalar sigma, CeedScalar damp_Y[5], 24e7754af5SKenneth E. Jansen CeedScalar damp_residual[5]) { 25e7754af5SKenneth E. Jansen ScaleN(damp_Y, sigma, 5); 26edcfef1bSKenneth E. Jansen State damp_s = StateFromY_fwd(context, s, damp_Y); 27e7754af5SKenneth E. Jansen 28e7754af5SKenneth E. Jansen CeedScalar U[5]; 29e7754af5SKenneth E. Jansen UnpackState_U(damp_s.U, U); 30e7754af5SKenneth E. Jansen for (int i = 0; i < 5; i++) damp_residual[i] += U[i]; 31e7754af5SKenneth E. Jansen } 32e7754af5SKenneth E. Jansen 33bb8a0c61SJames Wright // ***************************************************************************** 343a8779fbSJames Wright // This QFunction sets a "still" initial condition for generic Newtonian IG problems 353a8779fbSJames Wright // ***************************************************************************** 368fff8293SJames Wright CEED_QFUNCTION_HELPER int ICsNewtonianIG(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateVariable state_var) { 373a8779fbSJames Wright // Inputs 383a8779fbSJames Wright 393a8779fbSJames Wright // Outputs 403a8779fbSJames Wright CeedScalar(*q0)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 413a8779fbSJames Wright 42bb8a0c61SJames Wright // Context 43bb8a0c61SJames Wright const SetupContext context = (SetupContext)ctx; 44bb8a0c61SJames Wright 453a8779fbSJames Wright // Quadrature Point Loop 462b916ea7SJeremy L Thompson CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 473a8779fbSJames Wright CeedScalar q[5] = {0.}; 48edcfef1bSKenneth E. Jansen State s = StateFromPrimitive(&context->gas, context->reference); 498fff8293SJames Wright StateToQ(&context->gas, s, q, state_var); 502b916ea7SJeremy L Thompson for (CeedInt j = 0; j < 5; j++) q0[j][i] = q[j]; 513a8779fbSJames Wright } // End of Quadrature Point Loop 523a8779fbSJames Wright return 0; 533a8779fbSJames Wright } 543a8779fbSJames Wright 552b916ea7SJeremy L Thompson CEED_QFUNCTION(ICsNewtonianIG_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 568fff8293SJames Wright return ICsNewtonianIG(ctx, Q, in, out, STATEVAR_PRIMITIVE); 57b8fb7609SAdeleke O. Bankole } 58b8fb7609SAdeleke O. Bankole CEED_QFUNCTION(ICsNewtonianIG_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 598fff8293SJames Wright return ICsNewtonianIG(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 60cbe60e31SLeila Ghaffari } 61cbe60e31SLeila Ghaffari 62cbe60e31SLeila Ghaffari // ***************************************************************************** 6304e40bb6SJeremy L Thompson // This QFunction implements the following formulation of Navier-Stokes with explicit time stepping method 643a8779fbSJames Wright // 6504e40bb6SJeremy L Thompson // This is 3D compressible Navier-Stokes in conservation form with state variables of density, momentum density, and total energy density. 663a8779fbSJames Wright // 673a8779fbSJames Wright // State Variables: q = ( rho, U1, U2, U3, E ) 683a8779fbSJames Wright // rho - Mass Density 693a8779fbSJames Wright // Ui - Momentum Density, Ui = rho ui 703a8779fbSJames Wright // E - Total Energy Density, E = rho (cv T + (u u)/2 + g z) 713a8779fbSJames Wright // 723a8779fbSJames Wright // Navier-Stokes Equations: 733a8779fbSJames Wright // drho/dt + div( U ) = 0 743a8779fbSJames Wright // dU/dt + div( rho (u x u) + P I3 ) + rho g khat = div( Fu ) 753a8779fbSJames Wright // dE/dt + div( (E + P) u ) = div( Fe ) 763a8779fbSJames Wright // 773a8779fbSJames Wright // Viscous Stress: 783a8779fbSJames Wright // Fu = mu (grad( u ) + grad( u )^T + lambda div ( u ) I3) 793a8779fbSJames Wright // 803a8779fbSJames Wright // Thermal Stress: 813a8779fbSJames Wright // Fe = u Fu + k grad( T ) 82bb8a0c61SJames Wright // Equation of State 833a8779fbSJames Wright // P = (gamma - 1) (E - rho (u u) / 2 - rho g z) 843a8779fbSJames Wright // 853a8779fbSJames Wright // Stabilization: 863a8779fbSJames Wright // Tau = diag(TauC, TauM, TauM, TauM, TauE) 873a8779fbSJames Wright // f1 = rho sqrt(ui uj gij) 883a8779fbSJames Wright // gij = dXi/dX * dXi/dX 893a8779fbSJames Wright // TauC = Cc f1 / (8 gii) 903a8779fbSJames Wright // TauM = min( 1 , 1 / f1 ) 913a8779fbSJames Wright // TauE = TauM / (Ce cv) 923a8779fbSJames Wright // 933a8779fbSJames Wright // SU = Galerkin + grad(v) . ( Ai^T * Tau * (Aj q,j) ) 943a8779fbSJames Wright // 953a8779fbSJames Wright // Constants: 963a8779fbSJames Wright // lambda = - 2 / 3, From Stokes hypothesis 973a8779fbSJames Wright // mu , Dynamic viscosity 983a8779fbSJames Wright // k , Thermal conductivity 993a8779fbSJames Wright // cv , Specific heat, constant volume 1003a8779fbSJames Wright // cp , Specific heat, constant pressure 1013a8779fbSJames Wright // g , Gravity 1023a8779fbSJames Wright // gamma = cp / cv, Specific heat ratio 1033a8779fbSJames Wright // 10404e40bb6SJeremy 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 10504e40bb6SJeremy L Thompson // gradu ) 1063a8779fbSJames Wright // ***************************************************************************** 1072b916ea7SJeremy L Thompson CEED_QFUNCTION(RHSFunction_Newtonian)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 1083a8779fbSJames Wright // Inputs 1093d65b166SJames Wright const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 11087bd45e7SJames Wright const CeedScalar(*Grad_q) = in[1]; 111ade49511SJames Wright const CeedScalar(*q_data) = in[2]; 1123d65b166SJames Wright 1133a8779fbSJames Wright // Outputs 1143d65b166SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 1153d65b166SJames Wright CeedScalar(*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 1163a8779fbSJames Wright 1173a8779fbSJames Wright // Context 1183a8779fbSJames Wright NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 119bb8a0c61SJames Wright const CeedScalar *g = context->g; 120bb8a0c61SJames Wright const CeedScalar dt = context->dt; 1213a8779fbSJames Wright 1223a8779fbSJames Wright // Quadrature Point Loop 1233d65b166SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 124ade49511SJames Wright CeedScalar U[5], wdetJ, dXdx[3][3]; 125c1a52365SJed Brown for (int j = 0; j < 5; j++) U[j] = q[j][i]; 126ade49511SJames Wright StoredValuesUnpack(Q, i, 0, 1, q_data, &wdetJ); 127ade49511SJames Wright StoredValuesUnpack(Q, i, 1, 9, q_data, (CeedScalar *)dXdx); 128edcfef1bSKenneth E. Jansen State s = StateFromU(context, U); 129c1a52365SJed Brown 130c1a52365SJed Brown State grad_s[3]; 131edcfef1bSKenneth E. Jansen StatePhysicalGradientFromReference(Q, i, context, s, STATEVAR_CONSERVATIVE, Grad_q, dXdx, grad_s); 132c1a52365SJed Brown 133c1a52365SJed Brown CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 13440a33f2dSJames Wright KMStrainRate_State(grad_s, strain_rate); 135c1a52365SJed Brown NewtonianStress(context, strain_rate, kmstress); 136c1a52365SJed Brown KMUnpack(kmstress, stress); 137c1a52365SJed Brown ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 138c1a52365SJed Brown 139c1a52365SJed Brown StateConservative F_inviscid[3]; 140c1a52365SJed Brown FluxInviscid(context, s, F_inviscid); 141c1a52365SJed Brown 142c1a52365SJed Brown // Total flux 143c1a52365SJed Brown CeedScalar Flux[5][3]; 144d1b9ef12SLeila Ghaffari FluxTotal(F_inviscid, stress, Fe, Flux); 145c1a52365SJed Brown 1467523f6aaSJames Wright for (CeedInt j = 0; j < 5; j++) { 1477523f6aaSJames 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]); 1482b916ea7SJeremy L Thompson } 149c1a52365SJed Brown 15060dbb574SKenneth 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)}; 1512b916ea7SJeremy L Thompson for (int j = 0; j < 5; j++) v[j][i] = wdetJ * body_force[j]; 1523a8779fbSJames Wright 153d1b9ef12SLeila Ghaffari // -- Stabilization method: none (Galerkin), SU, or SUPG 154d1b9ef12SLeila Ghaffari CeedScalar Tau_d[3], stab[5][3], U_dot[5] = {0}; 155d1b9ef12SLeila Ghaffari Tau_diagPrim(context, s, dXdx, dt, Tau_d); 156edcfef1bSKenneth E. Jansen Stabilization(context, s, Tau_d, grad_s, U_dot, body_force, stab); 1573a8779fbSJames Wright 1582b916ea7SJeremy L Thompson for (CeedInt j = 0; j < 5; j++) { 1592b916ea7SJeremy 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]); 1602b916ea7SJeremy L Thompson } 1613a8779fbSJames Wright } // End Quadrature Point Loop 1623a8779fbSJames Wright 1633a8779fbSJames Wright // Return 1643a8779fbSJames Wright return 0; 1653a8779fbSJames Wright } 1663a8779fbSJames Wright 1673a8779fbSJames Wright // ***************************************************************************** 16804e40bb6SJeremy L Thompson // This QFunction implements the Navier-Stokes equations (mentioned above) with implicit time stepping method 1693a8779fbSJames Wright // 1703a8779fbSJames Wright // SU = Galerkin + grad(v) . ( Ai^T * Tau * (Aj q,j) ) 1713a8779fbSJames Wright // SUPG = Galerkin + grad(v) . ( Ai^T * Tau * (q_dot + Aj q,j - body force) ) 17204e40bb6SJeremy L Thompson // (diffusive terms will be added later) 1733a8779fbSJames Wright // ***************************************************************************** 1748fff8293SJames Wright CEED_QFUNCTION_HELPER int IFunction_Newtonian(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateVariable state_var) { 1753a8779fbSJames Wright // Inputs 1763d65b166SJames Wright const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 17787bd45e7SJames Wright const CeedScalar(*Grad_q) = in[1]; 1783d65b166SJames Wright const CeedScalar(*q_dot)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2]; 179ade49511SJames Wright const CeedScalar(*q_data) = in[3]; 1803d65b166SJames Wright const CeedScalar(*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 1813d65b166SJames Wright 1823a8779fbSJames Wright // Outputs 1833d65b166SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 1843d65b166SJames Wright CeedScalar(*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 185ade49511SJames Wright CeedScalar(*jac_data) = out[2]; 1863d65b166SJames Wright 1873a8779fbSJames Wright // Context 1883a8779fbSJames Wright NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 189bb8a0c61SJames Wright const CeedScalar *g = context->g; 190bb8a0c61SJames Wright const CeedScalar dt = context->dt; 191e7754af5SKenneth E. Jansen const CeedScalar P0 = context->P0; 1923a8779fbSJames Wright 1933a8779fbSJames Wright // Quadrature Point Loop 1943d65b166SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 1953d65b166SJames Wright const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 196c1a52365SJed Brown const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 197edcfef1bSKenneth E. Jansen const State s = StateFromQ(context, qi, state_var); 198c1a52365SJed Brown 199ade49511SJames Wright CeedScalar wdetJ, dXdx[3][3]; 200ade49511SJames Wright QdataUnpack_3D(Q, i, q_data, &wdetJ, dXdx); 201c1a52365SJed Brown State grad_s[3]; 202edcfef1bSKenneth E. Jansen StatePhysicalGradientFromReference(Q, i, context, s, state_var, Grad_q, dXdx, grad_s); 203c1a52365SJed Brown 204c1a52365SJed Brown CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 20540a33f2dSJames Wright KMStrainRate_State(grad_s, strain_rate); 206c1a52365SJed Brown NewtonianStress(context, strain_rate, kmstress); 207c1a52365SJed Brown KMUnpack(kmstress, stress); 208c1a52365SJed Brown ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 209c1a52365SJed Brown 210c1a52365SJed Brown StateConservative F_inviscid[3]; 211c1a52365SJed Brown FluxInviscid(context, s, F_inviscid); 212c1a52365SJed Brown 213c1a52365SJed Brown // Total flux 214c1a52365SJed Brown CeedScalar Flux[5][3]; 215d1b9ef12SLeila Ghaffari FluxTotal(F_inviscid, stress, Fe, Flux); 216c1a52365SJed Brown 2177523f6aaSJames Wright for (CeedInt j = 0; j < 5; j++) { 2187523f6aaSJames Wright for (CeedInt k = 0; k < 3; k++) { 2197523f6aaSJames 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]); 2203d65b166SJames Wright } 2212b916ea7SJeremy L Thompson } 222c1a52365SJed Brown 22360dbb574SKenneth 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)}; 2243a8779fbSJames Wright 225d1b9ef12SLeila Ghaffari // -- Stabilization method: none (Galerkin), SU, or SUPG 226edcfef1bSKenneth E. Jansen CeedScalar Tau_d[3], stab[5][3], U_dot[5] = {0}, qi_dot[5]; 22776555becSJames Wright for (int j = 0; j < 5; j++) qi_dot[j] = q_dot[j][i]; 228edcfef1bSKenneth E. Jansen State s_dot = StateFromQ_fwd(context, s, qi_dot, state_var); 22976555becSJames Wright UnpackState_U(s_dot.U, U_dot); 23076555becSJames Wright 2312b916ea7SJeremy L Thompson for (CeedInt j = 0; j < 5; j++) v[j][i] = wdetJ * (U_dot[j] - body_force[j]); 232e7754af5SKenneth E. Jansen if (context->idl_enable) { 233*94a7b3d2SKenneth E. Jansen const CeedScalar sigma = LinearRampCoefficient(context->idl_amplitude, context->idl_length, context->idl_start, x_i[0]); 234*94a7b3d2SKenneth E. Jansen StoredValuesPack(Q, i, 14, 1, &sigma, jac_data); 235e7754af5SKenneth E. Jansen CeedScalar damp_state[5] = {s.Y.pressure - P0, 0, 0, 0, 0}, idl_residual[5] = {0.}; 236*94a7b3d2SKenneth E. Jansen InternalDampingLayer(context, s, sigma, damp_state, idl_residual); 237e7754af5SKenneth E. Jansen for (int j = 0; j < 5; j++) v[j][i] += wdetJ * idl_residual[j]; 238e7754af5SKenneth E. Jansen } 239e7754af5SKenneth E. Jansen 240d1b9ef12SLeila Ghaffari Tau_diagPrim(context, s, dXdx, dt, Tau_d); 241edcfef1bSKenneth E. Jansen Stabilization(context, s, Tau_d, grad_s, U_dot, body_force, stab); 2423a8779fbSJames Wright 2432b916ea7SJeremy L Thompson for (CeedInt j = 0; j < 5; j++) { 2443d65b166SJames Wright for (CeedInt k = 0; k < 3; k++) { 2453d65b166SJames 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]); 2463d65b166SJames Wright } 2472b916ea7SJeremy L Thompson } 248ade49511SJames Wright StoredValuesPack(Q, i, 0, 5, qi, jac_data); 249ade49511SJames Wright StoredValuesPack(Q, i, 5, 6, kmstress, jac_data); 250ade49511SJames Wright StoredValuesPack(Q, i, 11, 3, Tau_d, jac_data); 2513a8779fbSJames Wright 2523a8779fbSJames Wright } // End Quadrature Point Loop 2533a8779fbSJames Wright 2543a8779fbSJames Wright // Return 2553a8779fbSJames Wright return 0; 2563a8779fbSJames Wright } 257f0b65372SJed Brown 2582b916ea7SJeremy L Thompson CEED_QFUNCTION(IFunction_Newtonian_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 2598fff8293SJames Wright return IFunction_Newtonian(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 26076555becSJames Wright } 26176555becSJames Wright 2622b916ea7SJeremy L Thompson CEED_QFUNCTION(IFunction_Newtonian_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 2638fff8293SJames Wright return IFunction_Newtonian(ctx, Q, in, out, STATEVAR_PRIMITIVE); 26476555becSJames Wright } 26576555becSJames Wright 266cbe60e31SLeila Ghaffari // ***************************************************************************** 26704e40bb6SJeremy L Thompson // This QFunction implements the jacobian of the Navier-Stokes equations for implicit time stepping method. 268cbe60e31SLeila Ghaffari // ***************************************************************************** 2698fff8293SJames Wright CEED_QFUNCTION_HELPER int IJacobian_Newtonian(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateVariable state_var) { 270f0b65372SJed Brown // Inputs 2713d65b166SJames Wright const CeedScalar(*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 27287bd45e7SJames Wright const CeedScalar(*Grad_dq) = in[1]; 273ade49511SJames Wright const CeedScalar(*q_data) = in[2]; 274*94a7b3d2SKenneth E. Jansen const CeedScalar(*jac_data) = in[3]; 2753d65b166SJames Wright 276f0b65372SJed Brown // Outputs 2773d65b166SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 2783d65b166SJames Wright CeedScalar(*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 2793d65b166SJames Wright 280f0b65372SJed Brown // Context 281f0b65372SJed Brown NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 282f0b65372SJed Brown const CeedScalar *g = context->g; 283f0b65372SJed Brown 284f0b65372SJed Brown // Quadrature Point Loop 2853d65b166SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 286ade49511SJames Wright CeedScalar wdetJ, dXdx[3][3]; 287ade49511SJames Wright QdataUnpack_3D(Q, i, q_data, &wdetJ, dXdx); 288f0b65372SJed Brown 2898789e95fSJames Wright CeedScalar qi[5], kmstress[6], Tau_d[3]; 290ade49511SJames Wright StoredValuesUnpack(Q, i, 0, 5, jac_data, qi); 291ade49511SJames Wright StoredValuesUnpack(Q, i, 5, 6, jac_data, kmstress); 292ade49511SJames Wright StoredValuesUnpack(Q, i, 11, 3, jac_data, Tau_d); 293edcfef1bSKenneth E. Jansen State s = StateFromQ(context, qi, state_var); 294f0b65372SJed Brown 295edcfef1bSKenneth E. Jansen CeedScalar dqi[5]; 29676555becSJames Wright for (int j = 0; j < 5; j++) dqi[j] = dq[j][i]; 297edcfef1bSKenneth E. Jansen State ds = StateFromQ_fwd(context, s, dqi, state_var); 298f0b65372SJed Brown 299f0b65372SJed Brown State grad_ds[3]; 300edcfef1bSKenneth E. Jansen StatePhysicalGradientFromReference(Q, i, context, s, state_var, Grad_dq, dXdx, grad_ds); 301f0b65372SJed Brown 302f0b65372SJed Brown CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 30340a33f2dSJames Wright KMStrainRate_State(grad_ds, dstrain_rate); 304f0b65372SJed Brown NewtonianStress(context, dstrain_rate, dkmstress); 305f0b65372SJed Brown KMUnpack(dkmstress, dstress); 306f0b65372SJed Brown KMUnpack(kmstress, stress); 307f0b65372SJed Brown ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 308f0b65372SJed Brown 309f0b65372SJed Brown StateConservative dF_inviscid[3]; 310f0b65372SJed Brown FluxInviscid_fwd(context, s, ds, dF_inviscid); 311f0b65372SJed Brown 312f0b65372SJed Brown // Total flux 313f0b65372SJed Brown CeedScalar dFlux[5][3]; 314d1b9ef12SLeila Ghaffari FluxTotal(dF_inviscid, dstress, dFe, dFlux); 315f0b65372SJed Brown 31622387d3aSJames Wright for (int j = 0; j < 5; j++) { 31722387d3aSJames 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]); 3182b916ea7SJeremy L Thompson } 319f0b65372SJed Brown 32060dbb574SKenneth 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)}; 32176555becSJames Wright CeedScalar dU[5] = {0.}; 32276555becSJames Wright UnpackState_U(ds.U, dU); 3232b916ea7SJeremy L Thompson for (int j = 0; j < 5; j++) v[j][i] = wdetJ * (context->ijacobian_time_shift * dU[j] - dbody_force[j]); 324f0b65372SJed Brown 325e7754af5SKenneth E. Jansen if (context->idl_enable) { 326*94a7b3d2SKenneth E. Jansen const CeedScalar sigma = jac_data[14 * Q + i]; 327e7754af5SKenneth E. Jansen CeedScalar damp_state[5] = {ds.Y.pressure, 0, 0, 0, 0}, idl_residual[5] = {0.}; 328e7754af5SKenneth E. Jansen // This is a Picard-type linearization of the damping and could be replaced by an InternalDampingLayer_fwd that uses s and ds. 329*94a7b3d2SKenneth E. Jansen InternalDampingLayer(context, s, sigma, damp_state, idl_residual); 330e7754af5SKenneth E. Jansen for (int j = 0; j < 5; j++) v[j][i] += wdetJ * idl_residual[j]; 331e7754af5SKenneth E. Jansen } 332e7754af5SKenneth E. Jansen 333d1b9ef12SLeila Ghaffari // -- Stabilization method: none (Galerkin), SU, or SUPG 334d1b9ef12SLeila Ghaffari CeedScalar dstab[5][3], U_dot[5] = {0}; 335d1b9ef12SLeila Ghaffari for (CeedInt j = 0; j < 5; j++) U_dot[j] = context->ijacobian_time_shift * dU[j]; 336edcfef1bSKenneth E. Jansen Stabilization(context, s, Tau_d, grad_ds, U_dot, dbody_force, dstab); 337d1b9ef12SLeila Ghaffari 3382b916ea7SJeremy L Thompson for (int j = 0; j < 5; j++) { 3392b916ea7SJeremy 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]); 3402b916ea7SJeremy L Thompson } 341f0b65372SJed Brown } // End Quadrature Point Loop 342f0b65372SJed Brown return 0; 343f0b65372SJed Brown } 3448085925cSJames Wright 3452b916ea7SJeremy L Thompson CEED_QFUNCTION(IJacobian_Newtonian_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 3468fff8293SJames Wright return IJacobian_Newtonian(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 34776555becSJames Wright } 34876555becSJames Wright 3492b916ea7SJeremy L Thompson CEED_QFUNCTION(IJacobian_Newtonian_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 3508fff8293SJames Wright return IJacobian_Newtonian(ctx, Q, in, out, STATEVAR_PRIMITIVE); 35176555becSJames Wright } 35276555becSJames Wright 353d1b9ef12SLeila Ghaffari // ***************************************************************************** 3548085925cSJames Wright // Compute boundary integral (ie. for strongly set inflows) 355d1b9ef12SLeila Ghaffari // ***************************************************************************** 3568fff8293SJames Wright CEED_QFUNCTION_HELPER int BoundaryIntegral(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateVariable state_var) { 3573d65b166SJames Wright const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 35887bd45e7SJames Wright const CeedScalar(*Grad_q) = in[1]; 359ade49511SJames Wright const CeedScalar(*q_data_sur) = in[2]; 3608085925cSJames Wright 3613d65b166SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 362ade49511SJames Wright CeedScalar(*jac_data_sur) = out[1]; 3638085925cSJames Wright 364d3b25f3aSJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 365d3b25f3aSJames Wright const bool is_implicit = context->is_implicit; 3668085925cSJames Wright 3672b916ea7SJeremy L Thompson CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 36841e73928SJames Wright const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 369edcfef1bSKenneth E. Jansen State s = StateFromQ(context, qi, state_var); 3708085925cSJames Wright 371ade49511SJames Wright CeedScalar wdetJb, dXdx[2][3], norm[3]; 372ade49511SJames Wright QdataBoundaryUnpack_3D(Q, i, q_data_sur, &wdetJb, dXdx, norm); 373ade49511SJames Wright wdetJb *= is_implicit ? -1. : 1.; 3748085925cSJames Wright 375d3b25f3aSJames Wright State grad_s[3]; 376edcfef1bSKenneth E. Jansen StatePhysicalGradientFromReference_Boundary(Q, i, context, s, state_var, Grad_q, dXdx, grad_s); 3778085925cSJames Wright 378d3b25f3aSJames Wright CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 37940a33f2dSJames Wright KMStrainRate_State(grad_s, strain_rate); 380d3b25f3aSJames Wright NewtonianStress(context, strain_rate, kmstress); 381d3b25f3aSJames Wright KMUnpack(kmstress, stress); 382d3b25f3aSJames Wright ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 383d3b25f3aSJames Wright 384d3b25f3aSJames Wright StateConservative F_inviscid[3]; 385d3b25f3aSJames Wright FluxInviscid(context, s, F_inviscid); 386d3b25f3aSJames Wright 387c5740391SJames Wright CeedScalar Flux[5]; 388c5740391SJames Wright FluxTotal_Boundary(F_inviscid, stress, Fe, norm, Flux); 389d3b25f3aSJames Wright 390c5740391SJames Wright for (CeedInt j = 0; j < 5; j++) v[j][i] = -wdetJb * Flux[j]; 3918085925cSJames Wright 392ade49511SJames Wright StoredValuesPack(Q, i, 0, 5, qi, jac_data_sur); 393ade49511SJames Wright StoredValuesPack(Q, i, 5, 6, kmstress, jac_data_sur); 3948085925cSJames Wright } 3958085925cSJames Wright return 0; 3968085925cSJames Wright } 3978085925cSJames Wright 3982b916ea7SJeremy L Thompson CEED_QFUNCTION(BoundaryIntegral_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 3998fff8293SJames Wright return BoundaryIntegral(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 400d4559bbeSJames Wright } 401d4559bbeSJames Wright 4022b916ea7SJeremy L Thompson CEED_QFUNCTION(BoundaryIntegral_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 4038fff8293SJames Wright return BoundaryIntegral(ctx, Q, in, out, STATEVAR_PRIMITIVE); 404d4559bbeSJames Wright } 405d4559bbeSJames Wright 406d1b9ef12SLeila Ghaffari // ***************************************************************************** 40768ae065aSJames Wright // Jacobian for "set nothing" boundary integral 408d1b9ef12SLeila Ghaffari // ***************************************************************************** 4092b916ea7SJeremy L Thompson CEED_QFUNCTION_HELPER int BoundaryIntegral_Jacobian(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, 4108fff8293SJames Wright StateVariable state_var) { 41168ae065aSJames Wright // Inputs 4123d65b166SJames Wright const CeedScalar(*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 41387bd45e7SJames Wright const CeedScalar(*Grad_dq) = in[1]; 414ade49511SJames Wright const CeedScalar(*q_data_sur) = in[2]; 415c1484fadSKenneth E. Jansen const CeedScalar(*jac_data_sur) = in[4]; 4163d65b166SJames Wright 41768ae065aSJames Wright // Outputs 41868ae065aSJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 41968ae065aSJames Wright 42068ae065aSJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 421ade49511SJames Wright const bool is_implicit = context->is_implicit; 42268ae065aSJames Wright 42368ae065aSJames Wright // Quadrature Point Loop 4243d65b166SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 425ade49511SJames Wright CeedScalar wdetJb, dXdx[2][3], norm[3]; 426ade49511SJames Wright QdataBoundaryUnpack_3D(Q, i, q_data_sur, &wdetJb, dXdx, norm); 427ade49511SJames Wright wdetJb *= is_implicit ? -1. : 1.; 42868ae065aSJames Wright 429edcfef1bSKenneth E. Jansen CeedScalar qi[5], kmstress[6], dqi[5]; 430ade49511SJames Wright StoredValuesUnpack(Q, i, 0, 5, jac_data_sur, qi); 431ade49511SJames Wright StoredValuesUnpack(Q, i, 5, 6, jac_data_sur, kmstress); 43241e73928SJames Wright for (int j = 0; j < 5; j++) dqi[j] = dq[j][i]; 4333934e2b1SJames Wright 434edcfef1bSKenneth E. Jansen State s = StateFromQ(context, qi, state_var); 435edcfef1bSKenneth E. Jansen State ds = StateFromQ_fwd(context, s, dqi, state_var); 43668ae065aSJames Wright 43768ae065aSJames Wright State grad_ds[3]; 438edcfef1bSKenneth E. Jansen StatePhysicalGradientFromReference_Boundary(Q, i, context, s, state_var, Grad_dq, dXdx, grad_ds); 43968ae065aSJames Wright 44068ae065aSJames Wright CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 44140a33f2dSJames Wright KMStrainRate_State(grad_ds, dstrain_rate); 44268ae065aSJames Wright NewtonianStress(context, dstrain_rate, dkmstress); 44368ae065aSJames Wright KMUnpack(dkmstress, dstress); 44468ae065aSJames Wright KMUnpack(kmstress, stress); 44568ae065aSJames Wright ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 44668ae065aSJames Wright 44768ae065aSJames Wright StateConservative dF_inviscid[3]; 44868ae065aSJames Wright FluxInviscid_fwd(context, s, ds, dF_inviscid); 44968ae065aSJames Wright 450c5740391SJames Wright CeedScalar dFlux[5]; 451c5740391SJames Wright FluxTotal_Boundary(dF_inviscid, dstress, dFe, norm, dFlux); 45268ae065aSJames Wright 453c5740391SJames Wright for (int j = 0; j < 5; j++) v[j][i] = -wdetJb * dFlux[j]; 45468ae065aSJames Wright } // End Quadrature Point Loop 45568ae065aSJames Wright return 0; 45668ae065aSJames Wright } 45768ae065aSJames Wright 4582b916ea7SJeremy L Thompson CEED_QFUNCTION(BoundaryIntegral_Jacobian_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 4598fff8293SJames Wright return BoundaryIntegral_Jacobian(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 460d4559bbeSJames Wright } 461d4559bbeSJames Wright 4622b916ea7SJeremy L Thompson CEED_QFUNCTION(BoundaryIntegral_Jacobian_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 4638fff8293SJames Wright return BoundaryIntegral_Jacobian(ctx, Q, in, out, STATEVAR_PRIMITIVE); 464d4559bbeSJames Wright } 465d4559bbeSJames Wright 4663a8779fbSJames Wright #endif // newtonian_h 467