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> 17*2b916ea7SJeremy 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 23bb8a0c61SJames Wright // ***************************************************************************** 243a8779fbSJames Wright // This QFunction sets a "still" initial condition for generic Newtonian IG problems 253a8779fbSJames Wright // ***************************************************************************** 26*2b916ea7SJeremy L Thompson CEED_QFUNCTION(ICsNewtonianIG)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 273a8779fbSJames Wright // Inputs 283a8779fbSJames Wright const CeedScalar(*X)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 293a8779fbSJames Wright 303a8779fbSJames Wright // Outputs 313a8779fbSJames Wright CeedScalar(*q0)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 323a8779fbSJames Wright 33bb8a0c61SJames Wright // Context 34bb8a0c61SJames Wright const SetupContext context = (SetupContext)ctx; 35bb8a0c61SJames Wright const CeedScalar theta0 = context->theta0; 36bb8a0c61SJames Wright const CeedScalar P0 = context->P0; 37bb8a0c61SJames Wright const CeedScalar cv = context->cv; 38bb8a0c61SJames Wright const CeedScalar cp = context->cp; 39bb8a0c61SJames Wright const CeedScalar *g = context->g; 40bb8a0c61SJames Wright const CeedScalar Rd = cp - cv; 41bb8a0c61SJames Wright 423a8779fbSJames Wright // Quadrature Point Loop 43*2b916ea7SJeremy L Thompson CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 443a8779fbSJames Wright CeedScalar q[5] = {0.}; 453a8779fbSJames Wright 463a8779fbSJames Wright // Setup 473a8779fbSJames Wright // -- Coordinates 48bb8a0c61SJames Wright const CeedScalar x[3] = {X[0][i], X[1][i], X[2][i]}; 49d1b9ef12SLeila Ghaffari const CeedScalar e_potential = -Dot3(g, x); 503a8779fbSJames Wright 513a8779fbSJames Wright // -- Density 52bb8a0c61SJames Wright const CeedScalar rho = P0 / (Rd * theta0); 533a8779fbSJames Wright 543a8779fbSJames Wright // Initial Conditions 553a8779fbSJames Wright q[0] = rho; 563a8779fbSJames Wright q[1] = 0.0; 573a8779fbSJames Wright q[2] = 0.0; 583a8779fbSJames Wright q[3] = 0.0; 59bb8a0c61SJames Wright q[4] = rho * (cv * theta0 + e_potential); 603a8779fbSJames Wright 61*2b916ea7SJeremy L Thompson for (CeedInt j = 0; j < 5; j++) q0[j][i] = q[j]; 62d1b9ef12SLeila Ghaffari 633a8779fbSJames Wright } // End of Quadrature Point Loop 643a8779fbSJames Wright return 0; 653a8779fbSJames Wright } 663a8779fbSJames Wright 673a8779fbSJames Wright // ***************************************************************************** 68cbe60e31SLeila Ghaffari // This QFunction sets a "still" initial condition for generic Newtonian IG 69cbe60e31SLeila Ghaffari // problems in primitive variables 70cbe60e31SLeila Ghaffari // ***************************************************************************** 71*2b916ea7SJeremy L Thompson CEED_QFUNCTION(ICsNewtonianIG_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 72cbe60e31SLeila Ghaffari // Outputs 73cbe60e31SLeila Ghaffari CeedScalar(*q0)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 74cbe60e31SLeila Ghaffari 75cbe60e31SLeila Ghaffari // Context 76cbe60e31SLeila Ghaffari const SetupContext context = (SetupContext)ctx; 77cbe60e31SLeila Ghaffari const CeedScalar theta0 = context->theta0; 78cbe60e31SLeila Ghaffari const CeedScalar P0 = context->P0; 79cbe60e31SLeila Ghaffari 80cbe60e31SLeila Ghaffari // Quadrature Point Loop 81*2b916ea7SJeremy L Thompson CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 82cbe60e31SLeila Ghaffari CeedScalar q[5] = {0.}; 83cbe60e31SLeila Ghaffari 84cbe60e31SLeila Ghaffari // Initial Conditions 85cbe60e31SLeila Ghaffari q[0] = P0; 86cbe60e31SLeila Ghaffari q[1] = 0.0; 87cbe60e31SLeila Ghaffari q[2] = 0.0; 88cbe60e31SLeila Ghaffari q[3] = 0.0; 89cbe60e31SLeila Ghaffari q[4] = theta0; 90cbe60e31SLeila Ghaffari 91*2b916ea7SJeremy L Thompson for (CeedInt j = 0; j < 5; j++) q0[j][i] = q[j]; 92cbe60e31SLeila Ghaffari 93cbe60e31SLeila Ghaffari } // End of Quadrature Point Loop 94cbe60e31SLeila Ghaffari return 0; 95cbe60e31SLeila Ghaffari } 96cbe60e31SLeila Ghaffari 97cbe60e31SLeila Ghaffari // ***************************************************************************** 983a8779fbSJames Wright // This QFunction implements the following formulation of Navier-Stokes with 993a8779fbSJames Wright // explicit time stepping method 1003a8779fbSJames Wright // 1013a8779fbSJames Wright // This is 3D compressible Navier-Stokes in conservation form with state 1023a8779fbSJames Wright // variables of density, momentum density, and total energy density. 1033a8779fbSJames Wright // 1043a8779fbSJames Wright // State Variables: q = ( rho, U1, U2, U3, E ) 1053a8779fbSJames Wright // rho - Mass Density 1063a8779fbSJames Wright // Ui - Momentum Density, Ui = rho ui 1073a8779fbSJames Wright // E - Total Energy Density, E = rho (cv T + (u u)/2 + g z) 1083a8779fbSJames Wright // 1093a8779fbSJames Wright // Navier-Stokes Equations: 1103a8779fbSJames Wright // drho/dt + div( U ) = 0 1113a8779fbSJames Wright // dU/dt + div( rho (u x u) + P I3 ) + rho g khat = div( Fu ) 1123a8779fbSJames Wright // dE/dt + div( (E + P) u ) = div( Fe ) 1133a8779fbSJames Wright // 1143a8779fbSJames Wright // Viscous Stress: 1153a8779fbSJames Wright // Fu = mu (grad( u ) + grad( u )^T + lambda div ( u ) I3) 1163a8779fbSJames Wright // 1173a8779fbSJames Wright // Thermal Stress: 1183a8779fbSJames Wright // Fe = u Fu + k grad( T ) 119bb8a0c61SJames Wright // Equation of State 1203a8779fbSJames Wright // P = (gamma - 1) (E - rho (u u) / 2 - rho g z) 1213a8779fbSJames Wright // 1223a8779fbSJames Wright // Stabilization: 1233a8779fbSJames Wright // Tau = diag(TauC, TauM, TauM, TauM, TauE) 1243a8779fbSJames Wright // f1 = rho sqrt(ui uj gij) 1253a8779fbSJames Wright // gij = dXi/dX * dXi/dX 1263a8779fbSJames Wright // TauC = Cc f1 / (8 gii) 1273a8779fbSJames Wright // TauM = min( 1 , 1 / f1 ) 1283a8779fbSJames Wright // TauE = TauM / (Ce cv) 1293a8779fbSJames Wright // 1303a8779fbSJames Wright // SU = Galerkin + grad(v) . ( Ai^T * Tau * (Aj q,j) ) 1313a8779fbSJames Wright // 1323a8779fbSJames Wright // Constants: 1333a8779fbSJames Wright // lambda = - 2 / 3, From Stokes hypothesis 1343a8779fbSJames Wright // mu , Dynamic viscosity 1353a8779fbSJames Wright // k , Thermal conductivity 1363a8779fbSJames Wright // cv , Specific heat, constant volume 1373a8779fbSJames Wright // cp , Specific heat, constant pressure 1383a8779fbSJames Wright // g , Gravity 1393a8779fbSJames Wright // gamma = cp / cv, Specific heat ratio 1403a8779fbSJames Wright // 1413a8779fbSJames Wright // We require the product of the inverse of the Jacobian (dXdx_j,k) and 1423a8779fbSJames Wright // its transpose (dXdx_k,j) to properly compute integrals of the form: 1433a8779fbSJames Wright // int( gradv gradu ) 1443a8779fbSJames Wright // 1453a8779fbSJames Wright // ***************************************************************************** 146*2b916ea7SJeremy L Thompson CEED_QFUNCTION(RHSFunction_Newtonian)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 1473a8779fbSJames Wright // *INDENT-OFF* 1483a8779fbSJames Wright // Inputs 149*2b916ea7SJeremy L Thompson const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], (*Grad_q)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 150*2b916ea7SJeremy L Thompson (*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; 1513a8779fbSJames Wright // Outputs 152*2b916ea7SJeremy L Thompson CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], (*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 1533a8779fbSJames Wright // *INDENT-ON* 1543a8779fbSJames Wright 1553a8779fbSJames Wright // Context 1563a8779fbSJames Wright NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 157bb8a0c61SJames Wright const CeedScalar *g = context->g; 158bb8a0c61SJames Wright const CeedScalar dt = context->dt; 1593a8779fbSJames Wright 1603a8779fbSJames Wright CeedPragmaSIMD 1613a8779fbSJames Wright // Quadrature Point Loop 1623a8779fbSJames Wright for (CeedInt i = 0; i < Q; i++) { 163c1a52365SJed Brown CeedScalar U[5]; 164c1a52365SJed Brown for (int j = 0; j < 5; j++) U[j] = q[j][i]; 165c1a52365SJed Brown const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 166c1a52365SJed Brown State s = StateFromU(context, U, x_i); 167c1a52365SJed Brown 1683a8779fbSJames Wright // -- Interp-to-Interp q_data 1693a8779fbSJames Wright const CeedScalar wdetJ = q_data[0][i]; 1703a8779fbSJames Wright // -- Interp-to-Grad q_data 1713a8779fbSJames Wright // ---- Inverse of change of coordinate matrix: X_i,j 1723a8779fbSJames Wright // *INDENT-OFF* 173*2b916ea7SJeremy L Thompson const CeedScalar dXdx[3][3] = { 174*2b916ea7SJeremy L Thompson {q_data[1][i], q_data[2][i], q_data[3][i]}, 17534ea8d65SJames Wright {q_data[4][i], q_data[5][i], q_data[6][i]}, 17634ea8d65SJames Wright {q_data[7][i], q_data[8][i], q_data[9][i]} 1773a8779fbSJames Wright }; 1783a8779fbSJames Wright // *INDENT-ON* 179c1a52365SJed Brown State grad_s[3]; 180eef2387dSJed Brown for (CeedInt j = 0; j < 3; j++) { 1812f7ce6c1SJed Brown CeedScalar dx_i[3] = {0}, dU[5]; 182*2b916ea7SJeremy L Thompson for (CeedInt k = 0; k < 5; k++) dU[k] = Grad_q[0][k][i] * dXdx[0][j] + Grad_q[1][k][i] * dXdx[1][j] + Grad_q[2][k][i] * dXdx[2][j]; 183c1a52365SJed Brown dx_i[j] = 1.; 1842f7ce6c1SJed Brown grad_s[j] = StateFromU_fwd(context, s, dU, x_i, dx_i); 185c1a52365SJed Brown } 186c1a52365SJed Brown 187c1a52365SJed Brown CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 188c1a52365SJed Brown KMStrainRate(grad_s, strain_rate); 189c1a52365SJed Brown NewtonianStress(context, strain_rate, kmstress); 190c1a52365SJed Brown KMUnpack(kmstress, stress); 191c1a52365SJed Brown ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 192c1a52365SJed Brown 193c1a52365SJed Brown StateConservative F_inviscid[3]; 194c1a52365SJed Brown FluxInviscid(context, s, F_inviscid); 195c1a52365SJed Brown 196c1a52365SJed Brown // Total flux 197c1a52365SJed Brown CeedScalar Flux[5][3]; 198d1b9ef12SLeila Ghaffari FluxTotal(F_inviscid, stress, Fe, Flux); 199c1a52365SJed Brown 200*2b916ea7SJeremy L Thompson for (CeedInt j = 0; j < 3; j++) { 201*2b916ea7SJeremy L Thompson for (CeedInt k = 0; k < 5; k++) Grad_v[j][k][i] = wdetJ * (dXdx[j][0] * Flux[k][0] + dXdx[j][1] * Flux[k][1] + dXdx[j][2] * Flux[k][2]); 202*2b916ea7SJeremy L Thompson } 203c1a52365SJed Brown 204c1a52365SJed Brown const CeedScalar body_force[5] = {0, s.U.density * g[0], s.U.density * g[1], s.U.density * g[2], 0}; 205*2b916ea7SJeremy L Thompson for (int j = 0; j < 5; j++) v[j][i] = wdetJ * body_force[j]; 2063a8779fbSJames Wright 207d1b9ef12SLeila Ghaffari // -- Stabilization method: none (Galerkin), SU, or SUPG 208d1b9ef12SLeila Ghaffari CeedScalar Tau_d[3], stab[5][3], U_dot[5] = {0}; 209d1b9ef12SLeila Ghaffari Tau_diagPrim(context, s, dXdx, dt, Tau_d); 210d1b9ef12SLeila Ghaffari Stabilization(context, s, Tau_d, grad_s, U_dot, body_force, x_i, stab); 2113a8779fbSJames Wright 212*2b916ea7SJeremy L Thompson for (CeedInt j = 0; j < 5; j++) { 213*2b916ea7SJeremy 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]); 214*2b916ea7SJeremy L Thompson } 2153a8779fbSJames Wright } // End Quadrature Point Loop 2163a8779fbSJames Wright 2173a8779fbSJames Wright // Return 2183a8779fbSJames Wright return 0; 2193a8779fbSJames Wright } 2203a8779fbSJames Wright 2213a8779fbSJames Wright // ***************************************************************************** 2223a8779fbSJames Wright // This QFunction implements the Navier-Stokes equations (mentioned above) with 2233a8779fbSJames Wright // implicit time stepping method 2243a8779fbSJames Wright // 2253a8779fbSJames Wright // SU = Galerkin + grad(v) . ( Ai^T * Tau * (Aj q,j) ) 2263a8779fbSJames Wright // SUPG = Galerkin + grad(v) . ( Ai^T * Tau * (q_dot + Aj q,j - body force) ) 2273a8779fbSJames Wright // (diffussive terms will be added later) 2283a8779fbSJames Wright // 2293a8779fbSJames Wright // ***************************************************************************** 230*2b916ea7SJeremy L Thompson CEED_QFUNCTION_HELPER int IFunction_Newtonian(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateFromQi_t StateFromQi, 231*2b916ea7SJeremy L Thompson StateFromQi_fwd_t StateFromQi_fwd) { 2323a8779fbSJames Wright // *INDENT-OFF* 2333a8779fbSJames Wright // Inputs 234*2b916ea7SJeremy L Thompson const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], (*Grad_q)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 235*2b916ea7SJeremy L Thompson (*q_dot)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], (*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 2363a8779fbSJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 2373a8779fbSJames Wright // Outputs 238*2b916ea7SJeremy L Thompson CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], (*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1], 239752f40e3SJed Brown (*jac_data)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[2]; 2403a8779fbSJames Wright // *INDENT-ON* 2413a8779fbSJames Wright // Context 2423a8779fbSJames Wright NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 243bb8a0c61SJames Wright const CeedScalar *g = context->g; 244bb8a0c61SJames Wright const CeedScalar dt = context->dt; 2453a8779fbSJames Wright 2463a8779fbSJames Wright CeedPragmaSIMD 2473a8779fbSJames Wright // Quadrature Point Loop 2483a8779fbSJames Wright for (CeedInt i = 0; i < Q; i++) { 24976555becSJames Wright CeedScalar qi[5]; 25076555becSJames Wright for (CeedInt j = 0; j < 5; j++) qi[j] = q[j][i]; 251c1a52365SJed Brown const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 25276555becSJames Wright State s = StateFromQi(context, qi, x_i); 253c1a52365SJed Brown 2543a8779fbSJames Wright // -- Interp-to-Interp q_data 2553a8779fbSJames Wright const CeedScalar wdetJ = q_data[0][i]; 2563a8779fbSJames Wright // -- Interp-to-Grad q_data 2573a8779fbSJames Wright // ---- Inverse of change of coordinate matrix: X_i,j 2583a8779fbSJames Wright // *INDENT-OFF* 259*2b916ea7SJeremy L Thompson const CeedScalar dXdx[3][3] = { 260*2b916ea7SJeremy L Thompson {q_data[1][i], q_data[2][i], q_data[3][i]}, 26134ea8d65SJames Wright {q_data[4][i], q_data[5][i], q_data[6][i]}, 26234ea8d65SJames Wright {q_data[7][i], q_data[8][i], q_data[9][i]} 2633a8779fbSJames Wright }; 2643a8779fbSJames Wright // *INDENT-ON* 265c1a52365SJed Brown State grad_s[3]; 266493642f1SJames Wright for (CeedInt j = 0; j < 3; j++) { 26776555becSJames Wright CeedScalar dx_i[3] = {0}, dqi[5]; 268*2b916ea7SJeremy L Thompson for (CeedInt k = 0; k < 5; k++) dqi[k] = Grad_q[0][k][i] * dXdx[0][j] + Grad_q[1][k][i] * dXdx[1][j] + Grad_q[2][k][i] * dXdx[2][j]; 269c1a52365SJed Brown dx_i[j] = 1.; 27076555becSJames Wright grad_s[j] = StateFromQi_fwd(context, s, dqi, x_i, dx_i); 2713a8779fbSJames Wright } 272c1a52365SJed Brown 273c1a52365SJed Brown CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 274c1a52365SJed Brown KMStrainRate(grad_s, strain_rate); 275c1a52365SJed Brown NewtonianStress(context, strain_rate, kmstress); 276c1a52365SJed Brown KMUnpack(kmstress, stress); 277c1a52365SJed Brown ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 278c1a52365SJed Brown 279c1a52365SJed Brown StateConservative F_inviscid[3]; 280c1a52365SJed Brown FluxInviscid(context, s, F_inviscid); 281c1a52365SJed Brown 282c1a52365SJed Brown // Total flux 283c1a52365SJed Brown CeedScalar Flux[5][3]; 284d1b9ef12SLeila Ghaffari FluxTotal(F_inviscid, stress, Fe, Flux); 285c1a52365SJed Brown 286*2b916ea7SJeremy L Thompson for (CeedInt j = 0; j < 3; j++) { 287*2b916ea7SJeremy L Thompson for (CeedInt k = 0; k < 5; k++) Grad_v[j][k][i] = -wdetJ * (dXdx[j][0] * Flux[k][0] + dXdx[j][1] * Flux[k][1] + dXdx[j][2] * Flux[k][2]); 288*2b916ea7SJeremy L Thompson } 289c1a52365SJed Brown 290c1a52365SJed Brown const CeedScalar body_force[5] = {0, s.U.density * g[0], s.U.density * g[1], s.U.density * g[2], 0}; 2913a8779fbSJames Wright 292d1b9ef12SLeila Ghaffari // -- Stabilization method: none (Galerkin), SU, or SUPG 29376555becSJames Wright CeedScalar Tau_d[3], stab[5][3], U_dot[5] = {0}, qi_dot[5], dx0[3] = {0}; 29476555becSJames Wright for (int j = 0; j < 5; j++) qi_dot[j] = q_dot[j][i]; 29576555becSJames Wright State s_dot = StateFromQi_fwd(context, s, qi_dot, x_i, dx0); 29676555becSJames Wright UnpackState_U(s_dot.U, U_dot); 29776555becSJames Wright 298*2b916ea7SJeremy L Thompson for (CeedInt j = 0; j < 5; j++) v[j][i] = wdetJ * (U_dot[j] - body_force[j]); 299d1b9ef12SLeila Ghaffari Tau_diagPrim(context, s, dXdx, dt, Tau_d); 300d1b9ef12SLeila Ghaffari Stabilization(context, s, Tau_d, grad_s, U_dot, body_force, x_i, stab); 3013a8779fbSJames Wright 302*2b916ea7SJeremy L Thompson for (CeedInt j = 0; j < 5; j++) { 303*2b916ea7SJeremy 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]); 304*2b916ea7SJeremy L Thompson } 30576555becSJames Wright for (CeedInt j = 0; j < 5; j++) jac_data[j][i] = qi[j]; 306eef2387dSJed Brown for (CeedInt j = 0; j < 6; j++) jac_data[5 + j][i] = kmstress[j]; 307eef2387dSJed Brown for (CeedInt j = 0; j < 3; j++) jac_data[5 + 6 + j][i] = Tau_d[j]; 3083a8779fbSJames Wright 3093a8779fbSJames Wright } // End Quadrature Point Loop 3103a8779fbSJames Wright 3113a8779fbSJames Wright // Return 3123a8779fbSJames Wright return 0; 3133a8779fbSJames Wright } 314f0b65372SJed Brown 315*2b916ea7SJeremy L Thompson CEED_QFUNCTION(IFunction_Newtonian_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 31676555becSJames Wright return IFunction_Newtonian(ctx, Q, in, out, StateFromU, StateFromU_fwd); 31776555becSJames Wright } 31876555becSJames Wright 319*2b916ea7SJeremy L Thompson CEED_QFUNCTION(IFunction_Newtonian_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 32076555becSJames Wright return IFunction_Newtonian(ctx, Q, in, out, StateFromY, StateFromY_fwd); 32176555becSJames Wright } 32276555becSJames Wright 323cbe60e31SLeila Ghaffari // ***************************************************************************** 32476555becSJames Wright // This QFunction implements the jacobian of the Navier-Stokes equations 325cbe60e31SLeila Ghaffari // for implicit time stepping method. 326cbe60e31SLeila Ghaffari // ***************************************************************************** 327*2b916ea7SJeremy L Thompson CEED_QFUNCTION_HELPER int IJacobian_Newtonian(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateFromQi_t StateFromQi, 328*2b916ea7SJeremy L Thompson StateFromQi_fwd_t StateFromQi_fwd) { 329f0b65372SJed Brown // *INDENT-OFF* 330f0b65372SJed Brown // Inputs 331*2b916ea7SJeremy L Thompson const CeedScalar(*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], (*Grad_dq)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 332*2b916ea7SJeremy L Thompson (*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 333f0b65372SJed Brown (*jac_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 334f0b65372SJed Brown // Outputs 335*2b916ea7SJeremy L Thompson CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], (*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 336f0b65372SJed Brown // *INDENT-ON* 337f0b65372SJed Brown // Context 338f0b65372SJed Brown NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 339f0b65372SJed Brown const CeedScalar *g = context->g; 340f0b65372SJed Brown 341f0b65372SJed Brown CeedPragmaSIMD 342f0b65372SJed Brown // Quadrature Point Loop 343f0b65372SJed Brown for (CeedInt i = 0; i < Q; i++) { 344f0b65372SJed Brown // -- Interp-to-Interp q_data 345f0b65372SJed Brown const CeedScalar wdetJ = q_data[0][i]; 346f0b65372SJed Brown // -- Interp-to-Grad q_data 347f0b65372SJed Brown // ---- Inverse of change of coordinate matrix: X_i,j 348f0b65372SJed Brown // *INDENT-OFF* 349*2b916ea7SJeremy L Thompson const CeedScalar dXdx[3][3] = { 350*2b916ea7SJeremy L Thompson {q_data[1][i], q_data[2][i], q_data[3][i]}, 35134ea8d65SJames Wright {q_data[4][i], q_data[5][i], q_data[6][i]}, 35234ea8d65SJames Wright {q_data[7][i], q_data[8][i], q_data[9][i]} 353f0b65372SJed Brown }; 354f0b65372SJed Brown // *INDENT-ON* 355f0b65372SJed Brown 3568789e95fSJames Wright CeedScalar qi[5], kmstress[6], Tau_d[3]; 35776555becSJames Wright for (int j = 0; j < 5; j++) qi[j] = jac_data[j][i]; 358f0b65372SJed Brown for (int j = 0; j < 6; j++) kmstress[j] = jac_data[5 + j][i]; 359f0b65372SJed Brown for (int j = 0; j < 3; j++) Tau_d[j] = jac_data[5 + 6 + j][i]; 360f0b65372SJed Brown const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 36176555becSJames Wright State s = StateFromQi(context, qi, x_i); 362f0b65372SJed Brown 36376555becSJames Wright CeedScalar dqi[5], dx0[3] = {0}; 36476555becSJames Wright for (int j = 0; j < 5; j++) dqi[j] = dq[j][i]; 36576555becSJames Wright State ds = StateFromQi_fwd(context, s, dqi, x_i, dx0); 366f0b65372SJed Brown 367f0b65372SJed Brown State grad_ds[3]; 368f0b65372SJed Brown for (int j = 0; j < 3; j++) { 36976555becSJames Wright CeedScalar dqi_j[5]; 370*2b916ea7SJeremy L Thompson for (int k = 0; k < 5; k++) dqi_j[k] = Grad_dq[0][k][i] * dXdx[0][j] + Grad_dq[1][k][i] * dXdx[1][j] + Grad_dq[2][k][i] * dXdx[2][j]; 37176555becSJames Wright grad_ds[j] = StateFromQi_fwd(context, s, dqi_j, x_i, dx0); 372f0b65372SJed Brown } 373f0b65372SJed Brown 374f0b65372SJed Brown CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 375f0b65372SJed Brown KMStrainRate(grad_ds, dstrain_rate); 376f0b65372SJed Brown NewtonianStress(context, dstrain_rate, dkmstress); 377f0b65372SJed Brown KMUnpack(dkmstress, dstress); 378f0b65372SJed Brown KMUnpack(kmstress, stress); 379f0b65372SJed Brown ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 380f0b65372SJed Brown 381f0b65372SJed Brown StateConservative dF_inviscid[3]; 382f0b65372SJed Brown FluxInviscid_fwd(context, s, ds, dF_inviscid); 383f0b65372SJed Brown 384f0b65372SJed Brown // Total flux 385f0b65372SJed Brown CeedScalar dFlux[5][3]; 386d1b9ef12SLeila Ghaffari FluxTotal(dF_inviscid, dstress, dFe, dFlux); 387f0b65372SJed Brown 388*2b916ea7SJeremy L Thompson for (int j = 0; j < 3; j++) { 389*2b916ea7SJeremy L Thompson for (int k = 0; k < 5; k++) Grad_v[j][k][i] = -wdetJ * (dXdx[j][0] * dFlux[k][0] + dXdx[j][1] * dFlux[k][1] + dXdx[j][2] * dFlux[k][2]); 390*2b916ea7SJeremy L Thompson } 391f0b65372SJed Brown 392f0b65372SJed Brown const CeedScalar dbody_force[5] = {0, ds.U.density * g[0], ds.U.density * g[1], ds.U.density * g[2], 0}; 39376555becSJames Wright CeedScalar dU[5] = {0.}; 39476555becSJames Wright UnpackState_U(ds.U, dU); 395*2b916ea7SJeremy L Thompson for (int j = 0; j < 5; j++) v[j][i] = wdetJ * (context->ijacobian_time_shift * dU[j] - dbody_force[j]); 396f0b65372SJed Brown 397d1b9ef12SLeila Ghaffari // -- Stabilization method: none (Galerkin), SU, or SUPG 398d1b9ef12SLeila Ghaffari CeedScalar dstab[5][3], U_dot[5] = {0}; 399d1b9ef12SLeila Ghaffari for (CeedInt j = 0; j < 5; j++) U_dot[j] = context->ijacobian_time_shift * dU[j]; 400d1b9ef12SLeila Ghaffari Stabilization(context, s, Tau_d, grad_ds, U_dot, dbody_force, x_i, dstab); 401d1b9ef12SLeila Ghaffari 402*2b916ea7SJeremy L Thompson for (int j = 0; j < 5; j++) { 403*2b916ea7SJeremy 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]); 404*2b916ea7SJeremy L Thompson } 405f0b65372SJed Brown } // End Quadrature Point Loop 406f0b65372SJed Brown return 0; 407f0b65372SJed Brown } 4088085925cSJames Wright 409*2b916ea7SJeremy L Thompson CEED_QFUNCTION(IJacobian_Newtonian_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 41076555becSJames Wright return IJacobian_Newtonian(ctx, Q, in, out, StateFromU, StateFromU_fwd); 41176555becSJames Wright } 41276555becSJames Wright 413*2b916ea7SJeremy L Thompson CEED_QFUNCTION(IJacobian_Newtonian_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 41476555becSJames Wright return IJacobian_Newtonian(ctx, Q, in, out, StateFromY, StateFromY_fwd); 41576555becSJames Wright } 41676555becSJames Wright 417d1b9ef12SLeila Ghaffari // ***************************************************************************** 4188085925cSJames Wright // Compute boundary integral (ie. for strongly set inflows) 419d1b9ef12SLeila Ghaffari // ***************************************************************************** 420*2b916ea7SJeremy L Thompson CEED_QFUNCTION_HELPER int BoundaryIntegral(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateFromQi_t StateFromQi, 421*2b916ea7SJeremy L Thompson StateFromQi_fwd_t StateFromQi_fwd) { 4228085925cSJames Wright //*INDENT-OFF* 423*2b916ea7SJeremy L Thompson const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], (*Grad_q)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 424*2b916ea7SJeremy L Thompson (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; 4258085925cSJames Wright 426*2b916ea7SJeremy L Thompson CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], (*jac_data_sur)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[1]; 4278085925cSJames Wright 4288085925cSJames Wright //*INDENT-ON* 4298085925cSJames Wright 430d3b25f3aSJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 431d3b25f3aSJames Wright const bool is_implicit = context->is_implicit; 4328085925cSJames Wright 433*2b916ea7SJeremy L Thompson CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 434d3b25f3aSJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 43541e73928SJames Wright const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 43641e73928SJames Wright State s = StateFromQi(context, qi, x_i); 4378085925cSJames Wright 4388085925cSJames Wright const CeedScalar wdetJb = (is_implicit ? -1. : 1.) * q_data_sur[0][i]; 439c5740391SJames Wright // ---- Normal vector 440*2b916ea7SJeremy L Thompson const CeedScalar norm[3] = {q_data_sur[1][i], q_data_sur[2][i], q_data_sur[3][i]}; 4418085925cSJames Wright 442d3b25f3aSJames Wright const CeedScalar dXdx[2][3] = { 443d3b25f3aSJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 444d3b25f3aSJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 445d3b25f3aSJames Wright }; 4468085925cSJames Wright 447d3b25f3aSJames Wright State grad_s[3]; 448d3b25f3aSJames Wright for (CeedInt j = 0; j < 3; j++) { 44941e73928SJames Wright CeedScalar dx_i[3] = {0}, dqi[5]; 450*2b916ea7SJeremy L Thompson for (CeedInt k = 0; k < 5; k++) dqi[k] = Grad_q[0][k][i] * dXdx[0][j] + Grad_q[1][k][i] * dXdx[1][j]; 451d3b25f3aSJames Wright dx_i[j] = 1.; 45241e73928SJames Wright grad_s[j] = StateFromQi_fwd(context, s, dqi, x_i, dx_i); 453d3b25f3aSJames Wright } 4548085925cSJames Wright 455d3b25f3aSJames Wright CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 456d3b25f3aSJames Wright KMStrainRate(grad_s, strain_rate); 457d3b25f3aSJames Wright NewtonianStress(context, strain_rate, kmstress); 458d3b25f3aSJames Wright KMUnpack(kmstress, stress); 459d3b25f3aSJames Wright ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 460d3b25f3aSJames Wright 461d3b25f3aSJames Wright StateConservative F_inviscid[3]; 462d3b25f3aSJames Wright FluxInviscid(context, s, F_inviscid); 463d3b25f3aSJames Wright 464c5740391SJames Wright CeedScalar Flux[5]; 465c5740391SJames Wright FluxTotal_Boundary(F_inviscid, stress, Fe, norm, Flux); 466d3b25f3aSJames Wright 467c5740391SJames Wright for (CeedInt j = 0; j < 5; j++) v[j][i] = -wdetJb * Flux[j]; 4688085925cSJames Wright 469c5740391SJames Wright for (int j = 0; j < 5; j++) jac_data_sur[j][i] = qi[j]; 47068ae065aSJames Wright for (int j = 0; j < 6; j++) jac_data_sur[5 + j][i] = kmstress[j]; 4718085925cSJames Wright } 4728085925cSJames Wright return 0; 4738085925cSJames Wright } 4748085925cSJames Wright 475*2b916ea7SJeremy L Thompson CEED_QFUNCTION(BoundaryIntegral_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 476d4559bbeSJames Wright return BoundaryIntegral(ctx, Q, in, out, StateFromU, StateFromU_fwd); 477d4559bbeSJames Wright } 478d4559bbeSJames Wright 479*2b916ea7SJeremy L Thompson CEED_QFUNCTION(BoundaryIntegral_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 480d4559bbeSJames Wright return BoundaryIntegral(ctx, Q, in, out, StateFromY, StateFromY_fwd); 481d4559bbeSJames Wright } 482d4559bbeSJames Wright 483d1b9ef12SLeila Ghaffari // ***************************************************************************** 48468ae065aSJames Wright // Jacobian for "set nothing" boundary integral 485d1b9ef12SLeila Ghaffari // ***************************************************************************** 486*2b916ea7SJeremy L Thompson CEED_QFUNCTION_HELPER int BoundaryIntegral_Jacobian(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, 487d4559bbeSJames Wright StateFromQi_t StateFromQi, StateFromQi_fwd_t StateFromQi_fwd) { 48868ae065aSJames Wright // *INDENT-OFF* 48968ae065aSJames Wright // Inputs 490*2b916ea7SJeremy L Thompson const CeedScalar(*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], (*Grad_dq)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 491*2b916ea7SJeremy L Thompson (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 49268ae065aSJames Wright (*jac_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 49368ae065aSJames Wright // Outputs 49468ae065aSJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 49568ae065aSJames Wright // *INDENT-ON* 49668ae065aSJames Wright 49768ae065aSJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 49868ae065aSJames Wright const bool implicit = context->is_implicit; 49968ae065aSJames Wright 50068ae065aSJames Wright CeedPragmaSIMD 50168ae065aSJames Wright // Quadrature Point Loop 50268ae065aSJames Wright for (CeedInt i = 0; i < Q; i++) { 50368ae065aSJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 50468ae065aSJames Wright const CeedScalar wdetJb = (implicit ? -1. : 1.) * q_data_sur[0][i]; 505*2b916ea7SJeremy L Thompson const CeedScalar norm[3] = {q_data_sur[1][i], q_data_sur[2][i], q_data_sur[3][i]}; 50668ae065aSJames Wright const CeedScalar dXdx[2][3] = { 50768ae065aSJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 50868ae065aSJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 50968ae065aSJames Wright }; 51068ae065aSJames Wright 51141e73928SJames Wright CeedScalar qi[5], kmstress[6], dqi[5], dx_i[3] = {0.}; 51241e73928SJames Wright for (int j = 0; j < 5; j++) qi[j] = jac_data_sur[j][i]; 51368ae065aSJames Wright for (int j = 0; j < 6; j++) kmstress[j] = jac_data_sur[5 + j][i]; 51441e73928SJames Wright for (int j = 0; j < 5; j++) dqi[j] = dq[j][i]; 5153934e2b1SJames Wright 51641e73928SJames Wright State s = StateFromQi(context, qi, x_i); 51741e73928SJames Wright State ds = StateFromQi_fwd(context, s, dqi, x_i, dx_i); 51868ae065aSJames Wright 51968ae065aSJames Wright State grad_ds[3]; 52068ae065aSJames Wright for (CeedInt j = 0; j < 3; j++) { 52141e73928SJames Wright CeedScalar dx_i[3] = {0}, dqi_j[5]; 522*2b916ea7SJeremy L Thompson for (CeedInt k = 0; k < 5; k++) dqi_j[k] = Grad_dq[0][k][i] * dXdx[0][j] + Grad_dq[1][k][i] * dXdx[1][j]; 52368ae065aSJames Wright dx_i[j] = 1.; 52441e73928SJames Wright grad_ds[j] = StateFromQi_fwd(context, s, dqi_j, x_i, dx_i); 52568ae065aSJames Wright } 52668ae065aSJames Wright 52768ae065aSJames Wright CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 52868ae065aSJames Wright KMStrainRate(grad_ds, dstrain_rate); 52968ae065aSJames Wright NewtonianStress(context, dstrain_rate, dkmstress); 53068ae065aSJames Wright KMUnpack(dkmstress, dstress); 53168ae065aSJames Wright KMUnpack(kmstress, stress); 53268ae065aSJames Wright ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 53368ae065aSJames Wright 53468ae065aSJames Wright StateConservative dF_inviscid[3]; 53568ae065aSJames Wright FluxInviscid_fwd(context, s, ds, dF_inviscid); 53668ae065aSJames Wright 537c5740391SJames Wright CeedScalar dFlux[5]; 538c5740391SJames Wright FluxTotal_Boundary(dF_inviscid, dstress, dFe, norm, dFlux); 53968ae065aSJames Wright 540c5740391SJames Wright for (int j = 0; j < 5; j++) v[j][i] = -wdetJb * dFlux[j]; 54168ae065aSJames Wright } // End Quadrature Point Loop 54268ae065aSJames Wright return 0; 54368ae065aSJames Wright } 54468ae065aSJames Wright 545*2b916ea7SJeremy L Thompson CEED_QFUNCTION(BoundaryIntegral_Jacobian_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 546d4559bbeSJames Wright return BoundaryIntegral_Jacobian(ctx, Q, in, out, StateFromU, StateFromU_fwd); 547d4559bbeSJames Wright } 548d4559bbeSJames Wright 549*2b916ea7SJeremy L Thompson CEED_QFUNCTION(BoundaryIntegral_Jacobian_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 550d4559bbeSJames Wright return BoundaryIntegral_Jacobian(ctx, Q, in, out, StateFromY, StateFromY_fwd); 551d4559bbeSJames Wright } 552d4559bbeSJames Wright 553d1b9ef12SLeila Ghaffari // ***************************************************************************** 55404b9037bSJames Wright // Outflow boundary condition, weakly setting a constant pressure 555d1b9ef12SLeila Ghaffari // ***************************************************************************** 556*2b916ea7SJeremy L Thompson CEED_QFUNCTION_HELPER int PressureOutflow(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateFromQi_t StateFromQi, 557*2b916ea7SJeremy L Thompson StateFromQi_fwd_t StateFromQi_fwd) { 55804b9037bSJames Wright // *INDENT-OFF* 55904b9037bSJames Wright // Inputs 560*2b916ea7SJeremy L Thompson const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], (*Grad_q)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 561*2b916ea7SJeremy L Thompson (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; 56204b9037bSJames Wright // Outputs 563*2b916ea7SJeremy L Thompson CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], (*jac_data_sur)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[1]; 56404b9037bSJames Wright // *INDENT-ON* 56504b9037bSJames Wright 56604b9037bSJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 56704b9037bSJames Wright const bool implicit = context->is_implicit; 56804b9037bSJames Wright const CeedScalar P0 = context->P0; 56904b9037bSJames Wright 57004b9037bSJames Wright CeedPragmaSIMD 57104b9037bSJames Wright // Quadrature Point Loop 57204b9037bSJames Wright for (CeedInt i = 0; i < Q; i++) { 57304b9037bSJames Wright // Setup 57404b9037bSJames Wright // -- Interp in 57525bfcc41SJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 57641e73928SJames Wright const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 57741e73928SJames Wright State s = StateFromQi(context, qi, x_i); 57825bfcc41SJames Wright s.Y.pressure = P0; 57904b9037bSJames Wright 58004b9037bSJames Wright // -- Interp-to-Interp q_data 58104b9037bSJames Wright // For explicit mode, the surface integral is on the RHS of ODE q_dot = f(q). 58204b9037bSJames Wright // For implicit mode, it gets pulled to the LHS of implicit ODE/DAE g(q_dot, q). 58304b9037bSJames Wright // We can effect this by swapping the sign on this weight 58404b9037bSJames Wright const CeedScalar wdetJb = (implicit ? -1. : 1.) * q_data_sur[0][i]; 58504b9037bSJames Wright 586c5740391SJames Wright // ---- Normal vector 587d4559bbeSJames Wright const CeedScalar norm[3] = {q_data_sur[1][i], q_data_sur[2][i], q_data_sur[3][i]}; 58804b9037bSJames Wright 58925bfcc41SJames Wright const CeedScalar dXdx[2][3] = { 59025bfcc41SJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 59125bfcc41SJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 59225bfcc41SJames Wright }; 59304b9037bSJames Wright 59425bfcc41SJames Wright State grad_s[3]; 59525bfcc41SJames Wright for (CeedInt j = 0; j < 3; j++) { 59641e73928SJames Wright CeedScalar dx_i[3] = {0}, dqi[5]; 597*2b916ea7SJeremy L Thompson for (CeedInt k = 0; k < 5; k++) dqi[k] = Grad_q[0][k][i] * dXdx[0][j] + Grad_q[1][k][i] * dXdx[1][j]; 59825bfcc41SJames Wright dx_i[j] = 1.; 59941e73928SJames Wright grad_s[j] = StateFromQi_fwd(context, s, dqi, x_i, dx_i); 60025bfcc41SJames Wright } 60125bfcc41SJames Wright 60225bfcc41SJames Wright CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 60325bfcc41SJames Wright KMStrainRate(grad_s, strain_rate); 60425bfcc41SJames Wright NewtonianStress(context, strain_rate, kmstress); 60525bfcc41SJames Wright KMUnpack(kmstress, stress); 60625bfcc41SJames Wright ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 60725bfcc41SJames Wright 60825bfcc41SJames Wright StateConservative F_inviscid[3]; 60925bfcc41SJames Wright FluxInviscid(context, s, F_inviscid); 61025bfcc41SJames Wright 611c5740391SJames Wright CeedScalar Flux[5]; 612c5740391SJames Wright FluxTotal_Boundary(F_inviscid, stress, Fe, norm, Flux); 61304b9037bSJames Wright 614c5740391SJames Wright for (CeedInt j = 0; j < 5; j++) v[j][i] = -wdetJb * Flux[j]; 61504b9037bSJames Wright 61604b9037bSJames Wright // Save values for Jacobian 617c5740391SJames Wright for (int j = 0; j < 5; j++) jac_data_sur[j][i] = qi[j]; 618b01ba163SJames Wright for (int j = 0; j < 6; j++) jac_data_sur[5 + j][i] = kmstress[j]; 61904b9037bSJames Wright } // End Quadrature Point Loop 62004b9037bSJames Wright return 0; 62104b9037bSJames Wright } 62204b9037bSJames Wright 623*2b916ea7SJeremy L Thompson CEED_QFUNCTION(PressureOutflow_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 624d4559bbeSJames Wright return PressureOutflow(ctx, Q, in, out, StateFromU, StateFromU_fwd); 625d4559bbeSJames Wright } 626d4559bbeSJames Wright 627*2b916ea7SJeremy L Thompson CEED_QFUNCTION(PressureOutflow_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 628d4559bbeSJames Wright return PressureOutflow(ctx, Q, in, out, StateFromY, StateFromY_fwd); 629d4559bbeSJames Wright } 630d4559bbeSJames Wright 631d1b9ef12SLeila Ghaffari // ***************************************************************************** 63204b9037bSJames Wright // Jacobian for weak-pressure outflow boundary condition 633d1b9ef12SLeila Ghaffari // ***************************************************************************** 634*2b916ea7SJeremy L Thompson CEED_QFUNCTION_HELPER int PressureOutflow_Jacobian(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, 635d4559bbeSJames Wright StateFromQi_t StateFromQi, StateFromQi_fwd_t StateFromQi_fwd) { 63604b9037bSJames Wright // *INDENT-OFF* 63704b9037bSJames Wright // Inputs 638*2b916ea7SJeremy L Thompson const CeedScalar(*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], (*Grad_dq)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 639*2b916ea7SJeremy L Thompson (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 640b01ba163SJames Wright (*jac_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 64104b9037bSJames Wright // Outputs 64204b9037bSJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 64304b9037bSJames Wright // *INDENT-ON* 64404b9037bSJames Wright 64504b9037bSJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 64604b9037bSJames Wright const bool implicit = context->is_implicit; 64704b9037bSJames Wright 64804b9037bSJames Wright CeedPragmaSIMD 64904b9037bSJames Wright // Quadrature Point Loop 65004b9037bSJames Wright for (CeedInt i = 0; i < Q; i++) { 651b01ba163SJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 65204b9037bSJames Wright const CeedScalar wdetJb = (implicit ? -1. : 1.) * q_data_sur[0][i]; 653d4559bbeSJames Wright const CeedScalar norm[3] = {q_data_sur[1][i], q_data_sur[2][i], q_data_sur[3][i]}; 654b01ba163SJames Wright const CeedScalar dXdx[2][3] = { 655b01ba163SJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 656b01ba163SJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 657b01ba163SJames Wright }; 658b01ba163SJames Wright 65941e73928SJames Wright CeedScalar qi[5], kmstress[6], dqi[5], dx_i[3] = {0.}; 66041e73928SJames Wright for (int j = 0; j < 5; j++) qi[j] = jac_data_sur[j][i]; 661b01ba163SJames Wright for (int j = 0; j < 6; j++) kmstress[j] = jac_data_sur[5 + j][i]; 66241e73928SJames Wright for (int j = 0; j < 5; j++) dqi[j] = dq[j][i]; 6633934e2b1SJames Wright 66441e73928SJames Wright State s = StateFromQi(context, qi, x_i); 66541e73928SJames Wright State ds = StateFromQi_fwd(context, s, dqi, x_i, dx_i); 666b01ba163SJames Wright s.Y.pressure = context->P0; 667b01ba163SJames Wright ds.Y.pressure = 0.; 668b01ba163SJames Wright 669b01ba163SJames Wright State grad_ds[3]; 670b01ba163SJames Wright for (CeedInt j = 0; j < 3; j++) { 67141e73928SJames Wright CeedScalar dx_i[3] = {0}, dqi_j[5]; 672*2b916ea7SJeremy L Thompson for (CeedInt k = 0; k < 5; k++) dqi_j[k] = Grad_dq[0][k][i] * dXdx[0][j] + Grad_dq[1][k][i] * dXdx[1][j]; 673b01ba163SJames Wright dx_i[j] = 1.; 67441e73928SJames Wright grad_ds[j] = StateFromQi_fwd(context, s, dqi_j, x_i, dx_i); 675b01ba163SJames Wright } 676b01ba163SJames Wright 677b01ba163SJames Wright CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 678b01ba163SJames Wright KMStrainRate(grad_ds, dstrain_rate); 679b01ba163SJames Wright NewtonianStress(context, dstrain_rate, dkmstress); 680b01ba163SJames Wright KMUnpack(dkmstress, dstress); 681b01ba163SJames Wright KMUnpack(kmstress, stress); 682b01ba163SJames Wright ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 68304b9037bSJames Wright 684e6b47afbSJames Wright StateConservative dF_inviscid[3]; 685e6b47afbSJames Wright FluxInviscid_fwd(context, s, ds, dF_inviscid); 68604b9037bSJames Wright 687c5740391SJames Wright CeedScalar dFlux[5]; 688c5740391SJames Wright FluxTotal_Boundary(dF_inviscid, dstress, dFe, norm, dFlux); 689e6b47afbSJames Wright 690c5740391SJames Wright for (int j = 0; j < 5; j++) v[j][i] = -wdetJb * dFlux[j]; 69104b9037bSJames Wright } // End Quadrature Point Loop 69204b9037bSJames Wright return 0; 69304b9037bSJames Wright } 69404b9037bSJames Wright 695*2b916ea7SJeremy L Thompson CEED_QFUNCTION(PressureOutflow_Jacobian_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 696d4559bbeSJames Wright return PressureOutflow_Jacobian(ctx, Q, in, out, StateFromU, StateFromU_fwd); 697d4559bbeSJames Wright } 698d4559bbeSJames Wright 699*2b916ea7SJeremy L Thompson CEED_QFUNCTION(PressureOutflow_Jacobian_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 700d4559bbeSJames Wright return PressureOutflow_Jacobian(ctx, Q, in, out, StateFromY, StateFromY_fwd); 701d4559bbeSJames Wright } 702*2b916ea7SJeremy L Thompson 7033a8779fbSJames Wright #endif // newtonian_h 704