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 123a8779fbSJames Wright #ifndef newtonian_h 133a8779fbSJames Wright #define newtonian_h 143a8779fbSJames Wright 153a8779fbSJames Wright #include <ceed.h> 16d0cce58aSJeremy L Thompson #include <math.h> 17475b2820SJames Wright #include "newtonian_state.h" 18d0cce58aSJeremy L Thompson #include "newtonian_types.h" 19d1b9ef12SLeila Ghaffari #include "stabilization.h" 20d0cce58aSJeremy L Thompson #include "utils.h" 21bb8a0c61SJames Wright 22bb8a0c61SJames Wright // ***************************************************************************** 233a8779fbSJames Wright // This QFunction sets a "still" initial condition for generic Newtonian IG problems 243a8779fbSJames Wright // ***************************************************************************** 253a8779fbSJames Wright CEED_QFUNCTION(ICsNewtonianIG)(void *ctx, CeedInt Q, 263a8779fbSJames Wright 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 433a8779fbSJames Wright CeedPragmaSIMD 443a8779fbSJames Wright for (CeedInt i=0; i<Q; i++) { 453a8779fbSJames Wright CeedScalar q[5] = {0.}; 463a8779fbSJames Wright 473a8779fbSJames Wright // Setup 483a8779fbSJames Wright // -- Coordinates 49bb8a0c61SJames Wright const CeedScalar x[3] = {X[0][i], X[1][i], X[2][i]}; 50d1b9ef12SLeila Ghaffari const CeedScalar e_potential = -Dot3(g, x); 513a8779fbSJames Wright 523a8779fbSJames Wright // -- Density 53bb8a0c61SJames Wright const CeedScalar rho = P0 / (Rd*theta0); 543a8779fbSJames Wright 553a8779fbSJames Wright // Initial Conditions 563a8779fbSJames Wright q[0] = rho; 573a8779fbSJames Wright q[1] = 0.0; 583a8779fbSJames Wright q[2] = 0.0; 593a8779fbSJames Wright q[3] = 0.0; 60bb8a0c61SJames Wright q[4] = rho * (cv*theta0 + e_potential); 613a8779fbSJames Wright 623a8779fbSJames Wright for (CeedInt j=0; j<5; j++) 633a8779fbSJames Wright q0[j][i] = q[j]; 64d1b9ef12SLeila Ghaffari 653a8779fbSJames Wright } // End of Quadrature Point Loop 663a8779fbSJames Wright return 0; 673a8779fbSJames Wright } 683a8779fbSJames Wright 693a8779fbSJames Wright // ***************************************************************************** 70cbe60e31SLeila Ghaffari // This QFunction sets a "still" initial condition for generic Newtonian IG 71cbe60e31SLeila Ghaffari // problems in primitive variables 72cbe60e31SLeila Ghaffari // ***************************************************************************** 73cbe60e31SLeila Ghaffari CEED_QFUNCTION(ICsNewtonianIG_Prim)(void *ctx, CeedInt Q, 74cbe60e31SLeila Ghaffari const CeedScalar *const *in, CeedScalar *const *out) { 75cbe60e31SLeila Ghaffari // Outputs 76cbe60e31SLeila Ghaffari CeedScalar (*q0)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 77cbe60e31SLeila Ghaffari 78cbe60e31SLeila Ghaffari // Context 79cbe60e31SLeila Ghaffari const SetupContext context = (SetupContext)ctx; 80cbe60e31SLeila Ghaffari const CeedScalar theta0 = context->theta0; 81cbe60e31SLeila Ghaffari const CeedScalar P0 = context->P0; 82cbe60e31SLeila Ghaffari 83cbe60e31SLeila Ghaffari // Quadrature Point Loop 84cbe60e31SLeila Ghaffari CeedPragmaSIMD 85cbe60e31SLeila Ghaffari for (CeedInt i=0; i<Q; i++) { 86cbe60e31SLeila Ghaffari CeedScalar q[5] = {0.}; 87cbe60e31SLeila Ghaffari 88cbe60e31SLeila Ghaffari // Initial Conditions 89cbe60e31SLeila Ghaffari q[0] = P0; 90cbe60e31SLeila Ghaffari q[1] = 0.0; 91cbe60e31SLeila Ghaffari q[2] = 0.0; 92cbe60e31SLeila Ghaffari q[3] = 0.0; 93cbe60e31SLeila Ghaffari q[4] = theta0; 94cbe60e31SLeila Ghaffari 95cbe60e31SLeila Ghaffari for (CeedInt j=0; j<5; j++) 96cbe60e31SLeila Ghaffari q0[j][i] = q[j]; 97cbe60e31SLeila Ghaffari 98cbe60e31SLeila Ghaffari } // End of Quadrature Point Loop 99cbe60e31SLeila Ghaffari return 0; 100cbe60e31SLeila Ghaffari } 101cbe60e31SLeila Ghaffari 102cbe60e31SLeila Ghaffari // ***************************************************************************** 1033a8779fbSJames Wright // This QFunction implements the following formulation of Navier-Stokes with 1043a8779fbSJames Wright // explicit time stepping method 1053a8779fbSJames Wright // 1063a8779fbSJames Wright // This is 3D compressible Navier-Stokes in conservation form with state 1073a8779fbSJames Wright // variables of density, momentum density, and total energy density. 1083a8779fbSJames Wright // 1093a8779fbSJames Wright // State Variables: q = ( rho, U1, U2, U3, E ) 1103a8779fbSJames Wright // rho - Mass Density 1113a8779fbSJames Wright // Ui - Momentum Density, Ui = rho ui 1123a8779fbSJames Wright // E - Total Energy Density, E = rho (cv T + (u u)/2 + g z) 1133a8779fbSJames Wright // 1143a8779fbSJames Wright // Navier-Stokes Equations: 1153a8779fbSJames Wright // drho/dt + div( U ) = 0 1163a8779fbSJames Wright // dU/dt + div( rho (u x u) + P I3 ) + rho g khat = div( Fu ) 1173a8779fbSJames Wright // dE/dt + div( (E + P) u ) = div( Fe ) 1183a8779fbSJames Wright // 1193a8779fbSJames Wright // Viscous Stress: 1203a8779fbSJames Wright // Fu = mu (grad( u ) + grad( u )^T + lambda div ( u ) I3) 1213a8779fbSJames Wright // 1223a8779fbSJames Wright // Thermal Stress: 1233a8779fbSJames Wright // Fe = u Fu + k grad( T ) 124bb8a0c61SJames Wright // Equation of State 1253a8779fbSJames Wright // P = (gamma - 1) (E - rho (u u) / 2 - rho g z) 1263a8779fbSJames Wright // 1273a8779fbSJames Wright // Stabilization: 1283a8779fbSJames Wright // Tau = diag(TauC, TauM, TauM, TauM, TauE) 1293a8779fbSJames Wright // f1 = rho sqrt(ui uj gij) 1303a8779fbSJames Wright // gij = dXi/dX * dXi/dX 1313a8779fbSJames Wright // TauC = Cc f1 / (8 gii) 1323a8779fbSJames Wright // TauM = min( 1 , 1 / f1 ) 1333a8779fbSJames Wright // TauE = TauM / (Ce cv) 1343a8779fbSJames Wright // 1353a8779fbSJames Wright // SU = Galerkin + grad(v) . ( Ai^T * Tau * (Aj q,j) ) 1363a8779fbSJames Wright // 1373a8779fbSJames Wright // Constants: 1383a8779fbSJames Wright // lambda = - 2 / 3, From Stokes hypothesis 1393a8779fbSJames Wright // mu , Dynamic viscosity 1403a8779fbSJames Wright // k , Thermal conductivity 1413a8779fbSJames Wright // cv , Specific heat, constant volume 1423a8779fbSJames Wright // cp , Specific heat, constant pressure 1433a8779fbSJames Wright // g , Gravity 1443a8779fbSJames Wright // gamma = cp / cv, Specific heat ratio 1453a8779fbSJames Wright // 1463a8779fbSJames Wright // We require the product of the inverse of the Jacobian (dXdx_j,k) and 1473a8779fbSJames Wright // its transpose (dXdx_k,j) to properly compute integrals of the form: 1483a8779fbSJames Wright // int( gradv gradu ) 1493a8779fbSJames Wright // 1503a8779fbSJames Wright // ***************************************************************************** 151c1a52365SJed Brown CEED_QFUNCTION(RHSFunction_Newtonian)(void *ctx, CeedInt Q, 1523a8779fbSJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 1533a8779fbSJames Wright // *INDENT-OFF* 1543a8779fbSJames Wright // Inputs 1553a8779fbSJames Wright const CeedScalar (*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 156752f40e3SJed Brown (*Grad_q)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 1573a8779fbSJames Wright (*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 1583a8779fbSJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; 1593a8779fbSJames Wright // Outputs 1603a8779fbSJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], 161752f40e3SJed Brown (*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 1623a8779fbSJames Wright // *INDENT-ON* 1633a8779fbSJames Wright 1643a8779fbSJames Wright // Context 1653a8779fbSJames Wright NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 166bb8a0c61SJames Wright const CeedScalar *g = context->g; 167bb8a0c61SJames Wright const CeedScalar dt = context->dt; 1683a8779fbSJames Wright 1693a8779fbSJames Wright CeedPragmaSIMD 1703a8779fbSJames Wright // Quadrature Point Loop 1713a8779fbSJames Wright for (CeedInt i=0; i<Q; i++) { 172c1a52365SJed Brown CeedScalar U[5]; 173c1a52365SJed Brown for (int j=0; j<5; j++) U[j] = q[j][i]; 174c1a52365SJed Brown const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 175c1a52365SJed Brown State s = StateFromU(context, U, x_i); 176c1a52365SJed Brown 1773a8779fbSJames Wright // -- Interp-to-Interp q_data 1783a8779fbSJames Wright const CeedScalar wdetJ = q_data[0][i]; 1793a8779fbSJames Wright // -- Interp-to-Grad q_data 1803a8779fbSJames Wright // ---- Inverse of change of coordinate matrix: X_i,j 1813a8779fbSJames Wright // *INDENT-OFF* 18234ea8d65SJames Wright const CeedScalar dXdx[3][3] = {{q_data[1][i], q_data[2][i], q_data[3][i]}, 18334ea8d65SJames Wright {q_data[4][i], q_data[5][i], q_data[6][i]}, 18434ea8d65SJames Wright {q_data[7][i], q_data[8][i], q_data[9][i]} 1853a8779fbSJames Wright }; 1863a8779fbSJames Wright // *INDENT-ON* 187c1a52365SJed Brown State grad_s[3]; 188eef2387dSJed Brown for (CeedInt j=0; j<3; j++) { 1892f7ce6c1SJed Brown CeedScalar dx_i[3] = {0}, dU[5]; 1902556a851SJed Brown for (CeedInt k=0; k<5; k++) 1912556a851SJed Brown dU[k] = Grad_q[0][k][i] * dXdx[0][j] + 1922556a851SJed Brown Grad_q[1][k][i] * dXdx[1][j] + 1932556a851SJed Brown Grad_q[2][k][i] * dXdx[2][j]; 194c1a52365SJed Brown dx_i[j] = 1.; 1952f7ce6c1SJed Brown grad_s[j] = StateFromU_fwd(context, s, dU, x_i, dx_i); 196c1a52365SJed Brown } 197c1a52365SJed Brown 198c1a52365SJed Brown CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 199c1a52365SJed Brown KMStrainRate(grad_s, strain_rate); 200c1a52365SJed Brown NewtonianStress(context, strain_rate, kmstress); 201c1a52365SJed Brown KMUnpack(kmstress, stress); 202c1a52365SJed Brown ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 203c1a52365SJed Brown 204c1a52365SJed Brown StateConservative F_inviscid[3]; 205c1a52365SJed Brown FluxInviscid(context, s, F_inviscid); 206c1a52365SJed Brown 207c1a52365SJed Brown // Total flux 208c1a52365SJed Brown CeedScalar Flux[5][3]; 209d1b9ef12SLeila Ghaffari FluxTotal(F_inviscid, stress, Fe, Flux); 210c1a52365SJed Brown 211d1b9ef12SLeila Ghaffari for (CeedInt j=0; j<3; j++) 212d1b9ef12SLeila Ghaffari for (CeedInt k=0; k<5; k++) 213752f40e3SJed Brown Grad_v[j][k][i] = wdetJ * (dXdx[j][0] * Flux[k][0] + 214c1a52365SJed Brown dXdx[j][1] * Flux[k][1] + 215c1a52365SJed Brown dXdx[j][2] * Flux[k][2]); 216c1a52365SJed Brown 217c1a52365SJed Brown const CeedScalar body_force[5] = {0, s.U.density *g[0], s.U.density *g[1], s.U.density *g[2], 0}; 218c1a52365SJed Brown for (int j=0; j<5; j++) 219c1a52365SJed Brown v[j][i] = wdetJ * body_force[j]; 2203a8779fbSJames Wright 221d1b9ef12SLeila Ghaffari // -- Stabilization method: none (Galerkin), SU, or SUPG 222d1b9ef12SLeila Ghaffari CeedScalar Tau_d[3], stab[5][3], U_dot[5] = {0}; 223d1b9ef12SLeila Ghaffari Tau_diagPrim(context, s, dXdx, dt, Tau_d); 224d1b9ef12SLeila Ghaffari Stabilization(context, s, Tau_d, grad_s, U_dot, body_force, x_i, stab); 2253a8779fbSJames Wright 226493642f1SJames Wright for (CeedInt j=0; j<5; j++) 227493642f1SJames Wright for (CeedInt k=0; k<3; k++) 228752f40e3SJed Brown Grad_v[k][j][i] -= wdetJ*(stab[j][0] * dXdx[k][0] + 2293a8779fbSJames Wright stab[j][1] * dXdx[k][1] + 2303a8779fbSJames Wright stab[j][2] * dXdx[k][2]); 2313a8779fbSJames Wright 2323a8779fbSJames Wright } // End Quadrature Point Loop 2333a8779fbSJames Wright 2343a8779fbSJames Wright // Return 2353a8779fbSJames Wright return 0; 2363a8779fbSJames Wright } 2373a8779fbSJames Wright 2383a8779fbSJames Wright // ***************************************************************************** 2393a8779fbSJames Wright // This QFunction implements the Navier-Stokes equations (mentioned above) with 2403a8779fbSJames Wright // implicit time stepping method 2413a8779fbSJames Wright // 2423a8779fbSJames Wright // SU = Galerkin + grad(v) . ( Ai^T * Tau * (Aj q,j) ) 2433a8779fbSJames Wright // SUPG = Galerkin + grad(v) . ( Ai^T * Tau * (q_dot + Aj q,j - body force) ) 2443a8779fbSJames Wright // (diffussive terms will be added later) 2453a8779fbSJames Wright // 2463a8779fbSJames Wright // ***************************************************************************** 247*76555becSJames Wright CEED_QFUNCTION_HELPER int IFunction_Newtonian(void *ctx, CeedInt Q, 248*76555becSJames Wright const CeedScalar *const *in, CeedScalar *const *out, 249*76555becSJames Wright StateFromQi_t StateFromQi, StateFromQi_fwd_t StateFromQi_fwd) { 2503a8779fbSJames Wright // *INDENT-OFF* 2513a8779fbSJames Wright // Inputs 2523a8779fbSJames Wright const CeedScalar (*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 253752f40e3SJed Brown (*Grad_q)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 2543a8779fbSJames Wright (*q_dot)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 2553a8779fbSJames Wright (*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 2563a8779fbSJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 2573a8779fbSJames Wright // Outputs 2583a8779fbSJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], 259752f40e3SJed Brown (*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1], 260752f40e3SJed Brown (*jac_data)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[2]; 2613a8779fbSJames Wright // *INDENT-ON* 2623a8779fbSJames Wright // Context 2633a8779fbSJames Wright NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 264bb8a0c61SJames Wright const CeedScalar *g = context->g; 265bb8a0c61SJames Wright const CeedScalar dt = context->dt; 2663a8779fbSJames Wright 2673a8779fbSJames Wright CeedPragmaSIMD 2683a8779fbSJames Wright // Quadrature Point Loop 2693a8779fbSJames Wright for (CeedInt i=0; i<Q; i++) { 270*76555becSJames Wright CeedScalar qi[5]; 271*76555becSJames Wright for (CeedInt j=0; j<5; j++) qi[j] = q[j][i]; 272c1a52365SJed Brown const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 273*76555becSJames Wright State s = StateFromQi(context, qi, x_i); 274c1a52365SJed Brown 2753a8779fbSJames Wright // -- Interp-to-Interp q_data 2763a8779fbSJames Wright const CeedScalar wdetJ = q_data[0][i]; 2773a8779fbSJames Wright // -- Interp-to-Grad q_data 2783a8779fbSJames Wright // ---- Inverse of change of coordinate matrix: X_i,j 2793a8779fbSJames Wright // *INDENT-OFF* 28034ea8d65SJames Wright const CeedScalar dXdx[3][3] = {{q_data[1][i], q_data[2][i], q_data[3][i]}, 28134ea8d65SJames Wright {q_data[4][i], q_data[5][i], q_data[6][i]}, 28234ea8d65SJames Wright {q_data[7][i], q_data[8][i], q_data[9][i]} 2833a8779fbSJames Wright }; 2843a8779fbSJames Wright // *INDENT-ON* 285c1a52365SJed Brown State grad_s[3]; 286493642f1SJames Wright for (CeedInt j=0; j<3; j++) { 287*76555becSJames Wright CeedScalar dx_i[3] = {0}, dqi[5]; 2882556a851SJed Brown for (CeedInt k=0; k<5; k++) 289*76555becSJames Wright dqi[k] = Grad_q[0][k][i] * dXdx[0][j] + 2902556a851SJed Brown Grad_q[1][k][i] * dXdx[1][j] + 2912556a851SJed Brown Grad_q[2][k][i] * dXdx[2][j]; 292c1a52365SJed Brown dx_i[j] = 1.; 293*76555becSJames Wright grad_s[j] = StateFromQi_fwd(context, s, dqi, x_i, dx_i); 2943a8779fbSJames Wright } 295c1a52365SJed Brown 296c1a52365SJed Brown CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 297c1a52365SJed Brown KMStrainRate(grad_s, strain_rate); 298c1a52365SJed Brown NewtonianStress(context, strain_rate, kmstress); 299c1a52365SJed Brown KMUnpack(kmstress, stress); 300c1a52365SJed Brown ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 301c1a52365SJed Brown 302c1a52365SJed Brown StateConservative F_inviscid[3]; 303c1a52365SJed Brown FluxInviscid(context, s, F_inviscid); 304c1a52365SJed Brown 305c1a52365SJed Brown // Total flux 306c1a52365SJed Brown CeedScalar Flux[5][3]; 307d1b9ef12SLeila Ghaffari FluxTotal(F_inviscid, stress, Fe, Flux); 308c1a52365SJed Brown 309d1b9ef12SLeila Ghaffari for (CeedInt j=0; j<3; j++) 310d1b9ef12SLeila Ghaffari for (CeedInt k=0; k<5; k++) 311752f40e3SJed Brown Grad_v[j][k][i] = -wdetJ * (dXdx[j][0] * Flux[k][0] + 312c1a52365SJed Brown dXdx[j][1] * Flux[k][1] + 313c1a52365SJed Brown dXdx[j][2] * Flux[k][2]); 314c1a52365SJed Brown 315c1a52365SJed Brown const CeedScalar body_force[5] = {0, s.U.density *g[0], s.U.density *g[1], s.U.density *g[2], 0}; 3163a8779fbSJames Wright 317d1b9ef12SLeila Ghaffari // -- Stabilization method: none (Galerkin), SU, or SUPG 318*76555becSJames Wright CeedScalar Tau_d[3], stab[5][3], U_dot[5] = {0}, qi_dot[5], dx0[3] = {0}; 319*76555becSJames Wright for (int j=0; j<5; j++) qi_dot[j] = q_dot[j][i]; 320*76555becSJames Wright State s_dot = StateFromQi_fwd(context, s, qi_dot, x_i, dx0); 321*76555becSJames Wright UnpackState_U(s_dot.U, U_dot); 322*76555becSJames Wright 323*76555becSJames Wright for (CeedInt j=0; j<5; j++) 324*76555becSJames Wright v[j][i] = wdetJ * (U_dot[j] - body_force[j]); 325d1b9ef12SLeila Ghaffari Tau_diagPrim(context, s, dXdx, dt, Tau_d); 326d1b9ef12SLeila Ghaffari Stabilization(context, s, Tau_d, grad_s, U_dot, body_force, x_i, stab); 3273a8779fbSJames Wright 328493642f1SJames Wright for (CeedInt j=0; j<5; j++) 329493642f1SJames Wright for (CeedInt k=0; k<3; k++) 330752f40e3SJed Brown Grad_v[k][j][i] += wdetJ*(stab[j][0] * dXdx[k][0] + 3313a8779fbSJames Wright stab[j][1] * dXdx[k][1] + 3323a8779fbSJames Wright stab[j][2] * dXdx[k][2]); 333eef2387dSJed Brown 334*76555becSJames Wright for (CeedInt j=0; j<5; j++) jac_data[j][i] = qi[j]; 335eef2387dSJed Brown for (CeedInt j=0; j<6; j++) jac_data[5+j][i] = kmstress[j]; 336eef2387dSJed Brown for (CeedInt j=0; j<3; j++) jac_data[5+6+j][i] = Tau_d[j]; 3373a8779fbSJames Wright 3383a8779fbSJames Wright } // End Quadrature Point Loop 3393a8779fbSJames Wright 3403a8779fbSJames Wright // Return 3413a8779fbSJames Wright return 0; 3423a8779fbSJames Wright } 343f0b65372SJed Brown 344*76555becSJames Wright CEED_QFUNCTION(IFunction_Newtonian_Conserv)(void *ctx, CeedInt Q, 345*76555becSJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 346*76555becSJames Wright return IFunction_Newtonian(ctx, Q, in, out, StateFromU, StateFromU_fwd); 347*76555becSJames Wright } 348*76555becSJames Wright 349*76555becSJames Wright CEED_QFUNCTION(IFunction_Newtonian_Prim)(void *ctx, CeedInt Q, 350*76555becSJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 351*76555becSJames Wright return IFunction_Newtonian(ctx, Q, in, out, StateFromY, StateFromY_fwd); 352*76555becSJames Wright } 353*76555becSJames Wright 354cbe60e31SLeila Ghaffari // ***************************************************************************** 355*76555becSJames Wright // This QFunction implements the jacobian of the Navier-Stokes equations 356cbe60e31SLeila Ghaffari // for implicit time stepping method. 357cbe60e31SLeila Ghaffari // ***************************************************************************** 358*76555becSJames Wright CEED_QFUNCTION_HELPER int IJacobian_Newtonian(void *ctx, CeedInt Q, 359*76555becSJames Wright const CeedScalar *const *in, CeedScalar *const *out, 360*76555becSJames Wright StateFromQi_t StateFromQi, StateFromQi_fwd_t StateFromQi_fwd) { 361f0b65372SJed Brown // *INDENT-OFF* 362f0b65372SJed Brown // Inputs 363f0b65372SJed Brown const CeedScalar (*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 364f0b65372SJed Brown (*Grad_dq)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 365f0b65372SJed Brown (*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 366f0b65372SJed Brown (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 367f0b65372SJed Brown (*jac_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 368f0b65372SJed Brown // Outputs 369f0b65372SJed Brown CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], 370f0b65372SJed Brown (*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 371f0b65372SJed Brown // *INDENT-ON* 372f0b65372SJed Brown // Context 373f0b65372SJed Brown NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 374f0b65372SJed Brown const CeedScalar *g = context->g; 375f0b65372SJed Brown 376f0b65372SJed Brown CeedPragmaSIMD 377f0b65372SJed Brown // Quadrature Point Loop 378f0b65372SJed Brown for (CeedInt i=0; i<Q; i++) { 379f0b65372SJed Brown // -- Interp-to-Interp q_data 380f0b65372SJed Brown const CeedScalar wdetJ = q_data[0][i]; 381f0b65372SJed Brown // -- Interp-to-Grad q_data 382f0b65372SJed Brown // ---- Inverse of change of coordinate matrix: X_i,j 383f0b65372SJed Brown // *INDENT-OFF* 38434ea8d65SJames Wright const CeedScalar dXdx[3][3] = {{q_data[1][i], q_data[2][i], q_data[3][i]}, 38534ea8d65SJames Wright {q_data[4][i], q_data[5][i], q_data[6][i]}, 38634ea8d65SJames Wright {q_data[7][i], q_data[8][i], q_data[9][i]} 387f0b65372SJed Brown }; 388f0b65372SJed Brown // *INDENT-ON* 389f0b65372SJed Brown 390*76555becSJames Wright CeedScalar qi[5], kmstress[6], Tau_d[3] __attribute((unused)); 391*76555becSJames Wright for (int j=0; j<5; j++) qi[j] = jac_data[j][i]; 392f0b65372SJed Brown for (int j=0; j<6; j++) kmstress[j] = jac_data[5+j][i]; 393f0b65372SJed Brown for (int j=0; j<3; j++) Tau_d[j] = jac_data[5+6+j][i]; 394f0b65372SJed Brown const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 395*76555becSJames Wright State s = StateFromQi(context, qi, x_i); 396f0b65372SJed Brown 397*76555becSJames Wright CeedScalar dqi[5], dx0[3] = {0}; 398*76555becSJames Wright for (int j=0; j<5; j++) dqi[j] = dq[j][i]; 399*76555becSJames Wright State ds = StateFromQi_fwd(context, s, dqi, x_i, dx0); 400f0b65372SJed Brown 401f0b65372SJed Brown State grad_ds[3]; 402f0b65372SJed Brown for (int j=0; j<3; j++) { 403*76555becSJames Wright CeedScalar dqi_j[5]; 404d1b9ef12SLeila Ghaffari for (int k=0; k<5; k++) 405*76555becSJames Wright dqi_j[k] = Grad_dq[0][k][i] * dXdx[0][j] + 406d1b9ef12SLeila Ghaffari Grad_dq[1][k][i] * dXdx[1][j] + 407d1b9ef12SLeila Ghaffari Grad_dq[2][k][i] * dXdx[2][j]; 408*76555becSJames Wright grad_ds[j] = StateFromQi_fwd(context, s, dqi_j, x_i, dx0); 409f0b65372SJed Brown } 410f0b65372SJed Brown 411f0b65372SJed Brown CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 412f0b65372SJed Brown KMStrainRate(grad_ds, dstrain_rate); 413f0b65372SJed Brown NewtonianStress(context, dstrain_rate, dkmstress); 414f0b65372SJed Brown KMUnpack(dkmstress, dstress); 415f0b65372SJed Brown KMUnpack(kmstress, stress); 416f0b65372SJed Brown ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 417f0b65372SJed Brown 418f0b65372SJed Brown StateConservative dF_inviscid[3]; 419f0b65372SJed Brown FluxInviscid_fwd(context, s, ds, dF_inviscid); 420f0b65372SJed Brown 421f0b65372SJed Brown // Total flux 422f0b65372SJed Brown CeedScalar dFlux[5][3]; 423d1b9ef12SLeila Ghaffari FluxTotal(dF_inviscid, dstress, dFe, dFlux); 424f0b65372SJed Brown 425d1b9ef12SLeila Ghaffari for (int j=0; j<3; j++) 426d1b9ef12SLeila Ghaffari for (int k=0; k<5; k++) 427f0b65372SJed Brown Grad_v[j][k][i] = -wdetJ * (dXdx[j][0] * dFlux[k][0] + 428f0b65372SJed Brown dXdx[j][1] * dFlux[k][1] + 429f0b65372SJed Brown dXdx[j][2] * dFlux[k][2]); 430f0b65372SJed Brown 431f0b65372SJed Brown const CeedScalar dbody_force[5] = {0, ds.U.density *g[0], ds.U.density *g[1], ds.U.density *g[2], 0}; 432*76555becSJames Wright CeedScalar dU[5] = {0.}; 433*76555becSJames Wright UnpackState_U(ds.U, dU); 434f0b65372SJed Brown for (int j=0; j<5; j++) 435f0b65372SJed Brown v[j][i] = wdetJ * (context->ijacobian_time_shift * dU[j] - dbody_force[j]); 436f0b65372SJed Brown 437d1b9ef12SLeila Ghaffari // -- Stabilization method: none (Galerkin), SU, or SUPG 438d1b9ef12SLeila Ghaffari CeedScalar dstab[5][3], U_dot[5] = {0}; 439d1b9ef12SLeila Ghaffari for (CeedInt j=0; j<5; j++) U_dot[j] = context->ijacobian_time_shift * dU[j]; 440d1b9ef12SLeila Ghaffari Stabilization(context, s, Tau_d, grad_ds, U_dot, dbody_force, x_i, dstab); 441d1b9ef12SLeila Ghaffari 442f0b65372SJed Brown for (int j=0; j<5; j++) 443f0b65372SJed Brown for (int k=0; k<3; k++) 444f0b65372SJed Brown Grad_v[k][j][i] += wdetJ*(dstab[j][0] * dXdx[k][0] + 445f0b65372SJed Brown dstab[j][1] * dXdx[k][1] + 446f0b65372SJed Brown dstab[j][2] * dXdx[k][2]); 447f0b65372SJed Brown 448f0b65372SJed Brown } // End Quadrature Point Loop 449f0b65372SJed Brown return 0; 450f0b65372SJed Brown } 4518085925cSJames Wright 452*76555becSJames Wright CEED_QFUNCTION(IJacobian_Newtonian_Conserv)(void *ctx, CeedInt Q, 453*76555becSJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 454*76555becSJames Wright return IJacobian_Newtonian(ctx, Q, in, out, StateFromU, StateFromU_fwd); 455*76555becSJames Wright } 456*76555becSJames Wright 457*76555becSJames Wright CEED_QFUNCTION(IJacobian_Newtonian_Prim)(void *ctx, CeedInt Q, 458*76555becSJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 459*76555becSJames Wright return IJacobian_Newtonian(ctx, Q, in, out, StateFromY, StateFromY_fwd); 460*76555becSJames Wright } 461*76555becSJames Wright 462d1b9ef12SLeila Ghaffari // ***************************************************************************** 4638085925cSJames Wright // Compute boundary integral (ie. for strongly set inflows) 464d1b9ef12SLeila Ghaffari // ***************************************************************************** 465d4559bbeSJames Wright CEED_QFUNCTION_HELPER int BoundaryIntegral(void *ctx, CeedInt Q, 466d4559bbeSJames Wright const CeedScalar *const *in, CeedScalar *const *out, 467d4559bbeSJames Wright StateFromQi_t StateFromQi, StateFromQi_fwd_t StateFromQi_fwd) { 4688085925cSJames Wright 4698085925cSJames Wright //*INDENT-OFF* 4708085925cSJames Wright const CeedScalar (*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 471d3b25f3aSJames Wright (*Grad_q)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 472d3b25f3aSJames Wright (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 473d3b25f3aSJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; 4748085925cSJames Wright 47568ae065aSJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA]) out[0], 47668ae065aSJames Wright (*jac_data_sur)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA]) out[1]; 4778085925cSJames Wright 4788085925cSJames Wright //*INDENT-ON* 4798085925cSJames Wright 480d3b25f3aSJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext) ctx; 481d3b25f3aSJames Wright const bool is_implicit = context->is_implicit; 4828085925cSJames Wright 4838085925cSJames Wright CeedPragmaSIMD 4848085925cSJames Wright for(CeedInt i=0; i<Q; i++) { 485d3b25f3aSJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 48641e73928SJames Wright const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 48741e73928SJames Wright State s = StateFromQi(context, qi, x_i); 4888085925cSJames Wright 4898085925cSJames Wright const CeedScalar wdetJb = (is_implicit ? -1. : 1.) * q_data_sur[0][i]; 490c5740391SJames Wright // ---- Normal vector 4918085925cSJames Wright const CeedScalar norm[3] = {q_data_sur[1][i], 4928085925cSJames Wright q_data_sur[2][i], 4938085925cSJames Wright q_data_sur[3][i] 4948085925cSJames Wright }; 4958085925cSJames Wright 496d3b25f3aSJames Wright const CeedScalar dXdx[2][3] = { 497d3b25f3aSJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 498d3b25f3aSJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 499d3b25f3aSJames Wright }; 5008085925cSJames Wright 501d3b25f3aSJames Wright State grad_s[3]; 502d3b25f3aSJames Wright for (CeedInt j=0; j<3; j++) { 50341e73928SJames Wright CeedScalar dx_i[3] = {0}, dqi[5]; 504d3b25f3aSJames Wright for (CeedInt k=0; k<5; k++) 50541e73928SJames Wright dqi[k] = Grad_q[0][k][i] * dXdx[0][j] + 506d3b25f3aSJames Wright Grad_q[1][k][i] * dXdx[1][j]; 507d3b25f3aSJames Wright dx_i[j] = 1.; 50841e73928SJames Wright grad_s[j] = StateFromQi_fwd(context, s, dqi, x_i, dx_i); 509d3b25f3aSJames Wright } 5108085925cSJames Wright 511d3b25f3aSJames Wright CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 512d3b25f3aSJames Wright KMStrainRate(grad_s, strain_rate); 513d3b25f3aSJames Wright NewtonianStress(context, strain_rate, kmstress); 514d3b25f3aSJames Wright KMUnpack(kmstress, stress); 515d3b25f3aSJames Wright ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 516d3b25f3aSJames Wright 517d3b25f3aSJames Wright StateConservative F_inviscid[3]; 518d3b25f3aSJames Wright FluxInviscid(context, s, F_inviscid); 519d3b25f3aSJames Wright 520c5740391SJames Wright CeedScalar Flux[5]; 521c5740391SJames Wright FluxTotal_Boundary(F_inviscid, stress, Fe, norm, Flux); 522d3b25f3aSJames Wright 523c5740391SJames Wright for (CeedInt j=0; j<5; j++) v[j][i] = -wdetJb * Flux[j]; 5248085925cSJames Wright 525c5740391SJames Wright for (int j=0; j<5; j++) jac_data_sur[j][i] = qi[j]; 52668ae065aSJames Wright for (int j=0; j<6; j++) jac_data_sur[5+j][i] = kmstress[j]; 5278085925cSJames Wright } 5288085925cSJames Wright return 0; 5298085925cSJames Wright } 5308085925cSJames Wright 531d4559bbeSJames Wright CEED_QFUNCTION(BoundaryIntegral_Conserv)(void *ctx, CeedInt Q, 532d4559bbeSJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 533d4559bbeSJames Wright return BoundaryIntegral(ctx, Q, in, out, StateFromU, StateFromU_fwd); 534d4559bbeSJames Wright } 535d4559bbeSJames Wright 536d4559bbeSJames Wright CEED_QFUNCTION(BoundaryIntegral_Prim)(void *ctx, CeedInt Q, 537d4559bbeSJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 538d4559bbeSJames Wright return BoundaryIntegral(ctx, Q, in, out, StateFromY, StateFromY_fwd); 539d4559bbeSJames Wright } 540d4559bbeSJames Wright 541d1b9ef12SLeila Ghaffari // ***************************************************************************** 54268ae065aSJames Wright // Jacobian for "set nothing" boundary integral 543d1b9ef12SLeila Ghaffari // ***************************************************************************** 544d4559bbeSJames Wright CEED_QFUNCTION_HELPER int BoundaryIntegral_Jacobian(void *ctx, CeedInt Q, 545d4559bbeSJames Wright const CeedScalar *const *in, CeedScalar *const *out, 546d4559bbeSJames Wright StateFromQi_t StateFromQi, StateFromQi_fwd_t StateFromQi_fwd) { 54768ae065aSJames Wright // *INDENT-OFF* 54868ae065aSJames Wright // Inputs 54968ae065aSJames Wright const CeedScalar (*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 55068ae065aSJames Wright (*Grad_dq)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 55168ae065aSJames Wright (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 55268ae065aSJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 55368ae065aSJames Wright (*jac_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 55468ae065aSJames Wright // Outputs 55568ae065aSJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 55668ae065aSJames Wright // *INDENT-ON* 55768ae065aSJames Wright 55868ae065aSJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 55968ae065aSJames Wright const bool implicit = context->is_implicit; 56068ae065aSJames Wright 56168ae065aSJames Wright CeedPragmaSIMD 56268ae065aSJames Wright // Quadrature Point Loop 56368ae065aSJames Wright for (CeedInt i=0; i<Q; i++) { 56468ae065aSJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 56568ae065aSJames Wright const CeedScalar wdetJb = (implicit ? -1. : 1.) * q_data_sur[0][i]; 56668ae065aSJames Wright const CeedScalar norm[3] = {q_data_sur[1][i], 56768ae065aSJames Wright q_data_sur[2][i], 56868ae065aSJames Wright q_data_sur[3][i] 56968ae065aSJames Wright }; 57068ae065aSJames Wright const CeedScalar dXdx[2][3] = { 57168ae065aSJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 57268ae065aSJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 57368ae065aSJames Wright }; 57468ae065aSJames Wright 57541e73928SJames Wright CeedScalar qi[5], kmstress[6], dqi[5], dx_i[3] = {0.}; 57641e73928SJames Wright for (int j=0; j<5; j++) qi[j] = jac_data_sur[j][i]; 57768ae065aSJames Wright for (int j=0; j<6; j++) kmstress[j] = jac_data_sur[5+j][i]; 57841e73928SJames Wright for (int j=0; j<5; j++) dqi[j] = dq[j][i]; 5793934e2b1SJames Wright 58041e73928SJames Wright State s = StateFromQi(context, qi, x_i); 58141e73928SJames Wright State ds = StateFromQi_fwd(context, s, dqi, x_i, dx_i); 58268ae065aSJames Wright 58368ae065aSJames Wright State grad_ds[3]; 58468ae065aSJames Wright for (CeedInt j=0; j<3; j++) { 58541e73928SJames Wright CeedScalar dx_i[3] = {0}, dqi_j[5]; 58668ae065aSJames Wright for (CeedInt k=0; k<5; k++) 58741e73928SJames Wright dqi_j[k] = Grad_dq[0][k][i] * dXdx[0][j] + 58868ae065aSJames Wright Grad_dq[1][k][i] * dXdx[1][j]; 58968ae065aSJames Wright dx_i[j] = 1.; 59041e73928SJames Wright grad_ds[j] = StateFromQi_fwd(context, s, dqi_j, x_i, dx_i); 59168ae065aSJames Wright } 59268ae065aSJames Wright 59368ae065aSJames Wright CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 59468ae065aSJames Wright KMStrainRate(grad_ds, dstrain_rate); 59568ae065aSJames Wright NewtonianStress(context, dstrain_rate, dkmstress); 59668ae065aSJames Wright KMUnpack(dkmstress, dstress); 59768ae065aSJames Wright KMUnpack(kmstress, stress); 59868ae065aSJames Wright ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 59968ae065aSJames Wright 60068ae065aSJames Wright StateConservative dF_inviscid[3]; 60168ae065aSJames Wright FluxInviscid_fwd(context, s, ds, dF_inviscid); 60268ae065aSJames Wright 603c5740391SJames Wright CeedScalar dFlux[5]; 604c5740391SJames Wright FluxTotal_Boundary(dF_inviscid, dstress, dFe, norm, dFlux); 60568ae065aSJames Wright 606c5740391SJames Wright for (int j=0; j<5; j++) v[j][i] = -wdetJb * dFlux[j]; 60768ae065aSJames Wright } // End Quadrature Point Loop 60868ae065aSJames Wright return 0; 60968ae065aSJames Wright } 61068ae065aSJames Wright 611d4559bbeSJames Wright CEED_QFUNCTION(BoundaryIntegral_Jacobian_Conserv)(void *ctx, CeedInt Q, 612d4559bbeSJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 613d4559bbeSJames Wright return BoundaryIntegral_Jacobian(ctx, Q, in, out, StateFromU, StateFromU_fwd); 614d4559bbeSJames Wright } 615d4559bbeSJames Wright 616d4559bbeSJames Wright CEED_QFUNCTION(BoundaryIntegral_Jacobian_Prim)(void *ctx, CeedInt Q, 617d4559bbeSJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 618d4559bbeSJames Wright return BoundaryIntegral_Jacobian(ctx, Q, in, out, StateFromY, StateFromY_fwd); 619d4559bbeSJames Wright } 620d4559bbeSJames Wright 621d1b9ef12SLeila Ghaffari // ***************************************************************************** 62204b9037bSJames Wright // Outflow boundary condition, weakly setting a constant pressure 623d1b9ef12SLeila Ghaffari // ***************************************************************************** 624d4559bbeSJames Wright CEED_QFUNCTION_HELPER int PressureOutflow(void *ctx, CeedInt Q, 625d4559bbeSJames Wright const CeedScalar *const *in, CeedScalar *const *out, 626d4559bbeSJames Wright StateFromQi_t StateFromQi, StateFromQi_fwd_t StateFromQi_fwd) { 62704b9037bSJames Wright // *INDENT-OFF* 62804b9037bSJames Wright // Inputs 62904b9037bSJames Wright const CeedScalar (*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 63025bfcc41SJames Wright (*Grad_q)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 63125bfcc41SJames Wright (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 63225bfcc41SJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; 63304b9037bSJames Wright // Outputs 63404b9037bSJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], 63504b9037bSJames Wright (*jac_data_sur)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[1]; 63604b9037bSJames Wright // *INDENT-ON* 63704b9037bSJames Wright 63804b9037bSJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 63904b9037bSJames Wright const bool implicit = context->is_implicit; 64004b9037bSJames Wright const CeedScalar P0 = context->P0; 64104b9037bSJames Wright 64204b9037bSJames Wright CeedPragmaSIMD 64304b9037bSJames Wright // Quadrature Point Loop 64404b9037bSJames Wright for (CeedInt i=0; i<Q; i++) { 64504b9037bSJames Wright // Setup 64604b9037bSJames Wright // -- Interp in 64725bfcc41SJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 64841e73928SJames Wright const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 64941e73928SJames Wright State s = StateFromQi(context, qi, x_i); 65025bfcc41SJames Wright s.Y.pressure = P0; 65104b9037bSJames Wright 65204b9037bSJames Wright // -- Interp-to-Interp q_data 65304b9037bSJames Wright // For explicit mode, the surface integral is on the RHS of ODE q_dot = f(q). 65404b9037bSJames Wright // For implicit mode, it gets pulled to the LHS of implicit ODE/DAE g(q_dot, q). 65504b9037bSJames Wright // We can effect this by swapping the sign on this weight 65604b9037bSJames Wright const CeedScalar wdetJb = (implicit ? -1. : 1.) * q_data_sur[0][i]; 65704b9037bSJames Wright 658c5740391SJames Wright // ---- Normal vector 659d4559bbeSJames Wright const CeedScalar norm[3] = {q_data_sur[1][i], q_data_sur[2][i], q_data_sur[3][i]}; 66004b9037bSJames Wright 66125bfcc41SJames Wright const CeedScalar dXdx[2][3] = { 66225bfcc41SJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 66325bfcc41SJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 66425bfcc41SJames Wright }; 66504b9037bSJames Wright 66625bfcc41SJames Wright State grad_s[3]; 66725bfcc41SJames Wright for (CeedInt j=0; j<3; j++) { 66841e73928SJames Wright CeedScalar dx_i[3] = {0}, dqi[5]; 66925bfcc41SJames Wright for (CeedInt k=0; k<5; k++) 67041e73928SJames Wright dqi[k] = Grad_q[0][k][i] * dXdx[0][j] + 67125bfcc41SJames Wright Grad_q[1][k][i] * dXdx[1][j]; 67225bfcc41SJames Wright dx_i[j] = 1.; 67341e73928SJames Wright grad_s[j] = StateFromQi_fwd(context, s, dqi, x_i, dx_i); 67425bfcc41SJames Wright } 67525bfcc41SJames Wright 67625bfcc41SJames Wright CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 67725bfcc41SJames Wright KMStrainRate(grad_s, strain_rate); 67825bfcc41SJames Wright NewtonianStress(context, strain_rate, kmstress); 67925bfcc41SJames Wright KMUnpack(kmstress, stress); 68025bfcc41SJames Wright ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 68125bfcc41SJames Wright 68225bfcc41SJames Wright StateConservative F_inviscid[3]; 68325bfcc41SJames Wright FluxInviscid(context, s, F_inviscid); 68425bfcc41SJames Wright 685c5740391SJames Wright CeedScalar Flux[5]; 686c5740391SJames Wright FluxTotal_Boundary(F_inviscid, stress, Fe, norm, Flux); 68704b9037bSJames Wright 688c5740391SJames Wright for (CeedInt j=0; j<5; j++) v[j][i] = -wdetJb * Flux[j]; 68904b9037bSJames Wright 69004b9037bSJames Wright // Save values for Jacobian 691c5740391SJames Wright for (int j=0; j<5; j++) jac_data_sur[j][i] = qi[j]; 692b01ba163SJames Wright for (int j=0; j<6; j++) jac_data_sur[5+j][i] = kmstress[j]; 69304b9037bSJames Wright } // End Quadrature Point Loop 69404b9037bSJames Wright return 0; 69504b9037bSJames Wright } 69604b9037bSJames Wright 697d4559bbeSJames Wright CEED_QFUNCTION(PressureOutflow_Conserv)(void *ctx, CeedInt Q, 698d4559bbeSJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 699d4559bbeSJames Wright return PressureOutflow(ctx, Q, in, out, StateFromU, StateFromU_fwd); 700d4559bbeSJames Wright } 701d4559bbeSJames Wright 702d4559bbeSJames Wright CEED_QFUNCTION(PressureOutflow_Prim)(void *ctx, CeedInt Q, 703d4559bbeSJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 704d4559bbeSJames Wright return PressureOutflow(ctx, Q, in, out, StateFromY, StateFromY_fwd); 705d4559bbeSJames Wright } 706d4559bbeSJames Wright 707d1b9ef12SLeila Ghaffari // ***************************************************************************** 70804b9037bSJames Wright // Jacobian for weak-pressure outflow boundary condition 709d1b9ef12SLeila Ghaffari // ***************************************************************************** 710d4559bbeSJames Wright CEED_QFUNCTION_HELPER int PressureOutflow_Jacobian(void *ctx, CeedInt Q, 711d4559bbeSJames Wright const CeedScalar *const *in, CeedScalar *const *out, 712d4559bbeSJames Wright StateFromQi_t StateFromQi, StateFromQi_fwd_t StateFromQi_fwd) { 71304b9037bSJames Wright // *INDENT-OFF* 71404b9037bSJames Wright // Inputs 71504b9037bSJames Wright const CeedScalar (*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 716b01ba163SJames Wright (*Grad_dq)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 717b01ba163SJames Wright (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 718b01ba163SJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 719b01ba163SJames Wright (*jac_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 72004b9037bSJames Wright // Outputs 72104b9037bSJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 72204b9037bSJames Wright // *INDENT-ON* 72304b9037bSJames Wright 72404b9037bSJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 72504b9037bSJames Wright const bool implicit = context->is_implicit; 72604b9037bSJames Wright 72704b9037bSJames Wright CeedPragmaSIMD 72804b9037bSJames Wright // Quadrature Point Loop 72904b9037bSJames Wright for (CeedInt i=0; i<Q; i++) { 730b01ba163SJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 73104b9037bSJames Wright const CeedScalar wdetJb = (implicit ? -1. : 1.) * q_data_sur[0][i]; 732d4559bbeSJames Wright const CeedScalar norm[3] = {q_data_sur[1][i], q_data_sur[2][i], q_data_sur[3][i]}; 733b01ba163SJames Wright const CeedScalar dXdx[2][3] = { 734b01ba163SJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 735b01ba163SJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 736b01ba163SJames Wright }; 737b01ba163SJames Wright 73841e73928SJames Wright CeedScalar qi[5], kmstress[6], dqi[5], dx_i[3] = {0.}; 73941e73928SJames Wright for (int j=0; j<5; j++) qi[j] = jac_data_sur[j][i]; 740b01ba163SJames Wright for (int j=0; j<6; j++) kmstress[j] = jac_data_sur[5+j][i]; 74141e73928SJames Wright for (int j=0; j<5; j++) dqi[j] = dq[j][i]; 7423934e2b1SJames Wright 74341e73928SJames Wright State s = StateFromQi(context, qi, x_i); 74441e73928SJames Wright State ds = StateFromQi_fwd(context, s, dqi, x_i, dx_i); 745b01ba163SJames Wright s.Y.pressure = context->P0; 746b01ba163SJames Wright ds.Y.pressure = 0.; 747b01ba163SJames Wright 748b01ba163SJames Wright State grad_ds[3]; 749b01ba163SJames Wright for (CeedInt j=0; j<3; j++) { 75041e73928SJames Wright CeedScalar dx_i[3] = {0}, dqi_j[5]; 751b01ba163SJames Wright for (CeedInt k=0; k<5; k++) 75241e73928SJames Wright dqi_j[k] = Grad_dq[0][k][i] * dXdx[0][j] + 753b01ba163SJames Wright Grad_dq[1][k][i] * dXdx[1][j]; 754b01ba163SJames Wright dx_i[j] = 1.; 75541e73928SJames Wright grad_ds[j] = StateFromQi_fwd(context, s, dqi_j, x_i, dx_i); 756b01ba163SJames Wright } 757b01ba163SJames Wright 758b01ba163SJames Wright CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 759b01ba163SJames Wright KMStrainRate(grad_ds, dstrain_rate); 760b01ba163SJames Wright NewtonianStress(context, dstrain_rate, dkmstress); 761b01ba163SJames Wright KMUnpack(dkmstress, dstress); 762b01ba163SJames Wright KMUnpack(kmstress, stress); 763b01ba163SJames Wright ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 76404b9037bSJames Wright 765e6b47afbSJames Wright StateConservative dF_inviscid[3]; 766e6b47afbSJames Wright FluxInviscid_fwd(context, s, ds, dF_inviscid); 76704b9037bSJames Wright 768c5740391SJames Wright CeedScalar dFlux[5]; 769c5740391SJames Wright FluxTotal_Boundary(dF_inviscid, dstress, dFe, norm, dFlux); 770e6b47afbSJames Wright 771c5740391SJames Wright for (int j=0; j<5; j++) v[j][i] = -wdetJb * dFlux[j]; 77204b9037bSJames Wright } // End Quadrature Point Loop 77304b9037bSJames Wright return 0; 77404b9037bSJames Wright } 77504b9037bSJames Wright 776d4559bbeSJames Wright CEED_QFUNCTION(PressureOutflow_Jacobian_Conserv)(void *ctx, CeedInt Q, 777d4559bbeSJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 778d4559bbeSJames Wright return PressureOutflow_Jacobian(ctx, Q, in, out, StateFromU, StateFromU_fwd); 779d4559bbeSJames Wright } 780d4559bbeSJames Wright 781d4559bbeSJames Wright CEED_QFUNCTION(PressureOutflow_Jacobian_Prim)(void *ctx, CeedInt Q, 782d4559bbeSJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 783d4559bbeSJames Wright return PressureOutflow_Jacobian(ctx, Q, in, out, StateFromY, StateFromY_fwd); 784d4559bbeSJames Wright } 785d4559bbeSJames Wright 7863a8779fbSJames Wright #endif // newtonian_h 787