1*5aed82e4SJeremy 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 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 231d2a9659SKenneth E. Jansen CEED_QFUNCTION_HELPER void InternalDampingLayer(const NewtonianIdealGasContext context, const State s, const CeedScalar sigma, CeedScalar damp_Y[5], 24530ad8c4SKenneth E. Jansen CeedScalar damp_residual[5]) { 25530ad8c4SKenneth E. Jansen ScaleN(damp_Y, sigma, 5); 263bd61617SKenneth E. Jansen State damp_s = StateFromY_fwd(context, s, damp_Y); 27530ad8c4SKenneth E. Jansen 28530ad8c4SKenneth E. Jansen CeedScalar U[5]; 29530ad8c4SKenneth E. Jansen UnpackState_U(damp_s.U, U); 30530ad8c4SKenneth E. Jansen for (int i = 0; i < 5; i++) damp_residual[i] += U[i]; 31530ad8c4SKenneth E. Jansen } 32530ad8c4SKenneth E. Jansen 3388626eedSJames Wright // ***************************************************************************** 3488b783a1SJames Wright // This QFunction sets a "still" initial condition for generic Newtonian IG problems 3588b783a1SJames Wright // ***************************************************************************** 36be91e165SJames Wright CEED_QFUNCTION_HELPER int ICsNewtonianIG(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateVariable state_var) { 3788b783a1SJames Wright // Inputs 3888b783a1SJames Wright 3988b783a1SJames Wright // Outputs 4088b783a1SJames Wright CeedScalar(*q0)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 4188b783a1SJames Wright 4288626eedSJames Wright // Context 4388626eedSJames Wright const SetupContext context = (SetupContext)ctx; 4488626eedSJames Wright 4588b783a1SJames Wright // Quadrature Point Loop 462b730f8bSJeremy L Thompson CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 4788b783a1SJames Wright CeedScalar q[5] = {0.}; 483bd61617SKenneth E. Jansen State s = StateFromPrimitive(&context->gas, context->reference); 49be91e165SJames Wright StateToQ(&context->gas, s, q, state_var); 502b730f8bSJeremy L Thompson for (CeedInt j = 0; j < 5; j++) q0[j][i] = q[j]; 5188b783a1SJames Wright } // End of Quadrature Point Loop 5288b783a1SJames Wright return 0; 5388b783a1SJames Wright } 5488b783a1SJames Wright 552b730f8bSJeremy L Thompson CEED_QFUNCTION(ICsNewtonianIG_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 56be91e165SJames Wright return ICsNewtonianIG(ctx, Q, in, out, STATEVAR_PRIMITIVE); 57d310b3d3SAdeleke O. Bankole } 58d310b3d3SAdeleke O. Bankole CEED_QFUNCTION(ICsNewtonianIG_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 59be91e165SJames Wright return ICsNewtonianIG(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 60dc805cc4SLeila Ghaffari } 61dc805cc4SLeila Ghaffari 62dc805cc4SLeila Ghaffari // ***************************************************************************** 63ea61e9acSJeremy L Thompson // This QFunction implements the following formulation of Navier-Stokes with explicit time stepping method 6488b783a1SJames Wright // 65ea61e9acSJeremy L Thompson // This is 3D compressible Navier-Stokes in conservation form with state variables of density, momentum density, and total energy density. 6688b783a1SJames Wright // 6788b783a1SJames Wright // State Variables: q = ( rho, U1, U2, U3, E ) 6888b783a1SJames Wright // rho - Mass Density 6988b783a1SJames Wright // Ui - Momentum Density, Ui = rho ui 7088b783a1SJames Wright // E - Total Energy Density, E = rho (cv T + (u u)/2 + g z) 7188b783a1SJames Wright // 7288b783a1SJames Wright // Navier-Stokes Equations: 7388b783a1SJames Wright // drho/dt + div( U ) = 0 7488b783a1SJames Wright // dU/dt + div( rho (u x u) + P I3 ) + rho g khat = div( Fu ) 7588b783a1SJames Wright // dE/dt + div( (E + P) u ) = div( Fe ) 7688b783a1SJames Wright // 7788b783a1SJames Wright // Viscous Stress: 7888b783a1SJames Wright // Fu = mu (grad( u ) + grad( u )^T + lambda div ( u ) I3) 7988b783a1SJames Wright // 8088b783a1SJames Wright // Thermal Stress: 8188b783a1SJames Wright // Fe = u Fu + k grad( T ) 8288626eedSJames Wright // Equation of State 8388b783a1SJames Wright // P = (gamma - 1) (E - rho (u u) / 2 - rho g z) 8488b783a1SJames Wright // 8588b783a1SJames Wright // Stabilization: 8688b783a1SJames Wright // Tau = diag(TauC, TauM, TauM, TauM, TauE) 8788b783a1SJames Wright // f1 = rho sqrt(ui uj gij) 8888b783a1SJames Wright // gij = dXi/dX * dXi/dX 8988b783a1SJames Wright // TauC = Cc f1 / (8 gii) 9088b783a1SJames Wright // TauM = min( 1 , 1 / f1 ) 9188b783a1SJames Wright // TauE = TauM / (Ce cv) 9288b783a1SJames Wright // 9388b783a1SJames Wright // SU = Galerkin + grad(v) . ( Ai^T * Tau * (Aj q,j) ) 9488b783a1SJames Wright // 9588b783a1SJames Wright // Constants: 9688b783a1SJames Wright // lambda = - 2 / 3, From Stokes hypothesis 9788b783a1SJames Wright // mu , Dynamic viscosity 9888b783a1SJames Wright // k , Thermal conductivity 9988b783a1SJames Wright // cv , Specific heat, constant volume 10088b783a1SJames Wright // cp , Specific heat, constant pressure 10188b783a1SJames Wright // g , Gravity 10288b783a1SJames Wright // gamma = cp / cv, Specific heat ratio 10388b783a1SJames Wright // 104ea61e9acSJeremy 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 105ea61e9acSJeremy L Thompson // gradu ) 10688b783a1SJames Wright // ***************************************************************************** 1072b730f8bSJeremy L Thompson CEED_QFUNCTION(RHSFunction_Newtonian)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 10888b783a1SJames Wright // Inputs 10946603fc5SJames Wright const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 1109b6a821dSJames Wright const CeedScalar(*Grad_q) = in[1]; 111f3e15844SJames Wright const CeedScalar(*q_data) = in[2]; 11246603fc5SJames Wright 11388b783a1SJames Wright // Outputs 11446603fc5SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 11546603fc5SJames Wright CeedScalar(*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 11688b783a1SJames Wright 11788b783a1SJames Wright // Context 11888b783a1SJames Wright NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 11988626eedSJames Wright const CeedScalar *g = context->g; 12088626eedSJames Wright const CeedScalar dt = context->dt; 12188b783a1SJames Wright 12288b783a1SJames Wright // Quadrature Point Loop 12346603fc5SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 124f3e15844SJames Wright CeedScalar U[5], wdetJ, dXdx[3][3]; 1255c677226SJed Brown for (int j = 0; j < 5; j++) U[j] = q[j][i]; 126f3e15844SJames Wright StoredValuesUnpack(Q, i, 0, 1, q_data, &wdetJ); 127f3e15844SJames Wright StoredValuesUnpack(Q, i, 1, 9, q_data, (CeedScalar *)dXdx); 1283bd61617SKenneth E. Jansen State s = StateFromU(context, U); 1295c677226SJed Brown 1305c677226SJed Brown State grad_s[3]; 1313bd61617SKenneth E. Jansen StatePhysicalGradientFromReference(Q, i, context, s, STATEVAR_CONSERVATIVE, Grad_q, dXdx, grad_s); 1325c677226SJed Brown 1335c677226SJed Brown CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 134d08fcc28SJames Wright KMStrainRate_State(grad_s, strain_rate); 1355c677226SJed Brown NewtonianStress(context, strain_rate, kmstress); 1365c677226SJed Brown KMUnpack(kmstress, stress); 1375c677226SJed Brown ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 1385c677226SJed Brown 1395c677226SJed Brown StateConservative F_inviscid[3]; 1405c677226SJed Brown FluxInviscid(context, s, F_inviscid); 1415c677226SJed Brown 1425c677226SJed Brown // Total flux 1435c677226SJed Brown CeedScalar Flux[5][3]; 1442b89d87eSLeila Ghaffari FluxTotal(F_inviscid, stress, Fe, Flux); 1455c677226SJed Brown 1467b69c783SJames Wright for (CeedInt j = 0; j < 5; j++) { 1477b69c783SJames 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]); 1482b730f8bSJeremy L Thompson } 1495c677226SJed Brown 150858ec087SKenneth 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)}; 1512b730f8bSJeremy L Thompson for (int j = 0; j < 5; j++) v[j][i] = wdetJ * body_force[j]; 15288b783a1SJames Wright 1532b89d87eSLeila Ghaffari // -- Stabilization method: none (Galerkin), SU, or SUPG 1542b89d87eSLeila Ghaffari CeedScalar Tau_d[3], stab[5][3], U_dot[5] = {0}; 1552b89d87eSLeila Ghaffari Tau_diagPrim(context, s, dXdx, dt, Tau_d); 1563bd61617SKenneth E. Jansen Stabilization(context, s, Tau_d, grad_s, U_dot, body_force, stab); 15788b783a1SJames Wright 1582b730f8bSJeremy L Thompson for (CeedInt j = 0; j < 5; j++) { 1592b730f8bSJeremy 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]); 1602b730f8bSJeremy L Thompson } 16188b783a1SJames Wright } // End Quadrature Point Loop 16288b783a1SJames Wright 16388b783a1SJames Wright // Return 16488b783a1SJames Wright return 0; 16588b783a1SJames Wright } 16688b783a1SJames Wright 16788b783a1SJames Wright // ***************************************************************************** 168ea61e9acSJeremy L Thompson // This QFunction implements the Navier-Stokes equations (mentioned above) with implicit time stepping method 16988b783a1SJames Wright // 17088b783a1SJames Wright // SU = Galerkin + grad(v) . ( Ai^T * Tau * (Aj q,j) ) 17188b783a1SJames Wright // SUPG = Galerkin + grad(v) . ( Ai^T * Tau * (q_dot + Aj q,j - body force) ) 172ea61e9acSJeremy L Thompson // (diffusive terms will be added later) 17388b783a1SJames Wright // ***************************************************************************** 174be91e165SJames Wright CEED_QFUNCTION_HELPER int IFunction_Newtonian(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateVariable state_var) { 17588b783a1SJames Wright // Inputs 17646603fc5SJames Wright const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 1779b6a821dSJames Wright const CeedScalar(*Grad_q) = in[1]; 17846603fc5SJames Wright const CeedScalar(*q_dot)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2]; 179f3e15844SJames Wright const CeedScalar(*q_data) = in[3]; 18046603fc5SJames Wright const CeedScalar(*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 18146603fc5SJames Wright 18288b783a1SJames Wright // Outputs 18346603fc5SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 18446603fc5SJames Wright CeedScalar(*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 185f3e15844SJames Wright CeedScalar(*jac_data) = out[2]; 18646603fc5SJames Wright 18788b783a1SJames Wright // Context 18888b783a1SJames Wright NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 18988626eedSJames Wright const CeedScalar *g = context->g; 19088626eedSJames Wright const CeedScalar dt = context->dt; 191530ad8c4SKenneth E. Jansen const CeedScalar P0 = context->P0; 19288b783a1SJames Wright 19388b783a1SJames Wright // Quadrature Point Loop 19446603fc5SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 19546603fc5SJames Wright const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 1965c677226SJed Brown const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 1973bd61617SKenneth E. Jansen const State s = StateFromQ(context, qi, state_var); 1985c677226SJed Brown 199f3e15844SJames Wright CeedScalar wdetJ, dXdx[3][3]; 200f3e15844SJames Wright QdataUnpack_3D(Q, i, q_data, &wdetJ, dXdx); 2015c677226SJed Brown State grad_s[3]; 2023bd61617SKenneth E. Jansen StatePhysicalGradientFromReference(Q, i, context, s, state_var, Grad_q, dXdx, grad_s); 2035c677226SJed Brown 2045c677226SJed Brown CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 205d08fcc28SJames Wright KMStrainRate_State(grad_s, strain_rate); 2065c677226SJed Brown NewtonianStress(context, strain_rate, kmstress); 2075c677226SJed Brown KMUnpack(kmstress, stress); 2085c677226SJed Brown ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 2095c677226SJed Brown 2105c677226SJed Brown StateConservative F_inviscid[3]; 2115c677226SJed Brown FluxInviscid(context, s, F_inviscid); 2125c677226SJed Brown 2135c677226SJed Brown // Total flux 2145c677226SJed Brown CeedScalar Flux[5][3]; 2152b89d87eSLeila Ghaffari FluxTotal(F_inviscid, stress, Fe, Flux); 2165c677226SJed Brown 2177b69c783SJames Wright for (CeedInt j = 0; j < 5; j++) { 2187b69c783SJames Wright for (CeedInt k = 0; k < 3; k++) { 2197b69c783SJames 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]); 22046603fc5SJames Wright } 2212b730f8bSJeremy L Thompson } 2225c677226SJed Brown 223858ec087SKenneth 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)}; 22488b783a1SJames Wright 2252b89d87eSLeila Ghaffari // -- Stabilization method: none (Galerkin), SU, or SUPG 2263bd61617SKenneth E. Jansen CeedScalar Tau_d[3], stab[5][3], U_dot[5] = {0}, qi_dot[5]; 2273d02368aSJames Wright for (int j = 0; j < 5; j++) qi_dot[j] = q_dot[j][i]; 2283bd61617SKenneth E. Jansen State s_dot = StateFromQ_fwd(context, s, qi_dot, state_var); 2293d02368aSJames Wright UnpackState_U(s_dot.U, U_dot); 2303d02368aSJames Wright 2312b730f8bSJeremy L Thompson for (CeedInt j = 0; j < 5; j++) v[j][i] = wdetJ * (U_dot[j] - body_force[j]); 232530ad8c4SKenneth E. Jansen if (context->idl_enable) { 2331d2a9659SKenneth E. Jansen const CeedScalar sigma = LinearRampCoefficient(context->idl_amplitude, context->idl_length, context->idl_start, x_i[0]); 2341d2a9659SKenneth E. Jansen StoredValuesPack(Q, i, 14, 1, &sigma, jac_data); 235530ad8c4SKenneth E. Jansen CeedScalar damp_state[5] = {s.Y.pressure - P0, 0, 0, 0, 0}, idl_residual[5] = {0.}; 2361d2a9659SKenneth E. Jansen InternalDampingLayer(context, s, sigma, damp_state, idl_residual); 237530ad8c4SKenneth E. Jansen for (int j = 0; j < 5; j++) v[j][i] += wdetJ * idl_residual[j]; 238530ad8c4SKenneth E. Jansen } 239530ad8c4SKenneth E. Jansen 2402b89d87eSLeila Ghaffari Tau_diagPrim(context, s, dXdx, dt, Tau_d); 2413bd61617SKenneth E. Jansen Stabilization(context, s, Tau_d, grad_s, U_dot, body_force, stab); 24288b783a1SJames Wright 2432b730f8bSJeremy L Thompson for (CeedInt j = 0; j < 5; j++) { 24446603fc5SJames Wright for (CeedInt k = 0; k < 3; k++) { 24546603fc5SJames 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]); 24646603fc5SJames Wright } 2472b730f8bSJeremy L Thompson } 248f3e15844SJames Wright StoredValuesPack(Q, i, 0, 5, qi, jac_data); 249f3e15844SJames Wright StoredValuesPack(Q, i, 5, 6, kmstress, jac_data); 250f3e15844SJames Wright StoredValuesPack(Q, i, 11, 3, Tau_d, jac_data); 25188b783a1SJames Wright 25288b783a1SJames Wright } // End Quadrature Point Loop 25388b783a1SJames Wright 25488b783a1SJames Wright // Return 25588b783a1SJames Wright return 0; 25688b783a1SJames Wright } 257e334ad8fSJed Brown 2582b730f8bSJeremy L Thompson CEED_QFUNCTION(IFunction_Newtonian_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 259be91e165SJames Wright return IFunction_Newtonian(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 2603d02368aSJames Wright } 2613d02368aSJames Wright 2622b730f8bSJeremy L Thompson CEED_QFUNCTION(IFunction_Newtonian_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 263be91e165SJames Wright return IFunction_Newtonian(ctx, Q, in, out, STATEVAR_PRIMITIVE); 2643d02368aSJames Wright } 2653d02368aSJames Wright 266dc805cc4SLeila Ghaffari // ***************************************************************************** 267ea61e9acSJeremy L Thompson // This QFunction implements the jacobian of the Navier-Stokes equations for implicit time stepping method. 268dc805cc4SLeila Ghaffari // ***************************************************************************** 269be91e165SJames Wright CEED_QFUNCTION_HELPER int IJacobian_Newtonian(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateVariable state_var) { 270e334ad8fSJed Brown // Inputs 27146603fc5SJames Wright const CeedScalar(*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 2729b6a821dSJames Wright const CeedScalar(*Grad_dq) = in[1]; 273f3e15844SJames Wright const CeedScalar(*q_data) = in[2]; 2741d2a9659SKenneth E. Jansen const CeedScalar(*jac_data) = in[3]; 27546603fc5SJames Wright 276e334ad8fSJed Brown // Outputs 27746603fc5SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 27846603fc5SJames Wright CeedScalar(*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 27946603fc5SJames Wright 280e334ad8fSJed Brown // Context 281e334ad8fSJed Brown NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 282e334ad8fSJed Brown const CeedScalar *g = context->g; 283e334ad8fSJed Brown 284e334ad8fSJed Brown // Quadrature Point Loop 28546603fc5SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 286f3e15844SJames Wright CeedScalar wdetJ, dXdx[3][3]; 287f3e15844SJames Wright QdataUnpack_3D(Q, i, q_data, &wdetJ, dXdx); 288e334ad8fSJed Brown 289c98a0616SJames Wright CeedScalar qi[5], kmstress[6], Tau_d[3]; 290f3e15844SJames Wright StoredValuesUnpack(Q, i, 0, 5, jac_data, qi); 291f3e15844SJames Wright StoredValuesUnpack(Q, i, 5, 6, jac_data, kmstress); 292f3e15844SJames Wright StoredValuesUnpack(Q, i, 11, 3, jac_data, Tau_d); 2933bd61617SKenneth E. Jansen State s = StateFromQ(context, qi, state_var); 294e334ad8fSJed Brown 2953bd61617SKenneth E. Jansen CeedScalar dqi[5]; 2963d02368aSJames Wright for (int j = 0; j < 5; j++) dqi[j] = dq[j][i]; 2973bd61617SKenneth E. Jansen State ds = StateFromQ_fwd(context, s, dqi, state_var); 298e334ad8fSJed Brown 299e334ad8fSJed Brown State grad_ds[3]; 3003bd61617SKenneth E. Jansen StatePhysicalGradientFromReference(Q, i, context, s, state_var, Grad_dq, dXdx, grad_ds); 301e334ad8fSJed Brown 302e334ad8fSJed Brown CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 303d08fcc28SJames Wright KMStrainRate_State(grad_ds, dstrain_rate); 304e334ad8fSJed Brown NewtonianStress(context, dstrain_rate, dkmstress); 305e334ad8fSJed Brown KMUnpack(dkmstress, dstress); 306e334ad8fSJed Brown KMUnpack(kmstress, stress); 307e334ad8fSJed Brown ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 308e334ad8fSJed Brown 309e334ad8fSJed Brown StateConservative dF_inviscid[3]; 310e334ad8fSJed Brown FluxInviscid_fwd(context, s, ds, dF_inviscid); 311e334ad8fSJed Brown 312e334ad8fSJed Brown // Total flux 313e334ad8fSJed Brown CeedScalar dFlux[5][3]; 3142b89d87eSLeila Ghaffari FluxTotal(dF_inviscid, dstress, dFe, dFlux); 315e334ad8fSJed Brown 31651b00d91SJames Wright for (int j = 0; j < 5; j++) { 31751b00d91SJames 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]); 3182b730f8bSJeremy L Thompson } 319e334ad8fSJed Brown 320858ec087SKenneth 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)}; 3213d02368aSJames Wright CeedScalar dU[5] = {0.}; 3223d02368aSJames Wright UnpackState_U(ds.U, dU); 3232b730f8bSJeremy L Thompson for (int j = 0; j < 5; j++) v[j][i] = wdetJ * (context->ijacobian_time_shift * dU[j] - dbody_force[j]); 324e334ad8fSJed Brown 325530ad8c4SKenneth E. Jansen if (context->idl_enable) { 3261d2a9659SKenneth E. Jansen const CeedScalar sigma = jac_data[14 * Q + i]; 327530ad8c4SKenneth E. Jansen CeedScalar damp_state[5] = {ds.Y.pressure, 0, 0, 0, 0}, idl_residual[5] = {0.}; 328530ad8c4SKenneth E. Jansen // This is a Picard-type linearization of the damping and could be replaced by an InternalDampingLayer_fwd that uses s and ds. 3291d2a9659SKenneth E. Jansen InternalDampingLayer(context, s, sigma, damp_state, idl_residual); 330530ad8c4SKenneth E. Jansen for (int j = 0; j < 5; j++) v[j][i] += wdetJ * idl_residual[j]; 331530ad8c4SKenneth E. Jansen } 332530ad8c4SKenneth E. Jansen 3332b89d87eSLeila Ghaffari // -- Stabilization method: none (Galerkin), SU, or SUPG 3342b89d87eSLeila Ghaffari CeedScalar dstab[5][3], U_dot[5] = {0}; 3352b89d87eSLeila Ghaffari for (CeedInt j = 0; j < 5; j++) U_dot[j] = context->ijacobian_time_shift * dU[j]; 3363bd61617SKenneth E. Jansen Stabilization(context, s, Tau_d, grad_ds, U_dot, dbody_force, dstab); 3372b89d87eSLeila Ghaffari 3382b730f8bSJeremy L Thompson for (int j = 0; j < 5; j++) { 3392b730f8bSJeremy 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]); 3402b730f8bSJeremy L Thompson } 341e334ad8fSJed Brown } // End Quadrature Point Loop 342e334ad8fSJed Brown return 0; 343e334ad8fSJed Brown } 34465dd5cafSJames Wright 3452b730f8bSJeremy L Thompson CEED_QFUNCTION(IJacobian_Newtonian_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 346be91e165SJames Wright return IJacobian_Newtonian(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 3473d02368aSJames Wright } 3483d02368aSJames Wright 3492b730f8bSJeremy L Thompson CEED_QFUNCTION(IJacobian_Newtonian_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 350be91e165SJames Wright return IJacobian_Newtonian(ctx, Q, in, out, STATEVAR_PRIMITIVE); 3513d02368aSJames Wright } 3523d02368aSJames Wright 3532b89d87eSLeila Ghaffari // ***************************************************************************** 35465dd5cafSJames Wright // Compute boundary integral (ie. for strongly set inflows) 3552b89d87eSLeila Ghaffari // ***************************************************************************** 356be91e165SJames Wright CEED_QFUNCTION_HELPER int BoundaryIntegral(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateVariable state_var) { 35746603fc5SJames Wright const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 3589b6a821dSJames Wright const CeedScalar(*Grad_q) = in[1]; 359f3e15844SJames Wright const CeedScalar(*q_data_sur) = in[2]; 36065dd5cafSJames Wright 36146603fc5SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 362f3e15844SJames Wright CeedScalar(*jac_data_sur) = out[1]; 36365dd5cafSJames Wright 3642c4e60d7SJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 3652c4e60d7SJames Wright const bool is_implicit = context->is_implicit; 36665dd5cafSJames Wright 3672b730f8bSJeremy L Thompson CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 368efe9d856SJames Wright const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 3693bd61617SKenneth E. Jansen State s = StateFromQ(context, qi, state_var); 37065dd5cafSJames Wright 371f3e15844SJames Wright CeedScalar wdetJb, dXdx[2][3], norm[3]; 372f3e15844SJames Wright QdataBoundaryUnpack_3D(Q, i, q_data_sur, &wdetJb, dXdx, norm); 373f3e15844SJames Wright wdetJb *= is_implicit ? -1. : 1.; 37465dd5cafSJames Wright 3752c4e60d7SJames Wright State grad_s[3]; 3763bd61617SKenneth E. Jansen StatePhysicalGradientFromReference_Boundary(Q, i, context, s, state_var, Grad_q, dXdx, grad_s); 37765dd5cafSJames Wright 3782c4e60d7SJames Wright CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 379d08fcc28SJames Wright KMStrainRate_State(grad_s, strain_rate); 3802c4e60d7SJames Wright NewtonianStress(context, strain_rate, kmstress); 3812c4e60d7SJames Wright KMUnpack(kmstress, stress); 3822c4e60d7SJames Wright ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 3832c4e60d7SJames Wright 3842c4e60d7SJames Wright StateConservative F_inviscid[3]; 3852c4e60d7SJames Wright FluxInviscid(context, s, F_inviscid); 3862c4e60d7SJames Wright 3875bce47c7SJames Wright CeedScalar Flux[5]; 3885bce47c7SJames Wright FluxTotal_Boundary(F_inviscid, stress, Fe, norm, Flux); 3892c4e60d7SJames Wright 3905bce47c7SJames Wright for (CeedInt j = 0; j < 5; j++) v[j][i] = -wdetJb * Flux[j]; 39165dd5cafSJames Wright 392f3e15844SJames Wright StoredValuesPack(Q, i, 0, 5, qi, jac_data_sur); 393f3e15844SJames Wright StoredValuesPack(Q, i, 5, 6, kmstress, jac_data_sur); 39465dd5cafSJames Wright } 39565dd5cafSJames Wright return 0; 39665dd5cafSJames Wright } 39765dd5cafSJames Wright 3982b730f8bSJeremy L Thompson CEED_QFUNCTION(BoundaryIntegral_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 399be91e165SJames Wright return BoundaryIntegral(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 40020840d50SJames Wright } 40120840d50SJames Wright 4022b730f8bSJeremy L Thompson CEED_QFUNCTION(BoundaryIntegral_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 403be91e165SJames Wright return BoundaryIntegral(ctx, Q, in, out, STATEVAR_PRIMITIVE); 40420840d50SJames Wright } 40520840d50SJames Wright 4062b89d87eSLeila Ghaffari // ***************************************************************************** 407b55ac660SJames Wright // Jacobian for "set nothing" boundary integral 4082b89d87eSLeila Ghaffari // ***************************************************************************** 4092b730f8bSJeremy L Thompson CEED_QFUNCTION_HELPER int BoundaryIntegral_Jacobian(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, 410be91e165SJames Wright StateVariable state_var) { 411b55ac660SJames Wright // Inputs 41246603fc5SJames Wright const CeedScalar(*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 4139b6a821dSJames Wright const CeedScalar(*Grad_dq) = in[1]; 414f3e15844SJames Wright const CeedScalar(*q_data_sur) = in[2]; 415c1d93bc4SKenneth E. Jansen const CeedScalar(*jac_data_sur) = in[4]; 41646603fc5SJames Wright 417b55ac660SJames Wright // Outputs 418b55ac660SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 419b55ac660SJames Wright 420b55ac660SJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 421f3e15844SJames Wright const bool is_implicit = context->is_implicit; 422b55ac660SJames Wright 423b55ac660SJames Wright // Quadrature Point Loop 42446603fc5SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 425f3e15844SJames Wright CeedScalar wdetJb, dXdx[2][3], norm[3]; 426f3e15844SJames Wright QdataBoundaryUnpack_3D(Q, i, q_data_sur, &wdetJb, dXdx, norm); 427f3e15844SJames Wright wdetJb *= is_implicit ? -1. : 1.; 428b55ac660SJames Wright 4293bd61617SKenneth E. Jansen CeedScalar qi[5], kmstress[6], dqi[5]; 430f3e15844SJames Wright StoredValuesUnpack(Q, i, 0, 5, jac_data_sur, qi); 431f3e15844SJames Wright StoredValuesUnpack(Q, i, 5, 6, jac_data_sur, kmstress); 432efe9d856SJames Wright for (int j = 0; j < 5; j++) dqi[j] = dq[j][i]; 43357e55a1cSJames Wright 4343bd61617SKenneth E. Jansen State s = StateFromQ(context, qi, state_var); 4353bd61617SKenneth E. Jansen State ds = StateFromQ_fwd(context, s, dqi, state_var); 436b55ac660SJames Wright 437b55ac660SJames Wright State grad_ds[3]; 4383bd61617SKenneth E. Jansen StatePhysicalGradientFromReference_Boundary(Q, i, context, s, state_var, Grad_dq, dXdx, grad_ds); 439b55ac660SJames Wright 440b55ac660SJames Wright CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 441d08fcc28SJames Wright KMStrainRate_State(grad_ds, dstrain_rate); 442b55ac660SJames Wright NewtonianStress(context, dstrain_rate, dkmstress); 443b55ac660SJames Wright KMUnpack(dkmstress, dstress); 444b55ac660SJames Wright KMUnpack(kmstress, stress); 445b55ac660SJames Wright ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 446b55ac660SJames Wright 447b55ac660SJames Wright StateConservative dF_inviscid[3]; 448b55ac660SJames Wright FluxInviscid_fwd(context, s, ds, dF_inviscid); 449b55ac660SJames Wright 4505bce47c7SJames Wright CeedScalar dFlux[5]; 4515bce47c7SJames Wright FluxTotal_Boundary(dF_inviscid, dstress, dFe, norm, dFlux); 452b55ac660SJames Wright 4535bce47c7SJames Wright for (int j = 0; j < 5; j++) v[j][i] = -wdetJb * dFlux[j]; 454b55ac660SJames Wright } // End Quadrature Point Loop 455b55ac660SJames Wright return 0; 456b55ac660SJames Wright } 457b55ac660SJames Wright 4582b730f8bSJeremy L Thompson CEED_QFUNCTION(BoundaryIntegral_Jacobian_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 459be91e165SJames Wright return BoundaryIntegral_Jacobian(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 46020840d50SJames Wright } 46120840d50SJames Wright 4622b730f8bSJeremy L Thompson CEED_QFUNCTION(BoundaryIntegral_Jacobian_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 463be91e165SJames Wright return BoundaryIntegral_Jacobian(ctx, Q, in, out, STATEVAR_PRIMITIVE); 46420840d50SJames Wright } 46520840d50SJames Wright 46688b783a1SJames Wright #endif // newtonian_h 467