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> 17*7b530f2aSAdelekeBankole #include <stdlib.h> 18*7b530f2aSAdelekeBankole #include "ceed/types.h" 19475b2820SJames Wright #include "newtonian_state.h" 20d0cce58aSJeremy L Thompson #include "newtonian_types.h" 21d1b9ef12SLeila Ghaffari #include "stabilization.h" 22d0cce58aSJeremy L Thompson #include "utils.h" 23bb8a0c61SJames Wright 24bb8a0c61SJames Wright // ***************************************************************************** 253a8779fbSJames Wright // This QFunction sets a "still" initial condition for generic Newtonian IG problems 263a8779fbSJames Wright // ***************************************************************************** 273a8779fbSJames Wright CEED_QFUNCTION(ICsNewtonianIG)(void *ctx, CeedInt Q, 283a8779fbSJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 293a8779fbSJames Wright // Inputs 303a8779fbSJames Wright const CeedScalar (*X)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 313a8779fbSJames Wright 323a8779fbSJames Wright // Outputs 333a8779fbSJames Wright CeedScalar (*q0)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 343a8779fbSJames Wright 35bb8a0c61SJames Wright // Context 36bb8a0c61SJames Wright const SetupContext context = (SetupContext)ctx; 37bb8a0c61SJames Wright const CeedScalar theta0 = context->theta0; 38bb8a0c61SJames Wright const CeedScalar P0 = context->P0; 39bb8a0c61SJames Wright const CeedScalar cv = context->cv; 40bb8a0c61SJames Wright const CeedScalar cp = context->cp; 41bb8a0c61SJames Wright const CeedScalar *g = context->g; 42bb8a0c61SJames Wright const CeedScalar Rd = cp - cv; 43bb8a0c61SJames Wright 443a8779fbSJames Wright // Quadrature Point Loop 453a8779fbSJames Wright CeedPragmaSIMD 463a8779fbSJames Wright for (CeedInt i=0; i<Q; i++) { 473a8779fbSJames Wright CeedScalar q[5] = {0.}; 483a8779fbSJames Wright 493a8779fbSJames Wright // Setup 503a8779fbSJames Wright // -- Coordinates 51bb8a0c61SJames Wright const CeedScalar x[3] = {X[0][i], X[1][i], X[2][i]}; 52d1b9ef12SLeila Ghaffari const CeedScalar e_potential = -Dot3(g, x); 533a8779fbSJames Wright 543a8779fbSJames Wright // -- Density 55bb8a0c61SJames Wright const CeedScalar rho = P0 / (Rd*theta0); 563a8779fbSJames Wright 573a8779fbSJames Wright // Initial Conditions 583a8779fbSJames Wright q[0] = rho; 593a8779fbSJames Wright q[1] = 0.0; 603a8779fbSJames Wright q[2] = 0.0; 613a8779fbSJames Wright q[3] = 0.0; 62bb8a0c61SJames Wright q[4] = rho * (cv*theta0 + e_potential); 633a8779fbSJames Wright 643a8779fbSJames Wright for (CeedInt j=0; j<5; j++) 653a8779fbSJames Wright q0[j][i] = q[j]; 66d1b9ef12SLeila Ghaffari 673a8779fbSJames Wright } // End of Quadrature Point Loop 683a8779fbSJames Wright return 0; 693a8779fbSJames Wright } 703a8779fbSJames Wright 713a8779fbSJames Wright // ***************************************************************************** 72cbe60e31SLeila Ghaffari // This QFunction sets a "still" initial condition for generic Newtonian IG 73cbe60e31SLeila Ghaffari // problems in primitive variables 74cbe60e31SLeila Ghaffari // ***************************************************************************** 75cbe60e31SLeila Ghaffari CEED_QFUNCTION(ICsNewtonianIG_Prim)(void *ctx, CeedInt Q, 76cbe60e31SLeila Ghaffari const CeedScalar *const *in, CeedScalar *const *out) { 77cbe60e31SLeila Ghaffari // Outputs 78cbe60e31SLeila Ghaffari CeedScalar (*q0)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 79cbe60e31SLeila Ghaffari 80cbe60e31SLeila Ghaffari // Context 81cbe60e31SLeila Ghaffari const SetupContext context = (SetupContext)ctx; 82cbe60e31SLeila Ghaffari const CeedScalar theta0 = context->theta0; 83cbe60e31SLeila Ghaffari const CeedScalar P0 = context->P0; 84cbe60e31SLeila Ghaffari 85cbe60e31SLeila Ghaffari // Quadrature Point Loop 86cbe60e31SLeila Ghaffari CeedPragmaSIMD 87cbe60e31SLeila Ghaffari for (CeedInt i=0; i<Q; i++) { 88cbe60e31SLeila Ghaffari CeedScalar q[5] = {0.}; 89cbe60e31SLeila Ghaffari 90cbe60e31SLeila Ghaffari // Initial Conditions 91cbe60e31SLeila Ghaffari q[0] = P0; 92cbe60e31SLeila Ghaffari q[1] = 0.0; 93cbe60e31SLeila Ghaffari q[2] = 0.0; 94cbe60e31SLeila Ghaffari q[3] = 0.0; 95cbe60e31SLeila Ghaffari q[4] = theta0; 96cbe60e31SLeila Ghaffari 97cbe60e31SLeila Ghaffari for (CeedInt j=0; j<5; j++) 98cbe60e31SLeila Ghaffari q0[j][i] = q[j]; 99cbe60e31SLeila Ghaffari 100cbe60e31SLeila Ghaffari } // End of Quadrature Point Loop 101cbe60e31SLeila Ghaffari return 0; 102cbe60e31SLeila Ghaffari } 103cbe60e31SLeila Ghaffari 104cbe60e31SLeila Ghaffari // ***************************************************************************** 1053a8779fbSJames Wright // This QFunction implements the following formulation of Navier-Stokes with 1063a8779fbSJames Wright // explicit time stepping method 1073a8779fbSJames Wright // 1083a8779fbSJames Wright // This is 3D compressible Navier-Stokes in conservation form with state 1093a8779fbSJames Wright // variables of density, momentum density, and total energy density. 1103a8779fbSJames Wright // 1113a8779fbSJames Wright // State Variables: q = ( rho, U1, U2, U3, E ) 1123a8779fbSJames Wright // rho - Mass Density 1133a8779fbSJames Wright // Ui - Momentum Density, Ui = rho ui 1143a8779fbSJames Wright // E - Total Energy Density, E = rho (cv T + (u u)/2 + g z) 1153a8779fbSJames Wright // 1163a8779fbSJames Wright // Navier-Stokes Equations: 1173a8779fbSJames Wright // drho/dt + div( U ) = 0 1183a8779fbSJames Wright // dU/dt + div( rho (u x u) + P I3 ) + rho g khat = div( Fu ) 1193a8779fbSJames Wright // dE/dt + div( (E + P) u ) = div( Fe ) 1203a8779fbSJames Wright // 1213a8779fbSJames Wright // Viscous Stress: 1223a8779fbSJames Wright // Fu = mu (grad( u ) + grad( u )^T + lambda div ( u ) I3) 1233a8779fbSJames Wright // 1243a8779fbSJames Wright // Thermal Stress: 1253a8779fbSJames Wright // Fe = u Fu + k grad( T ) 126bb8a0c61SJames Wright // Equation of State 1273a8779fbSJames Wright // P = (gamma - 1) (E - rho (u u) / 2 - rho g z) 1283a8779fbSJames Wright // 1293a8779fbSJames Wright // Stabilization: 1303a8779fbSJames Wright // Tau = diag(TauC, TauM, TauM, TauM, TauE) 1313a8779fbSJames Wright // f1 = rho sqrt(ui uj gij) 1323a8779fbSJames Wright // gij = dXi/dX * dXi/dX 1333a8779fbSJames Wright // TauC = Cc f1 / (8 gii) 1343a8779fbSJames Wright // TauM = min( 1 , 1 / f1 ) 1353a8779fbSJames Wright // TauE = TauM / (Ce cv) 1363a8779fbSJames Wright // 1373a8779fbSJames Wright // SU = Galerkin + grad(v) . ( Ai^T * Tau * (Aj q,j) ) 1383a8779fbSJames Wright // 1393a8779fbSJames Wright // Constants: 1403a8779fbSJames Wright // lambda = - 2 / 3, From Stokes hypothesis 1413a8779fbSJames Wright // mu , Dynamic viscosity 1423a8779fbSJames Wright // k , Thermal conductivity 1433a8779fbSJames Wright // cv , Specific heat, constant volume 1443a8779fbSJames Wright // cp , Specific heat, constant pressure 1453a8779fbSJames Wright // g , Gravity 1463a8779fbSJames Wright // gamma = cp / cv, Specific heat ratio 1473a8779fbSJames Wright // 1483a8779fbSJames Wright // We require the product of the inverse of the Jacobian (dXdx_j,k) and 1493a8779fbSJames Wright // its transpose (dXdx_k,j) to properly compute integrals of the form: 1503a8779fbSJames Wright // int( gradv gradu ) 1513a8779fbSJames Wright // 1523a8779fbSJames Wright // ***************************************************************************** 153c1a52365SJed Brown CEED_QFUNCTION(RHSFunction_Newtonian)(void *ctx, CeedInt Q, 1543a8779fbSJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 1553a8779fbSJames Wright // *INDENT-OFF* 1563a8779fbSJames Wright // Inputs 1573a8779fbSJames Wright const CeedScalar (*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 158752f40e3SJed Brown (*Grad_q)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 1593a8779fbSJames Wright (*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 1603a8779fbSJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; 1613a8779fbSJames Wright // Outputs 1623a8779fbSJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], 163752f40e3SJed Brown (*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 1643a8779fbSJames Wright // *INDENT-ON* 1653a8779fbSJames Wright 1663a8779fbSJames Wright // Context 1673a8779fbSJames Wright NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 168bb8a0c61SJames Wright const CeedScalar *g = context->g; 169bb8a0c61SJames Wright const CeedScalar dt = context->dt; 1703a8779fbSJames Wright 1713a8779fbSJames Wright CeedPragmaSIMD 1723a8779fbSJames Wright // Quadrature Point Loop 1733a8779fbSJames Wright for (CeedInt i=0; i<Q; i++) { 174c1a52365SJed Brown CeedScalar U[5]; 175c1a52365SJed Brown for (int j=0; j<5; j++) U[j] = q[j][i]; 176c1a52365SJed Brown const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 177c1a52365SJed Brown State s = StateFromU(context, U, x_i); 178c1a52365SJed Brown 1793a8779fbSJames Wright // -- Interp-to-Interp q_data 1803a8779fbSJames Wright const CeedScalar wdetJ = q_data[0][i]; 1813a8779fbSJames Wright // -- Interp-to-Grad q_data 1823a8779fbSJames Wright // ---- Inverse of change of coordinate matrix: X_i,j 1833a8779fbSJames Wright // *INDENT-OFF* 18434ea8d65SJames Wright const CeedScalar dXdx[3][3] = {{q_data[1][i], q_data[2][i], q_data[3][i]}, 18534ea8d65SJames Wright {q_data[4][i], q_data[5][i], q_data[6][i]}, 18634ea8d65SJames Wright {q_data[7][i], q_data[8][i], q_data[9][i]} 1873a8779fbSJames Wright }; 1883a8779fbSJames Wright // *INDENT-ON* 189c1a52365SJed Brown State grad_s[3]; 190eef2387dSJed Brown for (CeedInt j=0; j<3; j++) { 1912f7ce6c1SJed Brown CeedScalar dx_i[3] = {0}, dU[5]; 1922556a851SJed Brown for (CeedInt k=0; k<5; k++) 1932556a851SJed Brown dU[k] = Grad_q[0][k][i] * dXdx[0][j] + 1942556a851SJed Brown Grad_q[1][k][i] * dXdx[1][j] + 1952556a851SJed Brown Grad_q[2][k][i] * dXdx[2][j]; 196c1a52365SJed Brown dx_i[j] = 1.; 1972f7ce6c1SJed Brown grad_s[j] = StateFromU_fwd(context, s, dU, x_i, dx_i); 198c1a52365SJed Brown } 199c1a52365SJed Brown 200c1a52365SJed Brown CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 201c1a52365SJed Brown KMStrainRate(grad_s, strain_rate); 202c1a52365SJed Brown NewtonianStress(context, strain_rate, kmstress); 203c1a52365SJed Brown KMUnpack(kmstress, stress); 204c1a52365SJed Brown ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 205c1a52365SJed Brown 206c1a52365SJed Brown StateConservative F_inviscid[3]; 207c1a52365SJed Brown FluxInviscid(context, s, F_inviscid); 208c1a52365SJed Brown 209c1a52365SJed Brown // Total flux 210c1a52365SJed Brown CeedScalar Flux[5][3]; 211d1b9ef12SLeila Ghaffari FluxTotal(F_inviscid, stress, Fe, Flux); 212c1a52365SJed Brown 213d1b9ef12SLeila Ghaffari for (CeedInt j=0; j<3; j++) 214d1b9ef12SLeila Ghaffari for (CeedInt k=0; k<5; k++) 215752f40e3SJed Brown Grad_v[j][k][i] = wdetJ * (dXdx[j][0] * Flux[k][0] + 216c1a52365SJed Brown dXdx[j][1] * Flux[k][1] + 217c1a52365SJed Brown dXdx[j][2] * Flux[k][2]); 218c1a52365SJed Brown 219c1a52365SJed Brown const CeedScalar body_force[5] = {0, s.U.density *g[0], s.U.density *g[1], s.U.density *g[2], 0}; 220c1a52365SJed Brown for (int j=0; j<5; j++) 221c1a52365SJed Brown v[j][i] = wdetJ * body_force[j]; 2223a8779fbSJames Wright 223d1b9ef12SLeila Ghaffari // -- Stabilization method: none (Galerkin), SU, or SUPG 224d1b9ef12SLeila Ghaffari CeedScalar Tau_d[3], stab[5][3], U_dot[5] = {0}; 225d1b9ef12SLeila Ghaffari Tau_diagPrim(context, s, dXdx, dt, Tau_d); 226d1b9ef12SLeila Ghaffari Stabilization(context, s, Tau_d, grad_s, U_dot, body_force, x_i, stab); 2273a8779fbSJames Wright 228493642f1SJames Wright for (CeedInt j=0; j<5; j++) 229493642f1SJames Wright for (CeedInt k=0; k<3; k++) 230752f40e3SJed Brown Grad_v[k][j][i] -= wdetJ*(stab[j][0] * dXdx[k][0] + 2313a8779fbSJames Wright stab[j][1] * dXdx[k][1] + 2323a8779fbSJames Wright stab[j][2] * dXdx[k][2]); 2333a8779fbSJames Wright 2343a8779fbSJames Wright } // End Quadrature Point Loop 2353a8779fbSJames Wright 2363a8779fbSJames Wright // Return 2373a8779fbSJames Wright return 0; 2383a8779fbSJames Wright } 2393a8779fbSJames Wright 2403a8779fbSJames Wright // ***************************************************************************** 2413a8779fbSJames Wright // This QFunction implements the Navier-Stokes equations (mentioned above) with 2423a8779fbSJames Wright // implicit time stepping method 2433a8779fbSJames Wright // 2443a8779fbSJames Wright // SU = Galerkin + grad(v) . ( Ai^T * Tau * (Aj q,j) ) 2453a8779fbSJames Wright // SUPG = Galerkin + grad(v) . ( Ai^T * Tau * (q_dot + Aj q,j - body force) ) 2463a8779fbSJames Wright // (diffussive terms will be added later) 2473a8779fbSJames Wright // 2483a8779fbSJames Wright // ***************************************************************************** 24976555becSJames Wright CEED_QFUNCTION_HELPER int IFunction_Newtonian(void *ctx, CeedInt Q, 25076555becSJames Wright const CeedScalar *const *in, CeedScalar *const *out, 25176555becSJames Wright StateFromQi_t StateFromQi, StateFromQi_fwd_t StateFromQi_fwd) { 2523a8779fbSJames Wright // *INDENT-OFF* 2533a8779fbSJames Wright // Inputs 2543a8779fbSJames Wright const CeedScalar (*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 255752f40e3SJed Brown (*Grad_q)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 2563a8779fbSJames Wright (*q_dot)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 2573a8779fbSJames Wright (*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 2583a8779fbSJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 2593a8779fbSJames Wright // Outputs 2603a8779fbSJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], 261752f40e3SJed Brown (*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1], 262752f40e3SJed Brown (*jac_data)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[2]; 2633a8779fbSJames Wright // *INDENT-ON* 2643a8779fbSJames Wright // Context 2653a8779fbSJames Wright NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 266bb8a0c61SJames Wright const CeedScalar *g = context->g; 267bb8a0c61SJames Wright const CeedScalar dt = context->dt; 2683a8779fbSJames Wright 2693a8779fbSJames Wright CeedPragmaSIMD 2703a8779fbSJames Wright // Quadrature Point Loop 2713a8779fbSJames Wright for (CeedInt i=0; i<Q; i++) { 27276555becSJames Wright CeedScalar qi[5]; 27376555becSJames Wright for (CeedInt j=0; j<5; j++) qi[j] = q[j][i]; 274c1a52365SJed Brown const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 27576555becSJames Wright State s = StateFromQi(context, qi, x_i); 276c1a52365SJed Brown 2773a8779fbSJames Wright // -- Interp-to-Interp q_data 2783a8779fbSJames Wright const CeedScalar wdetJ = q_data[0][i]; 2793a8779fbSJames Wright // -- Interp-to-Grad q_data 2803a8779fbSJames Wright // ---- Inverse of change of coordinate matrix: X_i,j 2813a8779fbSJames Wright // *INDENT-OFF* 28234ea8d65SJames Wright const CeedScalar dXdx[3][3] = {{q_data[1][i], q_data[2][i], q_data[3][i]}, 28334ea8d65SJames Wright {q_data[4][i], q_data[5][i], q_data[6][i]}, 28434ea8d65SJames Wright {q_data[7][i], q_data[8][i], q_data[9][i]} 2853a8779fbSJames Wright }; 2863a8779fbSJames Wright // *INDENT-ON* 287c1a52365SJed Brown State grad_s[3]; 288493642f1SJames Wright for (CeedInt j=0; j<3; j++) { 28976555becSJames Wright CeedScalar dx_i[3] = {0}, dqi[5]; 2902556a851SJed Brown for (CeedInt k=0; k<5; k++) 29176555becSJames Wright dqi[k] = Grad_q[0][k][i] * dXdx[0][j] + 2922556a851SJed Brown Grad_q[1][k][i] * dXdx[1][j] + 2932556a851SJed Brown Grad_q[2][k][i] * dXdx[2][j]; 294c1a52365SJed Brown dx_i[j] = 1.; 29576555becSJames Wright grad_s[j] = StateFromQi_fwd(context, s, dqi, x_i, dx_i); 2963a8779fbSJames Wright } 297c1a52365SJed Brown 298c1a52365SJed Brown CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 299c1a52365SJed Brown KMStrainRate(grad_s, strain_rate); 300c1a52365SJed Brown NewtonianStress(context, strain_rate, kmstress); 301c1a52365SJed Brown KMUnpack(kmstress, stress); 302c1a52365SJed Brown ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 303c1a52365SJed Brown 304c1a52365SJed Brown StateConservative F_inviscid[3]; 305c1a52365SJed Brown FluxInviscid(context, s, F_inviscid); 306c1a52365SJed Brown 307c1a52365SJed Brown // Total flux 308c1a52365SJed Brown CeedScalar Flux[5][3]; 309d1b9ef12SLeila Ghaffari FluxTotal(F_inviscid, stress, Fe, Flux); 310c1a52365SJed Brown 311d1b9ef12SLeila Ghaffari for (CeedInt j=0; j<3; j++) 312d1b9ef12SLeila Ghaffari for (CeedInt k=0; k<5; k++) 313752f40e3SJed Brown Grad_v[j][k][i] = -wdetJ * (dXdx[j][0] * Flux[k][0] + 314c1a52365SJed Brown dXdx[j][1] * Flux[k][1] + 315c1a52365SJed Brown dXdx[j][2] * Flux[k][2]); 316c1a52365SJed Brown 317c1a52365SJed Brown const CeedScalar body_force[5] = {0, s.U.density *g[0], s.U.density *g[1], s.U.density *g[2], 0}; 3183a8779fbSJames Wright 319d1b9ef12SLeila Ghaffari // -- Stabilization method: none (Galerkin), SU, or SUPG 32076555becSJames Wright CeedScalar Tau_d[3], stab[5][3], U_dot[5] = {0}, qi_dot[5], dx0[3] = {0}; 32176555becSJames Wright for (int j=0; j<5; j++) qi_dot[j] = q_dot[j][i]; 32276555becSJames Wright State s_dot = StateFromQi_fwd(context, s, qi_dot, x_i, dx0); 32376555becSJames Wright UnpackState_U(s_dot.U, U_dot); 32476555becSJames Wright 32576555becSJames Wright for (CeedInt j=0; j<5; j++) 32676555becSJames Wright v[j][i] = wdetJ * (U_dot[j] - body_force[j]); 327d1b9ef12SLeila Ghaffari Tau_diagPrim(context, s, dXdx, dt, Tau_d); 328d1b9ef12SLeila Ghaffari Stabilization(context, s, Tau_d, grad_s, U_dot, body_force, x_i, stab); 3293a8779fbSJames Wright 330493642f1SJames Wright for (CeedInt j=0; j<5; j++) 331493642f1SJames Wright for (CeedInt k=0; k<3; k++) 332752f40e3SJed Brown Grad_v[k][j][i] += wdetJ*(stab[j][0] * dXdx[k][0] + 3333a8779fbSJames Wright stab[j][1] * dXdx[k][1] + 3343a8779fbSJames Wright stab[j][2] * dXdx[k][2]); 335eef2387dSJed Brown 33676555becSJames Wright for (CeedInt j=0; j<5; j++) jac_data[j][i] = qi[j]; 337eef2387dSJed Brown for (CeedInt j=0; j<6; j++) jac_data[5+j][i] = kmstress[j]; 338eef2387dSJed Brown for (CeedInt j=0; j<3; j++) jac_data[5+6+j][i] = Tau_d[j]; 3393a8779fbSJames Wright 3403a8779fbSJames Wright } // End Quadrature Point Loop 3413a8779fbSJames Wright 3423a8779fbSJames Wright // Return 3433a8779fbSJames Wright return 0; 3443a8779fbSJames Wright } 345f0b65372SJed Brown 34676555becSJames Wright CEED_QFUNCTION(IFunction_Newtonian_Conserv)(void *ctx, CeedInt Q, 34776555becSJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 34876555becSJames Wright return IFunction_Newtonian(ctx, Q, in, out, StateFromU, StateFromU_fwd); 34976555becSJames Wright } 35076555becSJames Wright 35176555becSJames Wright CEED_QFUNCTION(IFunction_Newtonian_Prim)(void *ctx, CeedInt Q, 35276555becSJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 35376555becSJames Wright return IFunction_Newtonian(ctx, Q, in, out, StateFromY, StateFromY_fwd); 35476555becSJames Wright } 35576555becSJames Wright 356cbe60e31SLeila Ghaffari // ***************************************************************************** 35776555becSJames Wright // This QFunction implements the jacobian of the Navier-Stokes equations 358cbe60e31SLeila Ghaffari // for implicit time stepping method. 359cbe60e31SLeila Ghaffari // ***************************************************************************** 36076555becSJames Wright CEED_QFUNCTION_HELPER int IJacobian_Newtonian(void *ctx, CeedInt Q, 36176555becSJames Wright const CeedScalar *const *in, CeedScalar *const *out, 36276555becSJames Wright StateFromQi_t StateFromQi, StateFromQi_fwd_t StateFromQi_fwd) { 363f0b65372SJed Brown // *INDENT-OFF* 364f0b65372SJed Brown // Inputs 365f0b65372SJed Brown const CeedScalar (*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 366f0b65372SJed Brown (*Grad_dq)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 367f0b65372SJed Brown (*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 368f0b65372SJed Brown (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 369f0b65372SJed Brown (*jac_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 370f0b65372SJed Brown // Outputs 371f0b65372SJed Brown CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], 372f0b65372SJed Brown (*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 373f0b65372SJed Brown // *INDENT-ON* 374f0b65372SJed Brown // Context 375f0b65372SJed Brown NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 376f0b65372SJed Brown const CeedScalar *g = context->g; 377f0b65372SJed Brown 378f0b65372SJed Brown CeedPragmaSIMD 379f0b65372SJed Brown // Quadrature Point Loop 380f0b65372SJed Brown for (CeedInt i=0; i<Q; i++) { 381f0b65372SJed Brown // -- Interp-to-Interp q_data 382f0b65372SJed Brown const CeedScalar wdetJ = q_data[0][i]; 383f0b65372SJed Brown // -- Interp-to-Grad q_data 384f0b65372SJed Brown // ---- Inverse of change of coordinate matrix: X_i,j 385f0b65372SJed Brown // *INDENT-OFF* 38634ea8d65SJames Wright const CeedScalar dXdx[3][3] = {{q_data[1][i], q_data[2][i], q_data[3][i]}, 38734ea8d65SJames Wright {q_data[4][i], q_data[5][i], q_data[6][i]}, 38834ea8d65SJames Wright {q_data[7][i], q_data[8][i], q_data[9][i]} 389f0b65372SJed Brown }; 390f0b65372SJed Brown // *INDENT-ON* 391f0b65372SJed Brown 39276555becSJames Wright CeedScalar qi[5], kmstress[6], Tau_d[3] __attribute((unused)); 39376555becSJames Wright for (int j=0; j<5; j++) qi[j] = jac_data[j][i]; 394f0b65372SJed Brown for (int j=0; j<6; j++) kmstress[j] = jac_data[5+j][i]; 395f0b65372SJed Brown for (int j=0; j<3; j++) Tau_d[j] = jac_data[5+6+j][i]; 396f0b65372SJed Brown const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 39776555becSJames Wright State s = StateFromQi(context, qi, x_i); 398f0b65372SJed Brown 39976555becSJames Wright CeedScalar dqi[5], dx0[3] = {0}; 40076555becSJames Wright for (int j=0; j<5; j++) dqi[j] = dq[j][i]; 40176555becSJames Wright State ds = StateFromQi_fwd(context, s, dqi, x_i, dx0); 402f0b65372SJed Brown 403f0b65372SJed Brown State grad_ds[3]; 404f0b65372SJed Brown for (int j=0; j<3; j++) { 40576555becSJames Wright CeedScalar dqi_j[5]; 406d1b9ef12SLeila Ghaffari for (int k=0; k<5; k++) 40776555becSJames Wright dqi_j[k] = Grad_dq[0][k][i] * dXdx[0][j] + 408d1b9ef12SLeila Ghaffari Grad_dq[1][k][i] * dXdx[1][j] + 409d1b9ef12SLeila Ghaffari Grad_dq[2][k][i] * dXdx[2][j]; 41076555becSJames Wright grad_ds[j] = StateFromQi_fwd(context, s, dqi_j, x_i, dx0); 411f0b65372SJed Brown } 412f0b65372SJed Brown 413f0b65372SJed Brown CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 414f0b65372SJed Brown KMStrainRate(grad_ds, dstrain_rate); 415f0b65372SJed Brown NewtonianStress(context, dstrain_rate, dkmstress); 416f0b65372SJed Brown KMUnpack(dkmstress, dstress); 417f0b65372SJed Brown KMUnpack(kmstress, stress); 418f0b65372SJed Brown ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 419f0b65372SJed Brown 420f0b65372SJed Brown StateConservative dF_inviscid[3]; 421f0b65372SJed Brown FluxInviscid_fwd(context, s, ds, dF_inviscid); 422f0b65372SJed Brown 423f0b65372SJed Brown // Total flux 424f0b65372SJed Brown CeedScalar dFlux[5][3]; 425d1b9ef12SLeila Ghaffari FluxTotal(dF_inviscid, dstress, dFe, dFlux); 426f0b65372SJed Brown 427d1b9ef12SLeila Ghaffari for (int j=0; j<3; j++) 428d1b9ef12SLeila Ghaffari for (int k=0; k<5; k++) 429f0b65372SJed Brown Grad_v[j][k][i] = -wdetJ * (dXdx[j][0] * dFlux[k][0] + 430f0b65372SJed Brown dXdx[j][1] * dFlux[k][1] + 431f0b65372SJed Brown dXdx[j][2] * dFlux[k][2]); 432f0b65372SJed Brown 433f0b65372SJed Brown const CeedScalar dbody_force[5] = {0, ds.U.density *g[0], ds.U.density *g[1], ds.U.density *g[2], 0}; 43476555becSJames Wright CeedScalar dU[5] = {0.}; 43576555becSJames Wright UnpackState_U(ds.U, dU); 436f0b65372SJed Brown for (int j=0; j<5; j++) 437f0b65372SJed Brown v[j][i] = wdetJ * (context->ijacobian_time_shift * dU[j] - dbody_force[j]); 438f0b65372SJed Brown 439d1b9ef12SLeila Ghaffari // -- Stabilization method: none (Galerkin), SU, or SUPG 440d1b9ef12SLeila Ghaffari CeedScalar dstab[5][3], U_dot[5] = {0}; 441d1b9ef12SLeila Ghaffari for (CeedInt j=0; j<5; j++) U_dot[j] = context->ijacobian_time_shift * dU[j]; 442d1b9ef12SLeila Ghaffari Stabilization(context, s, Tau_d, grad_ds, U_dot, dbody_force, x_i, dstab); 443d1b9ef12SLeila Ghaffari 444f0b65372SJed Brown for (int j=0; j<5; j++) 445f0b65372SJed Brown for (int k=0; k<3; k++) 446f0b65372SJed Brown Grad_v[k][j][i] += wdetJ*(dstab[j][0] * dXdx[k][0] + 447f0b65372SJed Brown dstab[j][1] * dXdx[k][1] + 448f0b65372SJed Brown dstab[j][2] * dXdx[k][2]); 449f0b65372SJed Brown 450f0b65372SJed Brown } // End Quadrature Point Loop 451f0b65372SJed Brown return 0; 452f0b65372SJed Brown } 4538085925cSJames Wright 45476555becSJames Wright CEED_QFUNCTION(IJacobian_Newtonian_Conserv)(void *ctx, CeedInt Q, 45576555becSJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 45676555becSJames Wright return IJacobian_Newtonian(ctx, Q, in, out, StateFromU, StateFromU_fwd); 45776555becSJames Wright } 45876555becSJames Wright 45976555becSJames Wright CEED_QFUNCTION(IJacobian_Newtonian_Prim)(void *ctx, CeedInt Q, 46076555becSJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 46176555becSJames Wright return IJacobian_Newtonian(ctx, Q, in, out, StateFromY, StateFromY_fwd); 46276555becSJames Wright } 46376555becSJames Wright 464d1b9ef12SLeila Ghaffari // ***************************************************************************** 4658085925cSJames Wright // Compute boundary integral (ie. for strongly set inflows) 466d1b9ef12SLeila Ghaffari // ***************************************************************************** 467d4559bbeSJames Wright CEED_QFUNCTION_HELPER int BoundaryIntegral(void *ctx, CeedInt Q, 468d4559bbeSJames Wright const CeedScalar *const *in, CeedScalar *const *out, 469d4559bbeSJames Wright StateFromQi_t StateFromQi, StateFromQi_fwd_t StateFromQi_fwd) { 4708085925cSJames Wright 4718085925cSJames Wright //*INDENT-OFF* 4728085925cSJames Wright const CeedScalar (*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 473d3b25f3aSJames Wright (*Grad_q)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 474d3b25f3aSJames Wright (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 475d3b25f3aSJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; 4768085925cSJames Wright 47768ae065aSJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA]) out[0], 47868ae065aSJames Wright (*jac_data_sur)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA]) out[1]; 4798085925cSJames Wright 4808085925cSJames Wright //*INDENT-ON* 4818085925cSJames Wright 482d3b25f3aSJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext) ctx; 483d3b25f3aSJames Wright const bool is_implicit = context->is_implicit; 4848085925cSJames Wright 4858085925cSJames Wright CeedPragmaSIMD 4868085925cSJames Wright for(CeedInt i=0; i<Q; i++) { 487d3b25f3aSJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 48841e73928SJames Wright const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 48941e73928SJames Wright State s = StateFromQi(context, qi, x_i); 4908085925cSJames Wright 4918085925cSJames Wright const CeedScalar wdetJb = (is_implicit ? -1. : 1.) * q_data_sur[0][i]; 492c5740391SJames Wright // ---- Normal vector 4938085925cSJames Wright const CeedScalar norm[3] = {q_data_sur[1][i], 4948085925cSJames Wright q_data_sur[2][i], 4958085925cSJames Wright q_data_sur[3][i] 4968085925cSJames Wright }; 4978085925cSJames Wright 498d3b25f3aSJames Wright const CeedScalar dXdx[2][3] = { 499d3b25f3aSJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 500d3b25f3aSJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 501d3b25f3aSJames Wright }; 5028085925cSJames Wright 503d3b25f3aSJames Wright State grad_s[3]; 504d3b25f3aSJames Wright for (CeedInt j=0; j<3; j++) { 50541e73928SJames Wright CeedScalar dx_i[3] = {0}, dqi[5]; 506d3b25f3aSJames Wright for (CeedInt k=0; k<5; k++) 50741e73928SJames Wright dqi[k] = Grad_q[0][k][i] * dXdx[0][j] + 508d3b25f3aSJames Wright Grad_q[1][k][i] * dXdx[1][j]; 509d3b25f3aSJames Wright dx_i[j] = 1.; 51041e73928SJames Wright grad_s[j] = StateFromQi_fwd(context, s, dqi, x_i, dx_i); 511d3b25f3aSJames Wright } 5128085925cSJames Wright 513d3b25f3aSJames Wright CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 514d3b25f3aSJames Wright KMStrainRate(grad_s, strain_rate); 515d3b25f3aSJames Wright NewtonianStress(context, strain_rate, kmstress); 516d3b25f3aSJames Wright KMUnpack(kmstress, stress); 517d3b25f3aSJames Wright ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 518d3b25f3aSJames Wright 519d3b25f3aSJames Wright StateConservative F_inviscid[3]; 520d3b25f3aSJames Wright FluxInviscid(context, s, F_inviscid); 521d3b25f3aSJames Wright 522c5740391SJames Wright CeedScalar Flux[5]; 523c5740391SJames Wright FluxTotal_Boundary(F_inviscid, stress, Fe, norm, Flux); 524d3b25f3aSJames Wright 525c5740391SJames Wright for (CeedInt j=0; j<5; j++) v[j][i] = -wdetJb * Flux[j]; 5268085925cSJames Wright 527c5740391SJames Wright for (int j=0; j<5; j++) jac_data_sur[j][i] = qi[j]; 52868ae065aSJames Wright for (int j=0; j<6; j++) jac_data_sur[5+j][i] = kmstress[j]; 5298085925cSJames Wright } 5308085925cSJames Wright return 0; 5318085925cSJames Wright } 5328085925cSJames Wright 533d4559bbeSJames Wright CEED_QFUNCTION(BoundaryIntegral_Conserv)(void *ctx, CeedInt Q, 534d4559bbeSJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 535d4559bbeSJames Wright return BoundaryIntegral(ctx, Q, in, out, StateFromU, StateFromU_fwd); 536d4559bbeSJames Wright } 537d4559bbeSJames Wright 538d4559bbeSJames Wright CEED_QFUNCTION(BoundaryIntegral_Prim)(void *ctx, CeedInt Q, 539d4559bbeSJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 540d4559bbeSJames Wright return BoundaryIntegral(ctx, Q, in, out, StateFromY, StateFromY_fwd); 541d4559bbeSJames Wright } 542d4559bbeSJames Wright 543d1b9ef12SLeila Ghaffari // ***************************************************************************** 54468ae065aSJames Wright // Jacobian for "set nothing" boundary integral 545d1b9ef12SLeila Ghaffari // ***************************************************************************** 546d4559bbeSJames Wright CEED_QFUNCTION_HELPER int BoundaryIntegral_Jacobian(void *ctx, CeedInt Q, 547d4559bbeSJames Wright const CeedScalar *const *in, CeedScalar *const *out, 548d4559bbeSJames Wright StateFromQi_t StateFromQi, StateFromQi_fwd_t StateFromQi_fwd) { 54968ae065aSJames Wright // *INDENT-OFF* 55068ae065aSJames Wright // Inputs 55168ae065aSJames Wright const CeedScalar (*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 55268ae065aSJames Wright (*Grad_dq)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 55368ae065aSJames Wright (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 55468ae065aSJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 55568ae065aSJames Wright (*jac_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 55668ae065aSJames Wright // Outputs 55768ae065aSJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 55868ae065aSJames Wright // *INDENT-ON* 55968ae065aSJames Wright 56068ae065aSJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 56168ae065aSJames Wright const bool implicit = context->is_implicit; 56268ae065aSJames Wright 56368ae065aSJames Wright CeedPragmaSIMD 56468ae065aSJames Wright // Quadrature Point Loop 56568ae065aSJames Wright for (CeedInt i=0; i<Q; i++) { 56668ae065aSJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 56768ae065aSJames Wright const CeedScalar wdetJb = (implicit ? -1. : 1.) * q_data_sur[0][i]; 56868ae065aSJames Wright const CeedScalar norm[3] = {q_data_sur[1][i], 56968ae065aSJames Wright q_data_sur[2][i], 57068ae065aSJames Wright q_data_sur[3][i] 57168ae065aSJames Wright }; 57268ae065aSJames Wright const CeedScalar dXdx[2][3] = { 57368ae065aSJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 57468ae065aSJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 57568ae065aSJames Wright }; 57668ae065aSJames Wright 57741e73928SJames Wright CeedScalar qi[5], kmstress[6], dqi[5], dx_i[3] = {0.}; 57841e73928SJames Wright for (int j=0; j<5; j++) qi[j] = jac_data_sur[j][i]; 57968ae065aSJames Wright for (int j=0; j<6; j++) kmstress[j] = jac_data_sur[5+j][i]; 58041e73928SJames Wright for (int j=0; j<5; j++) dqi[j] = dq[j][i]; 5813934e2b1SJames Wright 58241e73928SJames Wright State s = StateFromQi(context, qi, x_i); 58341e73928SJames Wright State ds = StateFromQi_fwd(context, s, dqi, x_i, dx_i); 58468ae065aSJames Wright 58568ae065aSJames Wright State grad_ds[3]; 58668ae065aSJames Wright for (CeedInt j=0; j<3; j++) { 58741e73928SJames Wright CeedScalar dx_i[3] = {0}, dqi_j[5]; 58868ae065aSJames Wright for (CeedInt k=0; k<5; k++) 58941e73928SJames Wright dqi_j[k] = Grad_dq[0][k][i] * dXdx[0][j] + 59068ae065aSJames Wright Grad_dq[1][k][i] * dXdx[1][j]; 59168ae065aSJames Wright dx_i[j] = 1.; 59241e73928SJames Wright grad_ds[j] = StateFromQi_fwd(context, s, dqi_j, x_i, dx_i); 59368ae065aSJames Wright } 59468ae065aSJames Wright 59568ae065aSJames Wright CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 59668ae065aSJames Wright KMStrainRate(grad_ds, dstrain_rate); 59768ae065aSJames Wright NewtonianStress(context, dstrain_rate, dkmstress); 59868ae065aSJames Wright KMUnpack(dkmstress, dstress); 59968ae065aSJames Wright KMUnpack(kmstress, stress); 60068ae065aSJames Wright ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 60168ae065aSJames Wright 60268ae065aSJames Wright StateConservative dF_inviscid[3]; 60368ae065aSJames Wright FluxInviscid_fwd(context, s, ds, dF_inviscid); 60468ae065aSJames Wright 605c5740391SJames Wright CeedScalar dFlux[5]; 606c5740391SJames Wright FluxTotal_Boundary(dF_inviscid, dstress, dFe, norm, dFlux); 60768ae065aSJames Wright 608c5740391SJames Wright for (int j=0; j<5; j++) v[j][i] = -wdetJb * dFlux[j]; 60968ae065aSJames Wright } // End Quadrature Point Loop 61068ae065aSJames Wright return 0; 61168ae065aSJames Wright } 61268ae065aSJames Wright 613d4559bbeSJames Wright CEED_QFUNCTION(BoundaryIntegral_Jacobian_Conserv)(void *ctx, CeedInt Q, 614d4559bbeSJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 615d4559bbeSJames Wright return BoundaryIntegral_Jacobian(ctx, Q, in, out, StateFromU, StateFromU_fwd); 616d4559bbeSJames Wright } 617d4559bbeSJames Wright 618d4559bbeSJames Wright CEED_QFUNCTION(BoundaryIntegral_Jacobian_Prim)(void *ctx, CeedInt Q, 619d4559bbeSJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 620d4559bbeSJames Wright return BoundaryIntegral_Jacobian(ctx, Q, in, out, StateFromY, StateFromY_fwd); 621d4559bbeSJames Wright } 622d4559bbeSJames Wright 623d1b9ef12SLeila Ghaffari // ***************************************************************************** 62404b9037bSJames Wright // Outflow boundary condition, weakly setting a constant pressure 625d1b9ef12SLeila Ghaffari // ***************************************************************************** 626d4559bbeSJames Wright CEED_QFUNCTION_HELPER int PressureOutflow(void *ctx, CeedInt Q, 627d4559bbeSJames Wright const CeedScalar *const *in, CeedScalar *const *out, 628d4559bbeSJames Wright StateFromQi_t StateFromQi, StateFromQi_fwd_t StateFromQi_fwd) { 62904b9037bSJames Wright // *INDENT-OFF* 63004b9037bSJames Wright // Inputs 63104b9037bSJames Wright const CeedScalar (*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 63225bfcc41SJames Wright (*Grad_q)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 63325bfcc41SJames Wright (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 63425bfcc41SJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; 63504b9037bSJames Wright // Outputs 63604b9037bSJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], 63704b9037bSJames Wright (*jac_data_sur)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[1]; 63804b9037bSJames Wright // *INDENT-ON* 63904b9037bSJames Wright 64004b9037bSJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 64104b9037bSJames Wright const bool implicit = context->is_implicit; 64204b9037bSJames Wright const CeedScalar P0 = context->P0; 64304b9037bSJames Wright 64404b9037bSJames Wright CeedPragmaSIMD 64504b9037bSJames Wright // Quadrature Point Loop 64604b9037bSJames Wright for (CeedInt i=0; i<Q; i++) { 64704b9037bSJames Wright // Setup 64804b9037bSJames Wright // -- Interp in 64925bfcc41SJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 65041e73928SJames Wright const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 65141e73928SJames Wright State s = StateFromQi(context, qi, x_i); 65225bfcc41SJames Wright s.Y.pressure = P0; 65304b9037bSJames Wright 65404b9037bSJames Wright // -- Interp-to-Interp q_data 65504b9037bSJames Wright // For explicit mode, the surface integral is on the RHS of ODE q_dot = f(q). 65604b9037bSJames Wright // For implicit mode, it gets pulled to the LHS of implicit ODE/DAE g(q_dot, q). 65704b9037bSJames Wright // We can effect this by swapping the sign on this weight 65804b9037bSJames Wright const CeedScalar wdetJb = (implicit ? -1. : 1.) * q_data_sur[0][i]; 65904b9037bSJames Wright 660c5740391SJames Wright // ---- Normal vector 661d4559bbeSJames Wright const CeedScalar norm[3] = {q_data_sur[1][i], q_data_sur[2][i], q_data_sur[3][i]}; 66204b9037bSJames Wright 66325bfcc41SJames Wright const CeedScalar dXdx[2][3] = { 66425bfcc41SJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 66525bfcc41SJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 66625bfcc41SJames Wright }; 66704b9037bSJames Wright 66825bfcc41SJames Wright State grad_s[3]; 66925bfcc41SJames Wright for (CeedInt j=0; j<3; j++) { 67041e73928SJames Wright CeedScalar dx_i[3] = {0}, dqi[5]; 67125bfcc41SJames Wright for (CeedInt k=0; k<5; k++) 67241e73928SJames Wright dqi[k] = Grad_q[0][k][i] * dXdx[0][j] + 67325bfcc41SJames Wright Grad_q[1][k][i] * dXdx[1][j]; 67425bfcc41SJames Wright dx_i[j] = 1.; 67541e73928SJames Wright grad_s[j] = StateFromQi_fwd(context, s, dqi, x_i, dx_i); 67625bfcc41SJames Wright } 67725bfcc41SJames Wright 67825bfcc41SJames Wright CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 67925bfcc41SJames Wright KMStrainRate(grad_s, strain_rate); 68025bfcc41SJames Wright NewtonianStress(context, strain_rate, kmstress); 68125bfcc41SJames Wright KMUnpack(kmstress, stress); 68225bfcc41SJames Wright ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 68325bfcc41SJames Wright 68425bfcc41SJames Wright StateConservative F_inviscid[3]; 68525bfcc41SJames Wright FluxInviscid(context, s, F_inviscid); 68625bfcc41SJames Wright 687c5740391SJames Wright CeedScalar Flux[5]; 688c5740391SJames Wright FluxTotal_Boundary(F_inviscid, stress, Fe, norm, Flux); 68904b9037bSJames Wright 690c5740391SJames Wright for (CeedInt j=0; j<5; j++) v[j][i] = -wdetJb * Flux[j]; 69104b9037bSJames Wright 69204b9037bSJames Wright // Save values for Jacobian 693c5740391SJames Wright for (int j=0; j<5; j++) jac_data_sur[j][i] = qi[j]; 694b01ba163SJames Wright for (int j=0; j<6; j++) jac_data_sur[5+j][i] = kmstress[j]; 69504b9037bSJames Wright } // End Quadrature Point Loop 69604b9037bSJames Wright return 0; 69704b9037bSJames Wright } 69804b9037bSJames Wright 699d4559bbeSJames Wright CEED_QFUNCTION(PressureOutflow_Conserv)(void *ctx, CeedInt Q, 700d4559bbeSJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 701d4559bbeSJames Wright return PressureOutflow(ctx, Q, in, out, StateFromU, StateFromU_fwd); 702d4559bbeSJames Wright } 703d4559bbeSJames Wright 704d4559bbeSJames Wright CEED_QFUNCTION(PressureOutflow_Prim)(void *ctx, CeedInt Q, 705d4559bbeSJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 706d4559bbeSJames Wright return PressureOutflow(ctx, Q, in, out, StateFromY, StateFromY_fwd); 707d4559bbeSJames Wright } 708d4559bbeSJames Wright 709d1b9ef12SLeila Ghaffari // ***************************************************************************** 71004b9037bSJames Wright // Jacobian for weak-pressure outflow boundary condition 711d1b9ef12SLeila Ghaffari // ***************************************************************************** 712d4559bbeSJames Wright CEED_QFUNCTION_HELPER int PressureOutflow_Jacobian(void *ctx, CeedInt Q, 713d4559bbeSJames Wright const CeedScalar *const *in, CeedScalar *const *out, 714d4559bbeSJames Wright StateFromQi_t StateFromQi, StateFromQi_fwd_t StateFromQi_fwd) { 71504b9037bSJames Wright // *INDENT-OFF* 71604b9037bSJames Wright // Inputs 71704b9037bSJames Wright const CeedScalar (*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 718b01ba163SJames Wright (*Grad_dq)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 719b01ba163SJames Wright (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 720b01ba163SJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 721b01ba163SJames Wright (*jac_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 72204b9037bSJames Wright // Outputs 72304b9037bSJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 72404b9037bSJames Wright // *INDENT-ON* 72504b9037bSJames Wright 72604b9037bSJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 72704b9037bSJames Wright const bool implicit = context->is_implicit; 72804b9037bSJames Wright 72904b9037bSJames Wright CeedPragmaSIMD 73004b9037bSJames Wright // Quadrature Point Loop 73104b9037bSJames Wright for (CeedInt i=0; i<Q; i++) { 732b01ba163SJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 73304b9037bSJames Wright const CeedScalar wdetJb = (implicit ? -1. : 1.) * q_data_sur[0][i]; 734d4559bbeSJames Wright const CeedScalar norm[3] = {q_data_sur[1][i], q_data_sur[2][i], q_data_sur[3][i]}; 735b01ba163SJames Wright const CeedScalar dXdx[2][3] = { 736b01ba163SJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 737b01ba163SJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 738b01ba163SJames Wright }; 739b01ba163SJames Wright 74041e73928SJames Wright CeedScalar qi[5], kmstress[6], dqi[5], dx_i[3] = {0.}; 74141e73928SJames Wright for (int j=0; j<5; j++) qi[j] = jac_data_sur[j][i]; 742b01ba163SJames Wright for (int j=0; j<6; j++) kmstress[j] = jac_data_sur[5+j][i]; 74341e73928SJames Wright for (int j=0; j<5; j++) dqi[j] = dq[j][i]; 7443934e2b1SJames Wright 74541e73928SJames Wright State s = StateFromQi(context, qi, x_i); 74641e73928SJames Wright State ds = StateFromQi_fwd(context, s, dqi, x_i, dx_i); 747b01ba163SJames Wright s.Y.pressure = context->P0; 748b01ba163SJames Wright ds.Y.pressure = 0.; 749b01ba163SJames Wright 750b01ba163SJames Wright State grad_ds[3]; 751b01ba163SJames Wright for (CeedInt j=0; j<3; j++) { 75241e73928SJames Wright CeedScalar dx_i[3] = {0}, dqi_j[5]; 753b01ba163SJames Wright for (CeedInt k=0; k<5; k++) 75441e73928SJames Wright dqi_j[k] = Grad_dq[0][k][i] * dXdx[0][j] + 755b01ba163SJames Wright Grad_dq[1][k][i] * dXdx[1][j]; 756b01ba163SJames Wright dx_i[j] = 1.; 75741e73928SJames Wright grad_ds[j] = StateFromQi_fwd(context, s, dqi_j, x_i, dx_i); 758b01ba163SJames Wright } 759b01ba163SJames Wright 760b01ba163SJames Wright CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 761b01ba163SJames Wright KMStrainRate(grad_ds, dstrain_rate); 762b01ba163SJames Wright NewtonianStress(context, dstrain_rate, dkmstress); 763b01ba163SJames Wright KMUnpack(dkmstress, dstress); 764b01ba163SJames Wright KMUnpack(kmstress, stress); 765b01ba163SJames Wright ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 76604b9037bSJames Wright 767e6b47afbSJames Wright StateConservative dF_inviscid[3]; 768e6b47afbSJames Wright FluxInviscid_fwd(context, s, ds, dF_inviscid); 76904b9037bSJames Wright 770c5740391SJames Wright CeedScalar dFlux[5]; 771c5740391SJames Wright FluxTotal_Boundary(dF_inviscid, dstress, dFe, norm, dFlux); 772e6b47afbSJames Wright 773c5740391SJames Wright for (int j=0; j<5; j++) v[j][i] = -wdetJb * dFlux[j]; 77404b9037bSJames Wright } // End Quadrature Point Loop 77504b9037bSJames Wright return 0; 77604b9037bSJames Wright } 77704b9037bSJames Wright 778d4559bbeSJames Wright CEED_QFUNCTION(PressureOutflow_Jacobian_Conserv)(void *ctx, CeedInt Q, 779d4559bbeSJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 780d4559bbeSJames Wright return PressureOutflow_Jacobian(ctx, Q, in, out, StateFromU, StateFromU_fwd); 781d4559bbeSJames Wright } 782d4559bbeSJames Wright 783d4559bbeSJames Wright CEED_QFUNCTION(PressureOutflow_Jacobian_Prim)(void *ctx, CeedInt Q, 784d4559bbeSJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 785d4559bbeSJames Wright return PressureOutflow_Jacobian(ctx, Q, in, out, StateFromY, StateFromY_fwd); 786d4559bbeSJames Wright } 787d4559bbeSJames Wright 788*7b530f2aSAdelekeBankole // ***************************************************************************** 789*7b530f2aSAdelekeBankole // Harten Lax VanLeer (HLL) approximate Riemann solver. 790*7b530f2aSAdelekeBankole // Taking in two states (left, right) and returns RiemannFlux_HLL 791*7b530f2aSAdelekeBankole // ***************************************************************************** 792*7b530f2aSAdelekeBankole CEED_QFUNCTION_HELPER StateConservative Harten_Lax_VanLeer_Flux(NewtonianIdealGasContext gas, 793*7b530f2aSAdelekeBankole State left, State right, const CeedScalar normal[3]) { 794*7b530f2aSAdelekeBankole 795*7b530f2aSAdelekeBankole StateConservative flux_left = FluxInviscidDotNormal(gas, left, normal); 796*7b530f2aSAdelekeBankole StateConservative flux_right = FluxInviscidDotNormal(gas, right, normal); 797*7b530f2aSAdelekeBankole StateConservative RiemannFlux_HLL; 798*7b530f2aSAdelekeBankole // compute speed. 799*7b530f2aSAdelekeBankole // TODO: This is only stable for subsonic flows. We need to include a Roe average 800*7b530f2aSAdelekeBankole // or other technique to handle sonic flows. Stability requires that these speed estimates 801*7b530f2aSAdelekeBankole // are *at least* as fast as the physical wave speeds. 802*7b530f2aSAdelekeBankole CeedScalar s_left = Dot3(left.Y.velocity, normal) - SoundSpeed(gas, left.Y.temperature); 803*7b530f2aSAdelekeBankole CeedScalar s_right = Dot3(right.Y.velocity, normal) + SoundSpeed(gas, right.Y.temperature); 804*7b530f2aSAdelekeBankole // Compute HLL flux 805*7b530f2aSAdelekeBankole if (0 <= s_left) { 806*7b530f2aSAdelekeBankole RiemannFlux_HLL = flux_left; 807*7b530f2aSAdelekeBankole } else if (s_right <= 0) { 808*7b530f2aSAdelekeBankole RiemannFlux_HLL = flux_right; 809*7b530f2aSAdelekeBankole } else { 810*7b530f2aSAdelekeBankole RiemannFlux_HLL.density = 811*7b530f2aSAdelekeBankole (s_right * flux_left.density - s_left * flux_right.density + 812*7b530f2aSAdelekeBankole s_left * s_right * (right.U.density - left.U.density)) / 813*7b530f2aSAdelekeBankole (s_right - s_left); 814*7b530f2aSAdelekeBankole for (int i = 0; i < 3; i++) 815*7b530f2aSAdelekeBankole RiemannFlux_HLL.momentum[i] = 816*7b530f2aSAdelekeBankole (s_right * flux_left.momentum[i] - s_left * flux_right.momentum[i] + 817*7b530f2aSAdelekeBankole s_left * s_right * (right.U.momentum[i] - left.U.momentum[i])) / 818*7b530f2aSAdelekeBankole (s_right - s_left); 819*7b530f2aSAdelekeBankole RiemannFlux_HLL.E_total = 820*7b530f2aSAdelekeBankole (s_right * flux_left.E_total - s_left * flux_right.E_total + 821*7b530f2aSAdelekeBankole s_left * s_right * (right.U.E_total - left.U.E_total)) / 822*7b530f2aSAdelekeBankole (s_right - s_left); 823*7b530f2aSAdelekeBankole } 824*7b530f2aSAdelekeBankole // Return 825*7b530f2aSAdelekeBankole return RiemannFlux_HLL; 826*7b530f2aSAdelekeBankole } 827*7b530f2aSAdelekeBankole 8283a8779fbSJames Wright #endif // newtonian_h 829